From 19599e5140e329c93f9a5c3fed5c3683e66b351a Mon Sep 17 00:00:00 2001 From: Ryan Rondeau Date: Wed, 11 Dec 2024 08:35:38 -0800 Subject: [PATCH 1/4] feat: CE-239 Server-side Clustering (#799) --- backend/package-lock.json | 841 ++++++------------ backend/package.json | 3 + .../complaints/complaint-search-parameters.ts | 7 + .../models/complaints/map-search-results.ts | 12 +- .../code-table/code-table.controller.spec.ts | 2 +- .../src/v1/complaint/complaint.controller.ts | 20 +- .../v1/complaint/complaint.service.spec.ts | 49 +- backend/src/v1/complaint/complaint.service.ts | 302 ++++--- .../v1/office/office.controller.v2.spec.ts | 2 +- backend/src/v1/officer/officer.service.ts | 3 +- .../src/v1/person/person.controller.spec.ts | 2 +- backend/test/app.e2e-spec.ts | 2 +- backend/tsconfig.json | 1 + .../backend/templates/deployment.yaml | 4 +- .../cypress/e2e/complaints-on-map-view.cy.ts | 8 +- frontend/package-lock.json | 530 +++++------ frontend/package.json | 3 +- .../app/components/common/search-input.tsx | 9 +- .../complaints/complaint-filter.tsx | 2 +- ...plaint-map-with-server-side-clustering.tsx | 174 ++++ .../containers/complaints/complaint-map.tsx | 126 --- .../containers/complaints/complaints.tsx | 6 +- .../leaflet-map-with-multiple-points.tsx | 142 --- ...eaflet-map-with-server-side-clustering.tsx | 226 +++++ .../src/app/components/mapping/spiderfy.tsx | 70 ++ frontend/src/app/store/migrations.ts | 2 + .../src/app/store/migrations/migration-25.ts | 12 + frontend/src/app/store/reducers/complaints.ts | 124 +-- frontend/src/app/store/store.ts | 2 +- .../complaint-request-payload.ts | 5 + .../src/app/types/complaints/map-return.ts | 13 +- .../src/app/types/state/complaint-state.ts | 6 +- frontend/src/assets/sass/maps.scss | 48 + webeoc/package-lock.json | 4 +- webeoc/test/app.e2e-spec.ts | 2 +- 35 files changed, 1348 insertions(+), 1416 deletions(-) create mode 100644 frontend/src/app/components/containers/complaints/complaint-map-with-server-side-clustering.tsx delete mode 100644 frontend/src/app/components/containers/complaints/complaint-map.tsx delete mode 100644 frontend/src/app/components/mapping/leaflet-map-with-multiple-points.tsx create mode 100644 frontend/src/app/components/mapping/leaflet-map-with-server-side-clustering.tsx create mode 100644 frontend/src/app/components/mapping/spiderfy.tsx create mode 100644 frontend/src/app/store/migrations/migration-25.ts diff --git a/backend/package-lock.json b/backend/package-lock.json index 93694c69e..bfa695027 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -1,12 +1,12 @@ { "name": "nr-compliance-enforcement", - "version": "0.0.1", + "version": "0.28.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "nr-compliance-enforcement", - "version": "0.0.1", + "version": "0.28.1", "license": "Apache-2.0", "dependencies": { "@automapper/classes": "^8.8.1", @@ -35,6 +35,7 @@ "date-fns-tz": "^3.1.3", "dotenv": "^16.0.1", "escape-html": "^1.0.3", + "fix-esm": "^1.0.1", "form-data": "^4.0.0", "geojson": "^0.5.0", "jest-mock": "^29.6.1", @@ -51,6 +52,7 @@ "reflect-metadata": "^0.1.13", "rimraf": "^4.0.0", "rxjs": "^7.8.0", + "supercluster": "^7.1.5", "swagger-ui-express": "^4.6.0", "typeorm": "^0.3.14", "winston": "^3.9.0" @@ -61,6 +63,7 @@ "@types/jest": "^29.5.1", "@types/node": "^18.11.18", "@types/passport-jwt": "^3.0.8", + "@types/supercluster": "^7.1.3", "@types/supertest": "^2.0.11", "@typescript-eslint/eslint-plugin": "^5.48.2", "@typescript-eslint/parser": "^5.48.2", @@ -101,7 +104,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", - "dev": true, "dependencies": { "@jridgewell/gen-mapping": "^0.1.0", "@jridgewell/trace-mapping": "^0.3.9" @@ -311,86 +313,22 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", - "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", "dependencies": { - "@babel/highlight": "^7.23.4", - "chalk": "^2.4.2" + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/code-frame/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/code-frame/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" - }, - "node_modules/@babel/code-frame/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/code-frame/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/@babel/compat-data": { "version": "7.23.5", "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==", - "dev": true, "engines": { "node": ">=6.9.0" } @@ -399,7 +337,6 @@ "version": "7.23.6", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.6.tgz", "integrity": "sha512-FxpRyGjrMJXh7X3wGLGhNDCRiwpWEF74sKjTLDJSG5Kyvow3QZaG0Adbqzi9ZrVjTWpsX+2cxWXD71NMg93kdw==", - "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.23.5", @@ -429,35 +366,33 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, "bin": { "semver": "bin/semver.js" } }, "node_modules/@babel/generator": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", - "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", - "dev": true, + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.2.tgz", + "integrity": "sha512-zevQbhbau95nkoxSq3f/DC/SC+EEOUZd3DYqfSkMhY2/wfSeaHV1Ew4vk8e+x8lja31IbyuUa2uQ3JONqKbysw==", "dependencies": { - "@babel/types": "^7.23.6", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", - "jsesc": "^2.5.1" + "@babel/parser": "^7.26.2", + "@babel/types": "^7.26.0", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^3.0.2" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/generator/node_modules/@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dev": true, + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "dependencies": { - "@jridgewell/set-array": "^1.0.1", + "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { "node": ">=6.0.0" @@ -467,7 +402,6 @@ "version": "7.23.6", "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", - "dev": true, "dependencies": { "@babel/compat-data": "^7.23.5", "@babel/helper-validator-option": "^7.23.5", @@ -483,68 +417,30 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, "bin": { "semver": "bin/semver.js" } }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", - "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-function-name": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", - "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", - "dev": true, - "dependencies": { - "@babel/template": "^7.22.15", - "@babel/types": "^7.23.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", - "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-module-imports": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", - "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", - "dev": true, + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", + "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", "dependencies": { - "@babel/types": "^7.22.15" + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", - "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", - "dev": true, + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", + "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", "dependencies": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-module-imports": "^7.22.15", - "@babel/helper-simple-access": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/helper-validator-identifier": "^7.22.20" + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -554,51 +450,37 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", - "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", - "dev": true, + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.9.tgz", + "integrity": "sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-simple-access": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", - "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", - "dev": true, + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.25.9.tgz", + "integrity": "sha512-c6WHXuiaRsJTyHYLJV75t9IqsmTbItYfdj99PnzYGQZkYKvan5/2jKJ7gu31J3/BJ/A18grImSPModuyG/Eo0Q==", "dependencies": { - "@babel/types": "^7.22.5" + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-string-parser": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", - "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", - "dev": true, + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", "engines": { "node": ">=6.9.0" } @@ -607,7 +489,6 @@ "version": "7.23.5", "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", - "dev": true, "engines": { "node": ">=6.9.0" } @@ -616,7 +497,6 @@ "version": "7.23.6", "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.6.tgz", "integrity": "sha512-wCfsbN4nBidDRhpDhvcKlzHWCTlgJYUUdSJfzXb2NuBssDSIjc3xcb+znA7l+zYsFljAcGM0aFkN40cR3lXiGA==", - "dev": true, "dependencies": { "@babel/template": "^7.22.15", "@babel/traverse": "^7.23.6", @@ -626,93 +506,34 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/highlight": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", - "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", - "dependencies": { - "@babel/helper-validator-identifier": "^7.22.20", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "node_modules/@babel/parser": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.2.tgz", + "integrity": "sha512-DWMCZH9WA4Maitz2q21SRKHo9QXZxkDsbNZoVD62gusNtNBBqDg9i7uOhASfTfIGNzW+O+r7+jAlM8dwphcJKQ==", "dependencies": { - "color-convert": "^1.9.0" + "@babel/types": "^7.26.0" }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "bin": { + "parser": "bin/babel-parser.js" }, "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/highlight/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" - }, - "node_modules/@babel/highlight/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/highlight/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "engines": { - "node": ">=4" + "node": ">=6.0.0" } }, - "node_modules/@babel/highlight/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "node_modules/@babel/plugin-proposal-export-namespace-from": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.9.tgz", + "integrity": "sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-export-namespace-from instead.", "dependencies": { - "has-flag": "^3.0.0" + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" }, "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/parser": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.6.tgz", - "integrity": "sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ==", - "dev": true, - "bin": { - "parser": "bin/babel-parser.js" + "node": ">=6.9.0" }, - "engines": { - "node": ">=6.0.0" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-syntax-async-generators": { @@ -751,6 +572,17 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-syntax-import-meta": { "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", @@ -892,34 +724,45 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.25.9.tgz", + "integrity": "sha512-dwh2Ol1jWwL2MgkCzUSOvfmKElqQcuswAZypBSUsScMXvgdT8Ekq5YA6TtqpTVWH+4903NmboMuH1o9i8Rxlyg==", + "dependencies": { + "@babel/helper-module-transforms": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-simple-access": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/template": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", - "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", - "dev": true, + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz", + "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==", "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/parser": "^7.22.15", - "@babel/types": "^7.22.15" + "@babel/code-frame": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.6.tgz", - "integrity": "sha512-czastdK1e8YByZqezMPFiZ8ahwVMh/ESl9vPgvgdB9AmFMGP5jfpFax74AQgl5zj4XHzqeYAg2l8PuUeRS1MgQ==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.23.5", - "@babel/generator": "^7.23.6", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.6", - "@babel/types": "^7.23.6", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.9.tgz", + "integrity": "sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==", + "dependencies": { + "@babel/code-frame": "^7.25.9", + "@babel/generator": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/template": "^7.25.9", + "@babel/types": "^7.25.9", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -931,20 +774,17 @@ "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, "engines": { "node": ">=4" } }, "node_modules/@babel/types": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.6.tgz", - "integrity": "sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg==", - "dev": true, + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.0.tgz", + "integrity": "sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==", "dependencies": { - "@babel/helper-string-parser": "^7.23.4", - "@babel/helper-validator-identifier": "^7.22.20", - "to-fast-properties": "^2.0.0" + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1605,7 +1445,6 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", - "dev": true, "dependencies": { "@jridgewell/set-array": "^1.0.0", "@jridgewell/sourcemap-codec": "^1.4.10" @@ -2446,6 +2285,15 @@ "@types/node": "*" } }, + "node_modules/@types/supercluster": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@types/supercluster/-/supercluster-7.1.3.tgz", + "integrity": "sha512-Z0pOY34GDFl3Q6hUFYf3HkTwKEE02e7QgtJppBt+beEAxnyOpJua+voGFvxINBHa06GwLFFym7gRPY2SiKIfIA==", + "dev": true, + "dependencies": { + "@types/geojson": "*" + } + }, "node_modules/@types/supertest": { "version": "2.0.16", "resolved": "https://registry.npmjs.org/@types/supertest/-/supertest-2.0.16.tgz", @@ -3964,8 +3812,7 @@ "node_modules/convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" }, "node_modules/cookie": { "version": "0.6.0", @@ -5447,6 +5294,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/fix-esm": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/fix-esm/-/fix-esm-1.0.1.tgz", + "integrity": "sha512-EZtb7wPXZS54GaGxaWxMlhd1DUDCnAg5srlYdu/1ZVeW+7wwR3Tp59nu52dXByFs3MBRq+SByx1wDOJpRvLEXw==", + "dependencies": { + "@babel/core": "^7.14.6", + "@babel/plugin-proposal-export-namespace-from": "^7.14.5", + "@babel/plugin-transform-modules-commonjs": "^7.14.5" + } + }, "node_modules/flat-cache": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", @@ -5686,7 +5543,6 @@ "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, "engines": { "node": ">=6.9.0" } @@ -7253,15 +7109,14 @@ } }, "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true, + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", + "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", "bin": { "jsesc": "bin/jsesc" }, "engines": { - "node": ">=4" + "node": ">=6" } }, "node_modules/json-parse-even-better-errors": { @@ -7363,6 +7218,11 @@ "safe-buffer": "^5.0.1" } }, + "node_modules/kdbush": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/kdbush/-/kdbush-3.0.0.tgz", + "integrity": "sha512-hRkd6/XW4HTsA9vjVpY9tuXJYLSlelnkTmVFu4M9/7MIYQtFcHpbugAU7UbOfjOiVSVYl2fqgBuJ32JUmRo5Ew==" + }, "node_modules/kleur": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", @@ -7848,7 +7708,6 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, "dependencies": { "yallist": "^3.0.2" } @@ -10020,6 +9879,14 @@ "node": ">=4.0.0" } }, + "node_modules/supercluster": { + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/supercluster/-/supercluster-7.1.5.tgz", + "integrity": "sha512-EulshI3pGUM66o6ZdH3ReiFcvHpM3vAigyK+vcxdjpJyEbIIrtbmBdY23mGgnI24uXiGFvrGq9Gkum/8U7vJWg==", + "dependencies": { + "kdbush": "^3.0.0" + } + }, "node_modules/supertest": { "version": "6.3.4", "resolved": "https://registry.npmjs.org/supertest/-/supertest-6.3.4.tgz", @@ -10239,15 +10106,6 @@ "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", "dev": true }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -11152,8 +11010,7 @@ "node_modules/yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" }, "node_modules/yargs": { "version": "17.7.1", @@ -11213,7 +11070,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", - "dev": true, "requires": { "@jridgewell/gen-mapping": "^0.1.0", "@jridgewell/trace-mapping": "^0.3.9" @@ -11347,76 +11203,24 @@ "integrity": "sha512-f0Y/Q4dVfKH6SQyzS5bPk+hZ4pSxzVNAOPEHdEAUe3gAc6ou43DCBYERuOaVSZ3zbWJbVt1KgWVNLP1dj9OIeg==" }, "@babel/code-frame": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", - "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", "requires": { - "@babel/highlight": "^7.23.4", - "chalk": "^2.4.2" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==" - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "requires": { - "has-flag": "^3.0.0" - } - } + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" } }, "@babel/compat-data": { "version": "7.23.5", "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", - "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==", - "dev": true + "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==" }, "@babel/core": { "version": "7.23.6", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.6.tgz", "integrity": "sha512-FxpRyGjrMJXh7X3wGLGhNDCRiwpWEF74sKjTLDJSG5Kyvow3QZaG0Adbqzi9ZrVjTWpsX+2cxWXD71NMg93kdw==", - "dev": true, "requires": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.23.5", @@ -11438,32 +11242,30 @@ "semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" } } }, "@babel/generator": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", - "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", - "dev": true, + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.2.tgz", + "integrity": "sha512-zevQbhbau95nkoxSq3f/DC/SC+EEOUZd3DYqfSkMhY2/wfSeaHV1Ew4vk8e+x8lja31IbyuUa2uQ3JONqKbysw==", "requires": { - "@babel/types": "^7.23.6", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", - "jsesc": "^2.5.1" + "@babel/parser": "^7.26.2", + "@babel/types": "^7.26.0", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^3.0.2" }, "dependencies": { "@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dev": true, + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "requires": { - "@jridgewell/set-array": "^1.0.1", + "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/trace-mapping": "^0.3.24" } } } @@ -11472,7 +11274,6 @@ "version": "7.23.6", "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", - "dev": true, "requires": { "@babel/compat-data": "^7.23.5", "@babel/helper-validator-option": "^7.23.5", @@ -11484,176 +11285,84 @@ "semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" } } }, - "@babel/helper-environment-visitor": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", - "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", - "dev": true - }, - "@babel/helper-function-name": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", - "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", - "dev": true, - "requires": { - "@babel/template": "^7.22.15", - "@babel/types": "^7.23.0" - } - }, - "@babel/helper-hoist-variables": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", - "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", - "dev": true, - "requires": { - "@babel/types": "^7.22.5" - } - }, "@babel/helper-module-imports": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", - "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", - "dev": true, + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", + "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", "requires": { - "@babel/types": "^7.22.15" + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" } }, "@babel/helper-module-transforms": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", - "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", - "dev": true, + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", + "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", "requires": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-module-imports": "^7.22.15", - "@babel/helper-simple-access": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/helper-validator-identifier": "^7.22.20" + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" } }, "@babel/helper-plugin-utils": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", - "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", - "dev": true + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.9.tgz", + "integrity": "sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==" }, "@babel/helper-simple-access": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", - "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", - "dev": true, - "requires": { - "@babel/types": "^7.22.5" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", - "dev": true, + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.25.9.tgz", + "integrity": "sha512-c6WHXuiaRsJTyHYLJV75t9IqsmTbItYfdj99PnzYGQZkYKvan5/2jKJ7gu31J3/BJ/A18grImSPModuyG/Eo0Q==", "requires": { - "@babel/types": "^7.22.5" + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" } }, "@babel/helper-string-parser": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", - "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", - "dev": true + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==" }, "@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==" + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==" }, "@babel/helper-validator-option": { "version": "7.23.5", "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", - "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", - "dev": true + "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==" }, "@babel/helpers": { "version": "7.23.6", "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.6.tgz", "integrity": "sha512-wCfsbN4nBidDRhpDhvcKlzHWCTlgJYUUdSJfzXb2NuBssDSIjc3xcb+znA7l+zYsFljAcGM0aFkN40cR3lXiGA==", - "dev": true, "requires": { "@babel/template": "^7.22.15", "@babel/traverse": "^7.23.6", "@babel/types": "^7.23.6" } }, - "@babel/highlight": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", - "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", + "@babel/parser": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.2.tgz", + "integrity": "sha512-DWMCZH9WA4Maitz2q21SRKHo9QXZxkDsbNZoVD62gusNtNBBqDg9i7uOhASfTfIGNzW+O+r7+jAlM8dwphcJKQ==", "requires": { - "@babel/helper-validator-identifier": "^7.22.20", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==" - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "requires": { - "has-flag": "^3.0.0" - } - } + "@babel/types": "^7.26.0" } }, - "@babel/parser": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.6.tgz", - "integrity": "sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ==", - "dev": true + "@babel/plugin-proposal-export-namespace-from": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.9.tgz", + "integrity": "sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + } }, "@babel/plugin-syntax-async-generators": { "version": "7.8.4", @@ -11682,6 +11391,14 @@ "@babel/helper-plugin-utils": "^7.12.13" } }, + "@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, "@babel/plugin-syntax-import-meta": { "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", @@ -11781,31 +11498,36 @@ "@babel/helper-plugin-utils": "^7.22.5" } }, + "@babel/plugin-transform-modules-commonjs": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.25.9.tgz", + "integrity": "sha512-dwh2Ol1jWwL2MgkCzUSOvfmKElqQcuswAZypBSUsScMXvgdT8Ekq5YA6TtqpTVWH+4903NmboMuH1o9i8Rxlyg==", + "requires": { + "@babel/helper-module-transforms": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-simple-access": "^7.25.9" + } + }, "@babel/template": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", - "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", - "dev": true, + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz", + "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==", "requires": { - "@babel/code-frame": "^7.22.13", - "@babel/parser": "^7.22.15", - "@babel/types": "^7.22.15" + "@babel/code-frame": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/types": "^7.25.9" } }, "@babel/traverse": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.6.tgz", - "integrity": "sha512-czastdK1e8YByZqezMPFiZ8ahwVMh/ESl9vPgvgdB9AmFMGP5jfpFax74AQgl5zj4XHzqeYAg2l8PuUeRS1MgQ==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.23.5", - "@babel/generator": "^7.23.6", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.6", - "@babel/types": "^7.23.6", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.9.tgz", + "integrity": "sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==", + "requires": { + "@babel/code-frame": "^7.25.9", + "@babel/generator": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/template": "^7.25.9", + "@babel/types": "^7.25.9", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -11813,20 +11535,17 @@ "globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" } } }, "@babel/types": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.6.tgz", - "integrity": "sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg==", - "dev": true, + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.0.tgz", + "integrity": "sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==", "requires": { - "@babel/helper-string-parser": "^7.23.4", - "@babel/helper-validator-identifier": "^7.22.20", - "to-fast-properties": "^2.0.0" + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" } }, "@bcoe/v8-coverage": { @@ -12335,7 +12054,6 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", - "dev": true, "requires": { "@jridgewell/set-array": "^1.0.0", "@jridgewell/sourcemap-codec": "^1.4.10" @@ -12968,6 +12686,15 @@ "@types/node": "*" } }, + "@types/supercluster": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@types/supercluster/-/supercluster-7.1.3.tgz", + "integrity": "sha512-Z0pOY34GDFl3Q6hUFYf3HkTwKEE02e7QgtJppBt+beEAxnyOpJua+voGFvxINBHa06GwLFFym7gRPY2SiKIfIA==", + "dev": true, + "requires": { + "@types/geojson": "*" + } + }, "@types/supertest": { "version": "2.0.16", "resolved": "https://registry.npmjs.org/@types/supertest/-/supertest-2.0.16.tgz", @@ -14072,8 +13799,7 @@ "convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" }, "cookie": { "version": "0.6.0", @@ -15181,6 +14907,16 @@ "path-exists": "^4.0.0" } }, + "fix-esm": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/fix-esm/-/fix-esm-1.0.1.tgz", + "integrity": "sha512-EZtb7wPXZS54GaGxaWxMlhd1DUDCnAg5srlYdu/1ZVeW+7wwR3Tp59nu52dXByFs3MBRq+SByx1wDOJpRvLEXw==", + "requires": { + "@babel/core": "^7.14.6", + "@babel/plugin-proposal-export-namespace-from": "^7.14.5", + "@babel/plugin-transform-modules-commonjs": "^7.14.5" + } + }, "flat-cache": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", @@ -15346,8 +15082,7 @@ "gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==" }, "geojson": { "version": "0.5.0", @@ -16473,10 +16208,9 @@ } }, "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", + "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==" }, "json-parse-even-better-errors": { "version": "2.3.1", @@ -16562,6 +16296,11 @@ "safe-buffer": "^5.0.1" } }, + "kdbush": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/kdbush/-/kdbush-3.0.0.tgz", + "integrity": "sha512-hRkd6/XW4HTsA9vjVpY9tuXJYLSlelnkTmVFu4M9/7MIYQtFcHpbugAU7UbOfjOiVSVYl2fqgBuJ32JUmRo5Ew==" + }, "kleur": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", @@ -16913,7 +16652,6 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, "requires": { "yallist": "^3.0.2" } @@ -18509,6 +18247,14 @@ } } }, + "supercluster": { + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/supercluster/-/supercluster-7.1.5.tgz", + "integrity": "sha512-EulshI3pGUM66o6ZdH3ReiFcvHpM3vAigyK+vcxdjpJyEbIIrtbmBdY23mGgnI24uXiGFvrGq9Gkum/8U7vJWg==", + "requires": { + "kdbush": "^3.0.0" + } + }, "supertest": { "version": "6.3.4", "resolved": "https://registry.npmjs.org/supertest/-/supertest-6.3.4.tgz", @@ -18663,12 +18409,6 @@ "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", "dev": true }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true - }, "to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -19233,8 +18973,7 @@ "yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" }, "yargs": { "version": "17.7.1", diff --git a/backend/package.json b/backend/package.json index 0ee417c5e..10260c0ce 100644 --- a/backend/package.json +++ b/backend/package.json @@ -66,6 +66,7 @@ "date-fns-tz": "^3.1.3", "dotenv": "^16.0.1", "escape-html": "^1.0.3", + "fix-esm": "^1.0.1", "form-data": "^4.0.0", "geojson": "^0.5.0", "jest-mock": "^29.6.1", @@ -82,6 +83,7 @@ "reflect-metadata": "^0.1.13", "rimraf": "^4.0.0", "rxjs": "^7.8.0", + "supercluster": "^7.1.5", "swagger-ui-express": "^4.6.0", "typeorm": "^0.3.14", "winston": "^3.9.0" @@ -92,6 +94,7 @@ "@types/jest": "^29.5.1", "@types/node": "^18.11.18", "@types/passport-jwt": "^3.0.8", + "@types/supercluster": "^7.1.3", "@types/supertest": "^2.0.11", "@typescript-eslint/eslint-plugin": "^5.48.2", "@typescript-eslint/parser": "^5.48.2", diff --git a/backend/src/types/models/complaints/complaint-search-parameters.ts b/backend/src/types/models/complaints/complaint-search-parameters.ts index 16fa32175..4c7477af1 100644 --- a/backend/src/types/models/complaints/complaint-search-parameters.ts +++ b/backend/src/types/models/complaints/complaint-search-parameters.ts @@ -8,3 +8,10 @@ export interface ComplaintSearchParameters PageParameters, ComplaintFilterParameters, SearchParameters {} + +export interface ComplaintMapSearchClusteredParameters extends ComplaintSearchParameters { + bbox: string; + zoom: number; + clusters: boolean; + unmapped: boolean; +} diff --git a/backend/src/types/models/complaints/map-search-results.ts b/backend/src/types/models/complaints/map-search-results.ts index e025c79dd..5eec575bc 100644 --- a/backend/src/types/models/complaints/map-search-results.ts +++ b/backend/src/types/models/complaints/map-search-results.ts @@ -1,8 +1,8 @@ -import { WildlifeComplaintDto } from "./wildlife-complaint"; -import { AllegationComplaintDto } from "./allegation-complaint"; -import { GeneralIncidentComplaintDto } from "./gir-complaint"; - export interface MapSearchResults { - complaints: WildlifeComplaintDto[] | AllegationComplaintDto[] | GeneralIncidentComplaintDto[]; - unmappedComplaints: number; + clusters?: any; + mappedCount?: number; + unmappedCount?: number; + zoom?: number; + center?: Array; + debugLog?: string; } diff --git a/backend/src/v1/code-table/code-table.controller.spec.ts b/backend/src/v1/code-table/code-table.controller.spec.ts index 5edff2dd2..c7db5016e 100644 --- a/backend/src/v1/code-table/code-table.controller.spec.ts +++ b/backend/src/v1/code-table/code-table.controller.spec.ts @@ -1,7 +1,7 @@ import { Test, TestingModule } from "@nestjs/testing"; import { getRepositoryToken } from "@nestjs/typeorm"; import { INestApplication } from "@nestjs/common"; -import * as request from "supertest"; +import request from "supertest"; import { authGuardMock } from "../../../test/mocks/authGuardMock"; import { roleGuardMock } from "../../../test/mocks/roleGuardMock"; diff --git a/backend/src/v1/complaint/complaint.controller.ts b/backend/src/v1/complaint/complaint.controller.ts index d96196c13..1cc5a1213 100644 --- a/backend/src/v1/complaint/complaint.controller.ts +++ b/backend/src/v1/complaint/complaint.controller.ts @@ -9,7 +9,10 @@ import { COMPLAINT_TYPE } from "../../types/models/complaints/complaint-type"; import { WildlifeComplaintDto } from "../../types/models/complaints/wildlife-complaint"; import { AllegationComplaintDto } from "../../types/models/complaints/allegation-complaint"; import { ComplaintDto } from "../../types/models/complaints/complaint"; -import { ComplaintSearchParameters } from "../../types/models/complaints/complaint-search-parameters"; +import { + ComplaintSearchParameters, + ComplaintMapSearchClusteredParameters, +} from "../../types/models/complaints/complaint-search-parameters"; import { ZoneAtAGlanceStats } from "src/types/zone_at_a_glance/zone_at_a_glance_stats"; import { GeneralIncidentComplaintDto } from "src/types/models/complaints/gir-complaint"; import { ApiKeyGuard } from "src/auth/apikey.guard"; @@ -45,7 +48,7 @@ export class ComplaintController { return await this.service.findAllByType(complaintType); } - @Get("/map/search/:complaintType") + /* @Get("/map/search/:complaintType") @Roles(Role.COS_OFFICER, Role.CEEB) mapSearch( @Param("complaintType") complaintType: COMPLAINT_TYPE, @@ -56,6 +59,19 @@ export class ComplaintController { const hasCEEBRole = hasRole(req, Role.CEEB); return this.service.mapSearch(complaintType, model, hasCEEBRole, token); + } */ + + @Get("/map/search/clustered/:complaintType") + @Roles(Role.COS_OFFICER, Role.CEEB) + mapSearchClustered( + @Param("complaintType") complaintType: COMPLAINT_TYPE, + @Query() model: ComplaintMapSearchClusteredParameters, + @Request() req, + @Token() token, + ) { + const hasCEEBRole = hasRole(req, Role.CEEB); + + return this.service.mapSearchClustered(complaintType, model, hasCEEBRole, token); } @Get("/search/:complaintType") diff --git a/backend/src/v1/complaint/complaint.service.spec.ts b/backend/src/v1/complaint/complaint.service.spec.ts index 4b0d14250..cf42abcb6 100644 --- a/backend/src/v1/complaint/complaint.service.spec.ts +++ b/backend/src/v1/complaint/complaint.service.spec.ts @@ -61,7 +61,10 @@ import { MockUpdateComplaintsRepository, } from "../../../test/mocks/mock-complaints-repositories"; import { dataSourceMockFactory } from "../../../test/mocks/datasource"; -import { ComplaintSearchParameters } from "../../types/models/complaints/complaint-search-parameters"; +import { + ComplaintSearchParameters, + ComplaintMapSearchClusteredParameters, +} from "../../types/models/complaints/complaint-search-parameters"; import { GirTypeCode } from "../gir_type_code/entities/gir_type_code.entity"; import { GirComplaint } from "../gir_complaint/entities/gir_complaint.entity"; import { ComplaintUpdatesService } from "../complaint_updates/complaint_updates.service"; @@ -316,51 +319,59 @@ describe("Testing: Complaint Service", () => { it("should return list of complaints by mapSearch for non ceeb role users", async () => { //-- arrange const _complaintType: COMPLAINT_TYPE = "HWCR"; - const payload: ComplaintSearchParameters = { - sortBy: "incident_reported_utc_timestmp", - orderBy: "DESC", + const payload: ComplaintMapSearchClusteredParameters = { zone: "CRBOTMPSN", status: "OPEN", - page: 1, - pageSize: 50, query: "bear", + zoom: 17, + clusters: true, + unmapped: true, + bbox: undefined, + page: undefined, + pageSize: undefined, + sortBy: undefined, + orderBy: undefined, }; //-- act - const results = await service.mapSearch(_complaintType, payload, false); + const results = await service.mapSearchClustered(_complaintType, payload, false); //-- assert expect(results).not.toBe(null); - const { unmappedComplaints, complaints } = results; + const { mappedCount, unmappedCount } = results; - expect(complaints.length).toBe(5); - expect(unmappedComplaints).toBe(55); + expect(mappedCount).toBe(5); + expect(unmappedCount).toBe(55); }); it("should return list of complaints by mapSearch for user with ceeb role", async () => { //-- arrange const _complaintType: COMPLAINT_TYPE = "HWCR"; - const payload: ComplaintSearchParameters = { - sortBy: "incident_reported_utc_timestmp", - orderBy: "DESC", + const payload: ComplaintMapSearchClusteredParameters = { zone: "CRBOTMPSN", status: "OPEN", - page: 1, - pageSize: 50, query: "bear", + zoom: 17, + clusters: true, + unmapped: true, + bbox: undefined, + page: undefined, + pageSize: undefined, + sortBy: undefined, + orderBy: undefined, }; //-- act - const results = await service.mapSearch(_complaintType, payload, true); + const results = await service.mapSearchClustered(_complaintType, payload, true); //-- assert expect(results).not.toBe(null); - const { unmappedComplaints, complaints } = results; + const { mappedCount, unmappedCount } = results; - expect(complaints.length).toBe(5); - expect(unmappedComplaints).toBe(55); + expect(mappedCount).toBe(5); + expect(unmappedCount).toBe(55); }); }); diff --git a/backend/src/v1/complaint/complaint.service.ts b/backend/src/v1/complaint/complaint.service.ts index 114bf62fd..d3e36eef1 100644 --- a/backend/src/v1/complaint/complaint.service.ts +++ b/backend/src/v1/complaint/complaint.service.ts @@ -5,6 +5,8 @@ import { Brackets, DataSource, QueryRunner, Repository, SelectQueryBuilder } fro import { InjectMapper } from "@automapper/nestjs"; import { Mapper } from "@automapper/core"; import { caseFileQueryFields, get } from "../../external_api/case_management"; +import Supercluster, { PointFeature } from "supercluster"; +import { GeoJsonProperties } from "geojson"; import { applyAllegationComplaintMap, @@ -39,7 +41,10 @@ import { mapGirComplaintDtoToGirComplaint, } from "../../middleware/maps/automapper-dto-to-entity-maps"; -import { ComplaintSearchParameters } from "../../types/models/complaints/complaint-search-parameters"; +import { + ComplaintSearchParameters, + ComplaintMapSearchClusteredParameters, +} from "../../types/models/complaints/complaint-search-parameters"; import { SearchResults } from "../../types/models/complaints/search-results"; import { ComplaintFilterParameters } from "../../types/models/complaints/complaint-filter-parameters"; import { REQUEST } from "@nestjs/core"; @@ -70,6 +75,7 @@ import { OfficerService } from "../officer/officer.service"; import { SpeciesCode } from "../species_code/entities/species_code.entity"; import { LinkedComplaintXrefService } from "../linked_complaint_xref/linked_complaint_xref.service"; +const WorldBounds: Array = [-180, -90, 180, 90]; type complaintAlias = HwcrComplaint | AllegationComplaint | GirComplaint; @Injectable({ scope: Scope.REQUEST }) export class ComplaintService { @@ -167,10 +173,60 @@ export class ComplaintService { } }; - private _generateQueryBuilder = ( + private readonly _generateMapQueryBuilder = ( type: COMPLAINT_TYPE, - ): SelectQueryBuilder => { - let builder: SelectQueryBuilder; + includeCosOrganization: boolean, + ): SelectQueryBuilder => { + let builder: SelectQueryBuilder; + + switch (type) { + case "ERS": + builder = this._allegationComplaintRepository + .createQueryBuilder("allegation") + .leftJoin("allegation.complaint_identifier", "complaint") + .addSelect(["complaint.complaint_identifier", "complaint.location_geometry_point"]) + .leftJoin("allegation.violation_code", "violation_code"); + break; + case "GIR": + builder = this._girComplaintRepository + .createQueryBuilder("general") + .leftJoin("general.complaint_identifier", "complaint") + .addSelect(["complaint.complaint_identifier", "complaint.location_geometry_point"]) + .leftJoin("general.gir_type_code", "gir"); + break; + case "HWCR": + default: + builder = this._wildlifeComplaintRepository + .createQueryBuilder("wildlife") + .leftJoin("wildlife.complaint_identifier", "complaint") + .addSelect(["complaint.complaint_identifier", "complaint.location_geometry_point"]) + .leftJoin("wildlife.species_code", "species_code") + .leftJoin("wildlife.hwcr_complaint_nature_code", "complaint_nature_code") + .leftJoin("wildlife.attractant_hwcr_xref", "attractants", "attractants.active_ind = true") + .leftJoin("attractants.attractant_code", "attractant_code"); + break; + } + builder + .leftJoin("complaint.complaint_status_code", "complaint_status") + .leftJoin("complaint.reported_by_code", "reported_by") + .leftJoin("complaint.complaint_update", "complaint_update") + .leftJoin("complaint.action_taken", "action_taken") + .leftJoin("complaint.owned_by_agency_code", "owned_by") + .leftJoin("complaint.linked_complaint_xref", "linked_complaint") + .leftJoin("complaint.person_complaint_xref", "delegate", "delegate.active_ind = true") + .leftJoin("delegate.person_complaint_xref_code", "delegate_code") + .leftJoin("delegate.person_guid", "person", "delegate.active_ind = true") + .leftJoin("complaint.comp_mthd_recv_cd_agcy_cd_xref", "method_xref") + .leftJoin("method_xref.complaint_method_received_code", "method_code") + .leftJoin("method_xref.agency_code", "method_agency"); + if (includeCosOrganization) { + builder.leftJoin("complaint.cos_geo_org_unit", "cos_organization"); + } + return builder; + }; + + private readonly _generateQueryBuilder = (type: COMPLAINT_TYPE): SelectQueryBuilder => { + let builder: SelectQueryBuilder; switch (type) { case "ERS": builder = this._allegationComplaintRepository @@ -1063,89 +1119,43 @@ export class ComplaintService { } }; - mapSearch = async ( + _generateFilteredMapQueryBuilder = async ( complaintType: COMPLAINT_TYPE, - model: ComplaintSearchParameters, + model: ComplaintMapSearchClusteredParameters, hasCEEBRole: boolean, token?: string, - ): Promise => { - this.logger.error("Mapping search results"); - const { orderBy, sortBy, page, pageSize, query, ...filters } = model; + ): Promise> => { + const { query, ...filters } = model; try { - let results: MapSearchResults = { complaints: [], unmappedComplaints: 0 }; - - //-- assign the users agency - // _getAgencyByUser traces agency through assigned office of the officer, which CEEB users do not have - // so the hasCEEBRole is used to assign agency for them. - const agency = hasCEEBRole ? "EPO" : (await this._getAgencyByUser()).agency_code; //-- search for complaints - let complaintBuilder = this._generateQueryBuilder(complaintType); + // Only these options require the cos_geo_org_unit_flat_vw view (cos_organization), which is very slow. + const includeCosOrganization: boolean = Boolean(query || filters.community || filters.zone || filters.region); + let builder = this._generateMapQueryBuilder(complaintType, includeCosOrganization); //-- apply search if (query) { - complaintBuilder = await this._applySearch(complaintBuilder, complaintType, query, token); - } - - //-- apply filters - if (Object.keys(filters).length !== 0) { - complaintBuilder = this._applyFilters(complaintBuilder, filters as ComplaintFilterParameters, complaintType); - } - - //-- only return complaints for the agency the user is associated with - if (agency) { - complaintBuilder.andWhere("complaint.owned_by_agency_code.agency_code = :agency", { - agency: agency, - }); - } - - //-- added this for consistency with search method - //-- return Waste and Pestivide complaints for CEEB users - if (hasCEEBRole && complaintType === "ERS") { - complaintBuilder.andWhere("violation_code.agency_code = :agency", { agency: "EPO" }); - } - - //-- filter locations without coordinates - complaintBuilder.andWhere("ST_X(complaint.location_geometry_point) <> 0"); - complaintBuilder.andWhere("ST_Y(complaint.location_geometry_point) <> 0"); - - //-- get unmapable complaints - let unMappedBuilder = this._generateQueryBuilder(complaintType); - - //-- apply search - if (query) { - unMappedBuilder = await this._applySearch(unMappedBuilder, complaintType, query, token); + builder = await this._applySearch(builder, complaintType, query, token); } - //-- apply filters + //-- apply filters if used if (Object.keys(filters).length !== 0) { - unMappedBuilder = this._applyFilters(unMappedBuilder, filters as ComplaintFilterParameters, complaintType); + builder = this._applyFilters(builder, filters as ComplaintFilterParameters, complaintType); } //-- only return complaints for the agency the user is associated with - if (agency) { - unMappedBuilder.andWhere("complaint.owned_by_agency_code.agency_code = :agency", { - agency: agency, - }); - } + const agency = hasCEEBRole ? "EPO" : (await this._getAgencyByUser()).agency_code; + agency && builder.andWhere("complaint.owned_by_agency_code.agency_code = :agency", { agency }); - //-- added this for consistency with search method //-- return Waste and Pestivide complaints for CEEB users if (hasCEEBRole && complaintType === "ERS") { - unMappedBuilder.andWhere("violation_code.agency_code = :agency", { agency: "EPO" }); + builder.andWhere("violation_code.agency_code = :agency", { agency: "EPO" }); } - //-- filter locations without coordinates - unMappedBuilder.andWhere("ST_X(complaint.location_geometry_point) = 0"); - unMappedBuilder.andWhere("ST_Y(complaint.location_geometry_point) = 0"); - // -- filter by complaint identifiers returned by case management if actionTaken filter is present if (hasCEEBRole && filters.actionTaken) { const complaintIdentifiers = await this._getComplaintsByActionTaken(token, filters.actionTaken); - complaintBuilder.andWhere("complaint.complaint_identifier IN(:...complaint_identifiers)", { - complaint_identifiers: complaintIdentifiers, - }); - unMappedBuilder.andWhere("complaint.complaint_identifier IN(:...complaint_identifiers)", { + builder.andWhere("complaint.complaint_identifier IN(:...complaint_identifiers)", { complaint_identifiers: complaintIdentifiers, }); } @@ -1158,55 +1168,145 @@ export class ComplaintService { filters.outcomeAnimalStartDate, filters.outcomeAnimalEndDate, ); - complaintBuilder.andWhere("complaint.complaint_identifier IN(:...complaint_identifiers)", { - complaint_identifiers: complaintIdentifiers, - }); - unMappedBuilder.andWhere("complaint.complaint_identifier IN(:...complaint_identifiers)", { + builder.andWhere("complaint.complaint_identifier IN(:...complaint_identifiers)", { complaint_identifiers: complaintIdentifiers, }); } - //-- run queries + return builder; + } catch (error) { + this.logger.error(error); + } + }; + + _getUnmappedComplaintsCount = async ( + complaintType: COMPLAINT_TYPE, + model: ComplaintMapSearchClusteredParameters, + hasCEEBRole: boolean, + token?: string, + ): Promise => { + try { + const builder = await this._generateFilteredMapQueryBuilder(complaintType, model, hasCEEBRole, token); + + //-- filter for locations without coordinates + builder.andWhere("ST_X(complaint.location_geometry_point) = 0"); + builder.andWhere("ST_Y(complaint.location_geometry_point) = 0"); + + return builder.getCount(); + } catch (error) { + this.logger.error(error); + } + }; + + _getClusteredComplaints = async ( + complaintType: COMPLAINT_TYPE, + model: ComplaintMapSearchClusteredParameters, + hasCEEBRole: boolean, + token?: string, + ): Promise>> => { + try { + const complaintBuilder = await this._generateFilteredMapQueryBuilder(complaintType, model, hasCEEBRole, token); + + //-- filter locations without coordinates + complaintBuilder.andWhere("complaint.location_geometry_point is not null"); + complaintBuilder.andWhere("ST_X(complaint.location_geometry_point) <> 0"); + complaintBuilder.andWhere("ST_Y(complaint.location_geometry_point) <> 0"); + + //-- filter locations by bounding box if provided, otherwise default to the world + // geometry ST_MakeEnvelope(float xmin, float ymin, float xmax, float ymax, integer srid=unknown); + const bbox = model.bbox ? model.bbox.split(",") : WorldBounds; + complaintBuilder.andWhere( + `complaint.location_geometry_point && ST_MakeEnvelope(${bbox[0]}, ${bbox[1]}, ${bbox[2]}, ${bbox[3]}, 4326)`, + ); + + //-- run mapped query const mappedComplaints = await complaintBuilder.getMany(); - const unmappedComplaints = await unMappedBuilder.getCount(); - results = { ...results, unmappedComplaints }; - //-- map results - switch (complaintType) { - case "ERS": { - const items = this.mapper.mapArray( - mappedComplaints as Array, - "AllegationComplaint", - "AllegationComplaintDto", - ); - results.complaints = items; - break; - } - case "GIR": { - const items = this.mapper.mapArray( - mappedComplaints as Array, - "GirComplaint", - "GeneralIncidentComplaintDto", - ); + // convert to supercluster PointFeature array + const points: Array> = mappedComplaints.map((item) => { + return { + type: "Feature", + properties: { + cluster: false, + id: item.complaint_identifier.complaint_identifier, + }, + geometry: item.complaint_identifier.location_geometry_point, + } as PointFeature; + }); - results.complaints = items; - break; - } - case "HWCR": - default: { - const items = this.mapper.mapArray( - mappedComplaints as Array, - "HwcrComplaint", - "WildlifeComplaintDto", - ); + return points; + } catch (error) { + this.logger.error(error); + } + }; - results.complaints = items; - break; + mapSearchClustered = async ( + complaintType: COMPLAINT_TYPE, + model: ComplaintMapSearchClusteredParameters, + hasCEEBRole: boolean, + token?: string, + ): Promise => { + try { + let results: MapSearchResults = {}; + // Get unmappable complaints if requested + if (model.unmapped) { + // run query and append to results + const unmappedCount = await this._getUnmappedComplaintsCount(complaintType, model, hasCEEBRole, token); + results = { ...results, unmappedCount }; + } + + if (model.clusters) { + const points = await this._getClusteredComplaints(complaintType, model, hasCEEBRole, token); + + results.mappedCount = points.length; + + // load into Supercluster + const index = new Supercluster({ + log: false, + radius: 160, + maxZoom: 16, + }); + index.load(points); + + // cluster the results + const bbox = model.bbox ? model.bbox.split(",") : WorldBounds; + let clusters = index.getClusters( + [Number(bbox[0]), Number(bbox[1]), Number(bbox[2]), Number(bbox[3])], + model.zoom, + ); + + // If we are doing a global search and there is only one cluster, try to explode it to at least 2 clusters + // then return the center and zoom level so the client can then zoom to the clusters at an appropriate zoom level + if (!model.bbox && clusters.length === 1) { + const center = [clusters[0].geometry.coordinates[1], clusters[0].geometry.coordinates[0]]; + const expansionZoom = index.getClusterExpansionZoom(clusters[0].properties.cluster_id); + // If we can expand the cluster, do so. If not, it's a single point and we don't need to do anything + if (expansionZoom) { + clusters = index.getClusters( + [Number(bbox[0]), Number(bbox[1]), Number(bbox[2]), Number(bbox[3])], + expansionZoom + 2, // At least 2 clusters plus an arbitrary 2 steps of zoom + ); + } + results.zoom = expansionZoom || 18; // If we can't expand the cluster, fully zoom to the point + results.center = center; + } else if (!model.bbox && clusters.length === 0) { + // If we are doing a global search and there are no clusters, return the center of BC + if (clusters.length === 0) { + results.zoom = 5; + results.center = [55.0, -125.0]; // Center of BC + } } + + clusters.forEach((cluster) => { + cluster.properties.zoom = index.getClusterExpansionZoom(cluster.properties.cluster_id); + }); + + // set the results + results.clusters = clusters; } return results; } catch (error) { - this.logger.error(error.response); + this.logger.error(error); throw new HttpException("Unable to Perform Search", HttpStatus.BAD_REQUEST); } }; diff --git a/backend/src/v1/office/office.controller.v2.spec.ts b/backend/src/v1/office/office.controller.v2.spec.ts index c8c76c6db..816391661 100644 --- a/backend/src/v1/office/office.controller.v2.spec.ts +++ b/backend/src/v1/office/office.controller.v2.spec.ts @@ -15,7 +15,7 @@ import { JwtRoleGuard } from "../../auth/jwtrole.guard"; import { MockOfficeRepository } from "../../../test/mocks/mock-office-repository"; import { dataSourceMockFactory } from "../../../test/mocks/datasource"; -import * as request from "supertest"; +import request from "supertest"; import { UUID } from "crypto"; import { CreateOfficeDto } from "./dto/create-office.dto"; import { AgencyCodeDto } from "../agency_code/dto/agency_code.dto"; diff --git a/backend/src/v1/officer/officer.service.ts b/backend/src/v1/officer/officer.service.ts index b3c7dca16..df0180621 100644 --- a/backend/src/v1/officer/officer.service.ts +++ b/backend/src/v1/officer/officer.service.ts @@ -34,7 +34,8 @@ export class OfficerService { .leftJoinAndSelect("officer.office_guid", "office") .leftJoinAndSelect("officer.person_guid", "person") .leftJoinAndSelect("office.agency_code", "agency") - .leftJoinAndSelect("office.cos_geo_org_unit", "cos_geo_org_unit") + // This view is slow, no need to join and select for the properties that are mapped in this call + //.leftJoinAndSelect("office.cos_geo_org_unit", "cos_geo_org_unit") .leftJoinAndSelect("office.agency_code", "agency_code") .orderBy("person.last_name", "ASC") .getMany(); diff --git a/backend/src/v1/person/person.controller.spec.ts b/backend/src/v1/person/person.controller.spec.ts index 32741e4ec..d3beaa4b4 100644 --- a/backend/src/v1/person/person.controller.spec.ts +++ b/backend/src/v1/person/person.controller.spec.ts @@ -11,7 +11,7 @@ import { dataSourceMockFactory } from "../../../test/mocks/datasource"; import { PersonRepositoryMockFactory } from "../../../test/mocks/personRepositoryMockFactory"; import { getRepositoryToken } from "@nestjs/typeorm"; import { INestApplication } from "@nestjs/common"; -import * as request from "supertest"; +import request from "supertest"; describe("PersonController", () => { let controller: PersonController; diff --git a/backend/test/app.e2e-spec.ts b/backend/test/app.e2e-spec.ts index e74b0b2e2..35e03caf7 100644 --- a/backend/test/app.e2e-spec.ts +++ b/backend/test/app.e2e-spec.ts @@ -1,4 +1,4 @@ -import * as request from "supertest"; +import request from "supertest"; import { Test } from "@nestjs/testing"; import { INestApplication } from "@nestjs/common"; import { AppModule } from "../src/app.module"; diff --git a/backend/tsconfig.json b/backend/tsconfig.json index 6ba0771be..4b22ccdd9 100644 --- a/backend/tsconfig.json +++ b/backend/tsconfig.json @@ -1,6 +1,7 @@ { "compilerOptions": { "module": "commonjs", + "esModuleInterop": true, "declaration": true, "removeComments": true, "emitDecoratorMetadata": true, diff --git a/charts/app/templates/backend/templates/deployment.yaml b/charts/app/templates/backend/templates/deployment.yaml index 1888211fb..4b52a7e1a 100644 --- a/charts/app/templates/backend/templates/deployment.yaml +++ b/charts/app/templates/backend/templates/deployment.yaml @@ -94,10 +94,10 @@ spec: timeoutSeconds: 5 resources: # this is optional limits: - cpu: 150m + cpu: 450m memory: 150Mi requests: - cpu: 50m + cpu: 150m memory: 75Mi {{- with .Values.backend.nodeSelector }} nodeSelector: diff --git a/frontend/cypress/e2e/complaints-on-map-view.cy.ts b/frontend/cypress/e2e/complaints-on-map-view.cy.ts index 035ce7306..69d3d997a 100644 --- a/frontend/cypress/e2e/complaints-on-map-view.cy.ts +++ b/frontend/cypress/e2e/complaints-on-map-view.cy.ts @@ -22,7 +22,7 @@ describe("Complaints on map tests", () => { cy.get("#map_toggle_id").should("exist").click({ force: true }); // wait for the map to load - cy.waitForSpinner(); + cy.wait(1000); // verify default filters cy.get("#comp-status-filter").should("exist"); @@ -101,13 +101,13 @@ describe("Complaints on map tests", () => { cy.get("#map_toggle_id").click({ force: true }); // wait for the map to load - cy.waitForSpinner(); + cy.wait(1000); cy.get("#comp-filter-btn").click({ force: true }); cy.selectItemById("community-select-id", "Kelowna"); // wait for the map to load - cy.waitForSpinner(); + cy.wait(1000); cy.get("div.leaflet-container").should("exist"); @@ -146,7 +146,7 @@ describe("Complaints on map tests", () => { cy.get("#map_toggle_id").should("exist").click({ force: true }); // wait for the map to load - cy.waitForSpinner(); + cy.wait(1000); // verify default filters cy.get("#comp-status-filter").should("exist"); diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 0192dba9f..07ce67069 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -34,7 +34,6 @@ "@types/react-datepicker": "^4.11.2", "@types/react-dom": "^18.0.2", "@types/react-leaflet": "^3.0.0", - "@types/react-leaflet-markercluster": "^3.0.1", "@types/react-phone-number-input": "^3.0.14", "@types/react-transition-group": "^4.4.6", "@types/redux-persist": "^4.3.1", @@ -73,6 +72,7 @@ "nrs-ce-common-types": "^1.0.10", "omggif": "^1.0.10", "os-browserify": "^0.3.0", + "overlapping-marker-spiderfier-leaflet": "^0.2.7", "path-browserify": "^1.0.1", "path-to-regexp": "^8.0.0", "prop-types-extra": "^1.1.1", @@ -89,7 +89,6 @@ "react-is": "^16.13.1", "react-leaflet": "^4.2.1", "react-leaflet-cluster": "^2.1.0", - "react-leaflet-markercluster": "^3.0.0-rc1", "react-lifecycles-compat": "^3.0.4", "react-phone-number-input": "^3.3.6", "react-redux": "^8.0.1", @@ -4623,18 +4622,18 @@ } }, "node_modules/@types/eslint-scope": { - "version": "3.7.7", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", - "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", + "version": "3.7.4", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz", + "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==", "dependencies": { "@types/eslint": "*", "@types/estree": "*" } }, "node_modules/@types/estree": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", - "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==" + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==" }, "node_modules/@types/express": { "version": "4.17.21", @@ -4778,14 +4777,6 @@ "@types/geojson": "*" } }, - "node_modules/@types/leaflet.markercluster": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/@types/leaflet.markercluster/-/leaflet.markercluster-1.5.2.tgz", - "integrity": "sha512-Yfi5R0Fb0xc/qotTuqJDAX65XKRt6DauzIdsMTcgrrhgf8DpBOrqPV/jw8/zUjY8FetRd6QdnefNdNJKmG/+zA==", - "dependencies": { - "@types/leaflet": "*" - } - }, "node_modules/@types/lodash": { "version": "4.14.195", "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.195.tgz", @@ -4897,26 +4888,6 @@ "react-leaflet": "*" } }, - "node_modules/@types/react-leaflet-markercluster": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/react-leaflet-markercluster/-/react-leaflet-markercluster-3.0.4.tgz", - "integrity": "sha512-YhN2Jts1CI31LXv+defPHvHrbIbp88ZcMwZwUUf4iRnZ/FJ1jDgb41yOuqXrnyAdwfGkm5BU4q6eBUFnh0J4Vw==", - "dependencies": { - "@types/leaflet": "*", - "@types/leaflet.markercluster": "*", - "@types/react": "*", - "@types/react-leaflet": "^2.8.3" - } - }, - "node_modules/@types/react-leaflet-markercluster/node_modules/@types/react-leaflet": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/@types/react-leaflet/-/react-leaflet-2.8.3.tgz", - "integrity": "sha512-MeBQnVQe6ikw8dkuZE4F96PvMdQeilZG6/ekk5XxhkSzU3lofedULn3UR/6G0uIHjbRazi4DA8LnLACX0bPhBg==", - "dependencies": { - "@types/leaflet": "*", - "@types/react": "*" - } - }, "node_modules/@types/react-phone-number-input": { "version": "3.0.14", "resolved": "https://registry.npmjs.org/@types/react-phone-number-input/-/react-phone-number-input-3.0.14.tgz", @@ -5535,133 +5506,133 @@ "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==" }, "node_modules/@webassemblyjs/ast": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", - "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", + "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", "dependencies": { - "@webassemblyjs/helper-numbers": "1.13.2", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2" + "@webassemblyjs/helper-numbers": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1" } }, "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", - "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==" + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", + "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==" }, "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", - "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==" + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", + "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==" }, "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", - "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==" + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", + "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==" }, "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", - "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", + "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.13.2", - "@webassemblyjs/helper-api-error": "1.13.2", + "@webassemblyjs/floating-point-hex-parser": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", "@xtuc/long": "4.2.2" } }, "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", - "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==" + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", + "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==" }, "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz", - "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", + "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-buffer": "1.14.1", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/wasm-gen": "1.14.1" + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1" } }, "node_modules/@webassemblyjs/ieee754": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", - "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", + "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", "dependencies": { "@xtuc/ieee754": "^1.2.0" } }, "node_modules/@webassemblyjs/leb128": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", - "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", + "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", "dependencies": { "@xtuc/long": "4.2.2" } }, "node_modules/@webassemblyjs/utf8": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", - "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==" + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", + "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==" }, "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz", - "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", + "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-buffer": "1.14.1", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/helper-wasm-section": "1.14.1", - "@webassemblyjs/wasm-gen": "1.14.1", - "@webassemblyjs/wasm-opt": "1.14.1", - "@webassemblyjs/wasm-parser": "1.14.1", - "@webassemblyjs/wast-printer": "1.14.1" + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/helper-wasm-section": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-opt": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "@webassemblyjs/wast-printer": "1.11.1" } }, "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", - "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", + "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/ieee754": "1.13.2", - "@webassemblyjs/leb128": "1.13.2", - "@webassemblyjs/utf8": "1.13.2" + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" } }, "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz", - "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", + "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-buffer": "1.14.1", - "@webassemblyjs/wasm-gen": "1.14.1", - "@webassemblyjs/wasm-parser": "1.14.1" + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1" } }, "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz", - "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", + "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-api-error": "1.13.2", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/ieee754": "1.13.2", - "@webassemblyjs/leb128": "1.13.2", - "@webassemblyjs/utf8": "1.13.2" + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" } }, "node_modules/@webassemblyjs/wast-printer": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz", - "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", + "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", "dependencies": { - "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/ast": "1.11.1", "@xtuc/long": "4.2.2" } }, @@ -5713,6 +5684,14 @@ "acorn-walk": "^8.0.2" } }, + "node_modules/acorn-import-assertions": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", + "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", + "peerDependencies": { + "acorn": "^8" + } + }, "node_modules/acorn-jsx": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", @@ -6723,9 +6702,9 @@ "peer": true }, "node_modules/browserslist": { - "version": "4.24.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz", - "integrity": "sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==", + "version": "4.22.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz", + "integrity": "sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==", "funding": [ { "type": "opencollective", @@ -6741,10 +6720,10 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001669", - "electron-to-chromium": "^1.5.41", - "node-releases": "^2.0.18", - "update-browserslist-db": "^1.1.1" + "caniuse-lite": "^1.0.30001565", + "electron-to-chromium": "^1.4.601", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" }, "bin": { "browserslist": "cli.js" @@ -6950,9 +6929,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001687", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001687.tgz", - "integrity": "sha512-0S/FDhf4ZiqrTUiQ39dKeUjYRjkv7lOZU1Dgif2rIqrTzX/1wV2hfKu9TOm1IHkdSijfLswxTFzl/cvir+SLSQ==", + "version": "1.0.30001570", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001570.tgz", + "integrity": "sha512-+3e0ASu4sw1SWaoCtvPeyXp+5PsjigkSt8OXZbF9StH5pQWbxEjLAZE3n8Aup5udop1uRiKA7a4utUk/uoSpUw==", "funding": [ { "type": "opencollective", @@ -7489,9 +7468,9 @@ "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" }, "node_modules/cookie": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", - "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", "peer": true, "engines": { "node": ">= 0.6" @@ -7588,9 +7567,9 @@ "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==" }, "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -8194,9 +8173,9 @@ "dev": true }, "node_modules/debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "dependencies": { "ms": "^2.1.3" }, @@ -8626,9 +8605,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.71", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.71.tgz", - "integrity": "sha512-dB68l59BI75W1BUGVTAEJy45CEVuEGy9qPVVQ8pnHyHMn36PLPPoE1mjLH+lo9rKulO3HC2OhbACI/8tCqJBcA==" + "version": "1.4.615", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.615.tgz", + "integrity": "sha512-/bKPPcgZVUziECqDc+0HkT87+0zhaWSZHNXqF8FLd2lQcptpmUFwoCSWjCdOng9Gdq+afKArPdEg/0ZW461Eng==" }, "node_modules/emittery": { "version": "0.13.1", @@ -8684,9 +8663,9 @@ } }, "node_modules/enhanced-resolve": { - "version": "5.17.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", - "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", + "version": "5.12.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz", + "integrity": "sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==", "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" @@ -8908,9 +8887,9 @@ } }, "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", "engines": { "node": ">=6" } @@ -9326,9 +9305,9 @@ } }, "node_modules/eslint-plugin-jsdoc": { - "version": "50.6.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.6.0.tgz", - "integrity": "sha512-tCNp4fR79Le3dYTPB0dKEv7yFyvGkUCa+Z3yuTrrNGGOxBlXo9Pn0PEgroOZikUQOGjxoGMVKNjrOHcYEdfszg==", + "version": "50.6.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.6.1.tgz", + "integrity": "sha512-UWyaYi6iURdSfdVVqvfOs2vdCVz0J40O/z/HTsv2sFjdjmdlUI/qlKLOTmwbPQ2tAfQnE5F9vqx+B+poF71DBQ==", "dev": true, "dependencies": { "@es-joy/jsdoccomment": "~0.49.0", @@ -10024,9 +10003,9 @@ } }, "node_modules/express": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", - "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.0.tgz", + "integrity": "sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==", "peer": true, "dependencies": { "accepts": "~1.3.8", @@ -10034,7 +10013,7 @@ "body-parser": "1.20.3", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.7.1", + "cookie": "0.6.0", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", @@ -10048,7 +10027,7 @@ "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.12", + "path-to-regexp": "0.1.10", "proxy-addr": "~2.0.7", "qs": "6.13.0", "range-parser": "~1.2.1", @@ -10063,10 +10042,6 @@ }, "engines": { "node": ">= 0.10.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" } }, "node_modules/express/node_modules/array-flatten": { @@ -10091,9 +10066,9 @@ "peer": true }, "node_modules/express/node_modules/path-to-regexp": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", - "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", + "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==", "peer": true }, "node_modules/extend": { @@ -11330,9 +11305,9 @@ } }, "node_modules/http-proxy-middleware": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.7.tgz", - "integrity": "sha512-fgVY8AV7qU7z/MmXJ/rxwbrtQH4jBQ9m7kp3llF0liB7glmFeVZFBepQb32T3y8n8k2+AEYuMPCpinYW+/CuRA==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", + "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", "peer": true, "dependencies": { "@types/http-proxy": "^1.17.8", @@ -11549,8 +11524,7 @@ "node_modules/ini": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "peer": true + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" }, "node_modules/input-format": { "version": "0.3.8", @@ -11589,27 +11563,10 @@ "loose-envify": "^1.0.0" } }, - "node_modules/ip-address": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", - "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", - "dependencies": { - "jsbn": "1.1.0", - "sprintf-js": "^1.1.3" - }, - "engines": { - "node": ">= 12" - } - }, - "node_modules/ip-address/node_modules/jsbn": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", - "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==" - }, - "node_modules/ip-address/node_modules/sprintf-js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", - "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==" + "node_modules/ip": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.1.tgz", + "integrity": "sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ==" }, "node_modules/ipaddr.js": { "version": "2.0.1", @@ -15006,11 +14963,11 @@ } }, "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", "dependencies": { - "braces": "^3.0.3", + "braces": "^3.0.2", "picomatch": "^2.3.1" }, "engines": { @@ -15447,9 +15404,9 @@ "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==" }, "node_modules/node-releases": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", - "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==" + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==" }, "node_modules/normalize-path": { "version": "3.0.0", @@ -18288,6 +18245,11 @@ "integrity": "sha512-o6E5qJV5zkAbIDNhGSIlyOhScKXgQrSRMilfph0clDfM0nEnBOlKlH4sWDmG95BW/CvwNz0vmm7dJVtU2KlMiA==", "dev": true }, + "node_modules/overlapping-marker-spiderfier-leaflet": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/overlapping-marker-spiderfier-leaflet/-/overlapping-marker-spiderfier-leaflet-0.2.7.tgz", + "integrity": "sha512-U2biV2Ge0SU+4IEmq4BZOglvzA8Aj8G7/hp5v6lBnF9Kd3/Xf6ZEPsJyPOExtLvMxOqlrlTAfl55s6JJDND7Ew==" + }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -19954,6 +19916,15 @@ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, + "node_modules/postcss/node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -20582,83 +20553,6 @@ "react-leaflet": "^4.0.0" } }, - "node_modules/react-leaflet-markercluster": { - "version": "3.0.0-rc1", - "resolved": "https://registry.npmjs.org/react-leaflet-markercluster/-/react-leaflet-markercluster-3.0.0-rc1.tgz", - "integrity": "sha512-wr8ERtx73sY0uVoQAM1v1vsA5Vsbdgyqc88h+Eo2kYRwNdkVTEOoUTnAh3CgGuOyP0Y9QLd2dKGupGkufpwryQ==", - "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", - "dependencies": { - "@react-leaflet/core": "^1.0.2", - "leaflet": "^1.6.0", - "leaflet.markercluster": "^1.4.1", - "react-leaflet": "^3.0.0" - }, - "peerDependencies": { - "leaflet": "^1.6.0", - "leaflet.markercluster": "^1.4.1", - "react-leaflet": "^3.0.0" - } - }, - "node_modules/react-leaflet-markercluster/node_modules/@react-leaflet/core": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@react-leaflet/core/-/core-1.1.1.tgz", - "integrity": "sha512-7PGLWa9MZ5x/cWy8EH2VzI4T8q5WpuHbixzCDXqixP/WyqwIrg5NDUPgYuFnB4IEIZF+6nA265mYzswFo/h1Pw==", - "peerDependencies": { - "leaflet": "^1.7.1", - "react": "^17.0.1", - "react-dom": "^17.0.1" - } - }, - "node_modules/react-leaflet-markercluster/node_modules/react": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz", - "integrity": "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==", - "peer": true, - "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-leaflet-markercluster/node_modules/react-dom": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz", - "integrity": "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==", - "peer": true, - "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "scheduler": "^0.20.2" - }, - "peerDependencies": { - "react": "17.0.2" - } - }, - "node_modules/react-leaflet-markercluster/node_modules/react-leaflet": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/react-leaflet/-/react-leaflet-3.2.5.tgz", - "integrity": "sha512-Z3KZ+4SijsRbbrt2I1a3ZDY6+V6Pm91eYTdxTN18G6IOkFRsJo1BuSPLFnyFrlF3WDjQFPEcTPkEgD1VEeAoBg==", - "dependencies": { - "@react-leaflet/core": "^1.1.1" - }, - "peerDependencies": { - "leaflet": "^1.7.1", - "react": "^17.0.1", - "react-dom": "^17.0.1" - } - }, - "node_modules/react-leaflet-markercluster/node_modules/scheduler": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz", - "integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==", - "peer": true, - "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" - } - }, "node_modules/react-lifecycles-compat": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", @@ -22784,9 +22678,9 @@ } }, "node_modules/schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.2.tgz", + "integrity": "sha512-pvjEHOgWc9OWA/f/DE3ohBWTD6EleVLf7iFUkoSwAxttdBhB9QUebQgxER2kWueOvRJXPHNnyrvvh9eZINB8Eg==", "dependencies": { "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", @@ -23145,15 +23039,15 @@ } }, "node_modules/socks": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", - "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", + "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", "dependencies": { - "ip-address": "^9.0.5", + "ip": "^2.0.0", "smart-buffer": "^4.2.0" }, "engines": { - "node": ">= 10.0.0", + "node": ">= 10.13.0", "npm": ">= 3.0.0" } }, @@ -23185,9 +23079,9 @@ } }, "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", "engines": { "node": ">=0.10.0" } @@ -23232,14 +23126,12 @@ "node_modules/spdx-exceptions": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", - "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", - "dev": true + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==" }, "node_modules/spdx-expression-parse": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-4.0.0.tgz", "integrity": "sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==", - "dev": true, "dependencies": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" @@ -23248,8 +23140,7 @@ "node_modules/spdx-license-ids": { "version": "3.0.20", "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.20.tgz", - "integrity": "sha512-jg25NiDV/1fLtSgEgyvVyDunvaNHbuwF9lfNV17gSmPFAlYzdfNBlLtLzXTevwkPj7DhGbmN9VnmJIgLnhvaBw==", - "dev": true + "integrity": "sha512-jg25NiDV/1fLtSgEgyvVyDunvaNHbuwF9lfNV17gSmPFAlYzdfNBlLtLzXTevwkPj7DhGbmN9VnmJIgLnhvaBw==" }, "node_modules/spdy": { "version": "4.0.2", @@ -24058,12 +23949,12 @@ } }, "node_modules/terser": { - "version": "5.37.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.37.0.tgz", - "integrity": "sha512-B8wRRkmre4ERucLM/uXx4MOV5cbnOlVAqUst+1+iLKPI0dOgFO28f84ptoQt9HEI537PMzfYa/d+GEPKTRXmYA==", + "version": "5.16.9", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.9.tgz", + "integrity": "sha512-HPa/FdTB9XGI2H1/keLFZHxl6WNvAI4YalHGtDQTlMnJcoqSab1UwL4l1hGEhs6/GmLHBZIg/YgB++jcbzoOEg==", "dependencies": { - "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.8.2", + "@jridgewell/source-map": "^0.3.2", + "acorn": "^8.5.0", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, @@ -24075,15 +23966,15 @@ } }, "node_modules/terser-webpack-plugin": { - "version": "5.3.10", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", - "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", + "version": "5.3.7", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.7.tgz", + "integrity": "sha512-AfKwIktyP7Cu50xNjXF/6Qb5lBNzYaWpU6YfoX3uZicTx0zTy0stDDCsvjDapKsSDvOeWo5MEq4TmdBy2cNoHw==", "dependencies": { - "@jridgewell/trace-mapping": "^0.3.20", + "@jridgewell/trace-mapping": "^0.3.17", "jest-worker": "^27.4.5", "schema-utils": "^3.1.1", "serialize-javascript": "^6.0.1", - "terser": "^5.26.0" + "terser": "^5.16.5" }, "engines": { "node": ">= 10.13.0" @@ -24721,9 +24612,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", - "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", "funding": [ { "type": "opencollective", @@ -24739,8 +24630,8 @@ } ], "dependencies": { - "escalade": "^3.2.0", - "picocolors": "^1.1.0" + "escalade": "^3.1.1", + "picocolors": "^1.0.0" }, "bin": { "update-browserslist-db": "cli.js" @@ -24948,9 +24839,9 @@ } }, "node_modules/watchpack": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz", - "integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", + "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", "dependencies": { "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" @@ -24982,32 +24873,33 @@ } }, "node_modules/webpack": { - "version": "5.97.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.97.1.tgz", - "integrity": "sha512-EksG6gFY3L1eFMROS/7Wzgrii5mBAFe4rIr3r2BTfo7bcc+DWwFZ4OJ/miOuHJO/A85HwyI4eQ0F6IKXesO7Fg==", - "dependencies": { - "@types/eslint-scope": "^3.7.7", - "@types/estree": "^1.0.6", - "@webassemblyjs/ast": "^1.14.1", - "@webassemblyjs/wasm-edit": "^1.14.1", - "@webassemblyjs/wasm-parser": "^1.14.1", - "acorn": "^8.14.0", - "browserslist": "^4.24.0", + "version": "5.79.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.79.0.tgz", + "integrity": "sha512-3mN4rR2Xq+INd6NnYuL9RC9GAmc1ROPKJoHhrZ4pAjdMFEkJJWrsPw8o2JjCIyQyTu7rTXYn4VG6OpyB3CobZg==", + "dependencies": { + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^1.0.0", + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/wasm-edit": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "acorn": "^8.7.1", + "acorn-import-assertions": "^1.7.6", + "browserslist": "^4.14.5", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.17.1", + "enhanced-resolve": "^5.10.0", "es-module-lexer": "^1.2.1", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.11", + "graceful-fs": "^4.2.9", "json-parse-even-better-errors": "^2.3.1", "loader-runner": "^4.2.0", "mime-types": "^2.1.27", "neo-async": "^2.6.2", - "schema-utils": "^3.2.0", + "schema-utils": "^3.1.0", "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.10", - "watchpack": "^2.4.1", + "terser-webpack-plugin": "^5.3.7", + "watchpack": "^2.4.0", "webpack-sources": "^3.2.3" }, "bin": { @@ -25650,9 +25542,9 @@ "peer": true }, "node_modules/workbox-build/node_modules/rollup": { - "version": "2.79.2", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.2.tgz", - "integrity": "sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ==", + "version": "2.79.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz", + "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==", "peer": true, "bin": { "rollup": "dist/bin/rollup" diff --git a/frontend/package.json b/frontend/package.json index 277a5079b..ac9077f08 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -28,7 +28,6 @@ "@types/react-datepicker": "^4.11.2", "@types/react-dom": "^18.0.2", "@types/react-leaflet": "^3.0.0", - "@types/react-leaflet-markercluster": "^3.0.1", "@types/react-phone-number-input": "^3.0.14", "@types/react-transition-group": "^4.4.6", "@types/redux-persist": "^4.3.1", @@ -67,6 +66,7 @@ "nrs-ce-common-types": "^1.0.10", "omggif": "^1.0.10", "os-browserify": "^0.3.0", + "overlapping-marker-spiderfier-leaflet": "^0.2.7", "path-browserify": "^1.0.1", "path-to-regexp": "^8.0.0", "prop-types-extra": "^1.1.1", @@ -83,7 +83,6 @@ "react-is": "^16.13.1", "react-leaflet": "^4.2.1", "react-leaflet-cluster": "^2.1.0", - "react-leaflet-markercluster": "^3.0.0-rc1", "react-lifecycles-compat": "^3.0.4", "react-phone-number-input": "^3.3.6", "react-redux": "^8.0.1", diff --git a/frontend/src/app/components/common/search-input.tsx b/frontend/src/app/components/common/search-input.tsx index 3ca9b83a5..bf53692e2 100644 --- a/frontend/src/app/components/common/search-input.tsx +++ b/frontend/src/app/components/common/search-input.tsx @@ -1,11 +1,10 @@ import { ChangeEvent, FC, KeyboardEvent, useContext, useState, useEffect } from "react"; import { InputGroup } from "react-bootstrap"; import { ComplaintFilterContext } from "@providers/complaint-filter-provider"; -import { getComplaints, getMappedComplaints } from "@store/reducers/complaints"; +import { getComplaints } from "@store/reducers/complaints"; import { generateComplaintRequestPayload } from "@components/containers/complaints/complaint-list"; import { useAppDispatch } from "@hooks/hooks"; import { SORT_TYPES } from "@constants/sort-direction"; -import { generateMapComplaintRequestPayload } from "@components/containers/complaints/complaint-map"; type Props = { complaintType: string; @@ -43,12 +42,6 @@ const SearchInput: FC = ({ complaintType, viewType, searchQuery, applySea payload = { ...payload, query: input }; dispatch(getComplaints(complaintType, payload)); - } else { - let payload = generateMapComplaintRequestPayload(complaintType, filters, "", ""); - - payload = { ...payload, query: input }; - - dispatch(getMappedComplaints(complaintType, payload)); } } }; diff --git a/frontend/src/app/components/containers/complaints/complaint-filter.tsx b/frontend/src/app/components/containers/complaints/complaint-filter.tsx index b4e01203f..722fe4f15 100644 --- a/frontend/src/app/components/containers/complaints/complaint-filter.tsx +++ b/frontend/src/app/components/containers/complaints/complaint-filter.tsx @@ -24,7 +24,7 @@ import Option from "@apptypes/app/option"; import { listActiveFilters } from "@store/reducers/app"; import UserService from "@service/user-service"; import Roles from "@apptypes/app/roles"; -import { FilterDate } from "../../common/filter-date"; +import { FilterDate } from "@components/common/filter-date"; type Props = { type: string; diff --git a/frontend/src/app/components/containers/complaints/complaint-map-with-server-side-clustering.tsx b/frontend/src/app/components/containers/complaints/complaint-map-with-server-side-clustering.tsx new file mode 100644 index 000000000..4e4a65de4 --- /dev/null +++ b/frontend/src/app/components/containers/complaints/complaint-map-with-server-side-clustering.tsx @@ -0,0 +1,174 @@ +import { FC, useState, useContext, useEffect, useCallback } from "react"; +import { useAppDispatch } from "@hooks/hooks"; +import COMPLAINT_TYPES from "@apptypes/app/complaint-types"; +import { ComplaintFilterContext } from "@providers/complaint-filter-provider"; +import { ComplaintFilters } from "@apptypes/complaints/complaint-filters/complaint-filters"; +import { ComplaintRequestPayload } from "@/app/types/complaints/complaint-filters/complaint-request-payload"; +import LeafletMapWithServerSideClustering from "@components/mapping/leaflet-map-with-server-side-clustering"; +import { generateApiParameters, get } from "@common/api"; +import config from "@/config"; +import { setMappedComplaintsCount } from "@/app/store/reducers/complaints"; + +type Props = { + type: string; + searchQuery: string; +}; + +export const generateMapComplaintRequestPayload = ( + complaintType: string, + filters: ComplaintFilters, +): ComplaintRequestPayload => { + const { + region, + zone, + community, + officer, + startDate, + endDate, + status, + species, + natureOfComplaint, + violationType, + complaintMethod, + actionTaken, + outcomeAnimal, + outcomeAnimalStartDate, + outcomeAnimalEndDate, + } = filters; + + let common = { + sortColumn: "", // sort or order has no bearing on map data + sortOrder: "", // sort or order has no bearing on map data + regionCodeFilter: region, + zoneCodeFilter: zone, + areaCodeFilter: community, + officerFilter: officer, + startDateFilter: startDate, + endDateFilter: endDate, + complaintStatusFilter: status, + actionTakenFilter: actionTaken, + outcomeAnimalStartDateFilter: outcomeAnimalStartDate, + outcomeAnimalEndDateFilter: outcomeAnimalEndDate, + }; + + switch (complaintType) { + case COMPLAINT_TYPES.ERS: + return { + ...common, + violationFilter: violationType, + complaintMethodFilter: complaintMethod, + } as ComplaintRequestPayload; + case COMPLAINT_TYPES.HWCR: + default: + return { + ...common, + speciesCodeFilter: species, + natureOfComplaintFilter: natureOfComplaint, + outcomeAnimalFilter: outcomeAnimal, + } as ComplaintRequestPayload; + } +}; + +export const ComplaintMapWithServerSideClustering: FC = ({ type, searchQuery }) => { + const dispatch = useAppDispatch(); + + const [loadingMapData, setLoadingMapData] = useState(false); + const [clusters, setClusters] = useState>([]); + const [defaultClusterView, setDefaultClusterView] = useState(); + const [unmappedCount, setUnmappedCount] = useState(0); + + //-- the state from the context is not the same state as used in the rest of the application + //-- this is self-contained, rename the state locally to make clear + const { state: filters } = useContext(ComplaintFilterContext); + + const fetchMapData = useCallback( + async ( + filters: ComplaintFilters, + searchQuery: string, + unmapped: boolean, + clusters: boolean, + zoom: number = 0, + bbox?: { + west?: number; + south?: number; + east?: number; + north?: number; + }, + ) => { + setLoadingMapData(true); + let payload = generateMapComplaintRequestPayload(type, filters); + + let parms: any = { + bbox: bbox ? `${bbox.west},${bbox.south},${bbox.east},${bbox.north}` : undefined, // If the bbox is not provided, return all complaint clusters + zoom: zoom, + region: payload.regionCodeFilter?.value, + zone: payload.zoneCodeFilter?.value, + community: payload.areaCodeFilter?.value, + officerAssigned: payload.officerFilter?.value, + natureOfComplaint: payload.natureOfComplaintFilter?.value, + speciesCode: payload.speciesCodeFilter?.value, + incidentReportedStart: payload.startDateFilter, + incidentReportedEnd: payload.endDateFilter, + violationCode: payload.violationFilter?.value, + status: payload.complaintStatusFilter?.value, + complaintMethod: payload.complaintMethodFilter?.value, + actionTaken: payload.actionTakenFilter?.value, + outcomeAnimal: payload.outcomeAnimalFilter?.value, + outcomeAnimalStartDate: payload.outcomeAnimalStartDateFilter, + outcomeAnimalEndDate: payload.outcomeAnimalEndDateFilter, + query: searchQuery, + }; + + // For a boolean any value including "false" is interpreted as true by our API + if (unmapped) { + parms = { ...parms, unmapped: true }; + } + if (clusters) { + parms = { ...parms, clusters: true }; + } + + let parameters = generateApiParameters(`${config.API_BASE_URL}/v1/complaint/map/search/clustered/${type}`, parms); + + const response: any = await get(dispatch, parameters, {}, false); + if (response) { + response.unmappedCount != null && setUnmappedCount(response.unmappedCount); + // If there is no bounding box, update totals + bbox === undefined && + dispatch( + setMappedComplaintsCount({ + ...(response.mappedCount != null && { mapped: response.mappedCount }), + ...(response.unmappedCount != null && { unmapped: response.unmappedCount }), + }), + ); + response.clusters && setClusters(response.clusters); + if (response.zoom && response.center) { + setDefaultClusterView({ zoom: response.zoom, center: response.center }); + } + } + setLoadingMapData(false); + }, + [dispatch, type], + ); + + useEffect(() => { + //Update map when filters or searchQuery change + fetchMapData(filters, searchQuery, false, true); + fetchMapData(filters, searchQuery, true, false); + }, [fetchMapData, filters, searchQuery]); + + const handleMapMoved = (zoom: number, west?: number, south?: number, east?: number, north?: number) => { + setDefaultClusterView(undefined); // Clear the default cluster view when the map is moved + fetchMapData(filters, searchQuery, false, true, zoom, { west, south, east, north }); + }; + + return ( + + ); +}; diff --git a/frontend/src/app/components/containers/complaints/complaint-map.tsx b/frontend/src/app/components/containers/complaints/complaint-map.tsx deleted file mode 100644 index 63c872f42..000000000 --- a/frontend/src/app/components/containers/complaints/complaint-map.tsx +++ /dev/null @@ -1,126 +0,0 @@ -import { FC, useState, useContext, useEffect } from "react"; -import { useAppDispatch, useAppSelector } from "@hooks/hooks"; -import COMPLAINT_TYPES from "@apptypes/app/complaint-types"; -import { SORT_TYPES } from "@constants/sort-direction"; -import { ComplaintFilterContext } from "@providers/complaint-filter-provider"; -import { ComplaintFilters } from "@apptypes/complaints/complaint-filters/complaint-filters"; -import { ComplaintRequestPayload } from "@/app/types/complaints/complaint-filters/complaint-request-payload"; -import LeafletMapWithMultiplePoints from "@components/mapping/leaflet-map-with-multiple-points"; -import { - getMappedComplaints, - selectMappedComplaints, - selectTotalUnmappedComplaints, - setMappedComplaints, -} from "@store/reducers/complaints"; - -type Props = { - type: string; - searchQuery: string; -}; - -export const generateMapComplaintRequestPayload = ( - complaintType: string, - filters: ComplaintFilters, - sortKey: string, - sortDirection: string, -): ComplaintRequestPayload => { - const { - region, - zone, - community, - officer, - startDate, - endDate, - status, - species, - natureOfComplaint, - violationType, - complaintMethod, - actionTaken, - outcomeAnimal, - outcomeAnimalStartDate, - outcomeAnimalEndDate, - } = filters; - - const common = { - sortColumn: sortKey, - sortOrder: sortDirection, - regionCodeFilter: region, - zoneCodeFilter: zone, - areaCodeFilter: community, - officerFilter: officer, - startDateFilter: startDate, - endDateFilter: endDate, - complaintStatusFilter: status, - actionTakenFilter: actionTaken, - }; - - switch (complaintType) { - case COMPLAINT_TYPES.ERS: - return { - ...common, - violationFilter: violationType, - complaintMethodFilter: complaintMethod, - } as ComplaintRequestPayload; - case COMPLAINT_TYPES.HWCR: - default: - return { - ...common, - speciesCodeFilter: species, - natureOfComplaintFilter: natureOfComplaint, - outcomeAnimalFilter: outcomeAnimal, - outcomeAnimalStartDateFilter: outcomeAnimalStartDate, - outcomeAnimalEndDateFilter: outcomeAnimalEndDate, - } as ComplaintRequestPayload; - } -}; - -export const ComplaintMap: FC = ({ type, searchQuery }) => { - const dispatch = useAppDispatch(); - - const complaints = useAppSelector(selectMappedComplaints); - const unmappedComplaints = useAppSelector(selectTotalUnmappedComplaints); - - //-- the state from the context is not the same state as used in the rest of the application - //-- this is self-contained, rename the state locally to make clear - const { state: filters } = useContext(ComplaintFilterContext); - - const [sortKey, setSortKey] = useState("incident_reported_utc_timestmp"); - const [sortDirection, setSortDirection] = useState(SORT_TYPES.DESC); - - useEffect(() => { - //Update map when filters change - let payload = generateMapComplaintRequestPayload(type, filters, sortKey, sortDirection); - - if (searchQuery) { - payload = { ...payload, query: searchQuery }; - } - - dispatch(getMappedComplaints(type, payload)); - }, [filters]); - - useEffect(() => { - //when the search Query is cleared refresh the map - if (!searchQuery) { - let payload = generateMapComplaintRequestPayload(type, filters, sortKey, sortDirection); - payload = { ...payload, query: searchQuery }; - - dispatch(getMappedComplaints(type, payload)); - } - }, [searchQuery]); - - useEffect(() => { - //-- when the component unmounts clear the complaint from redux - return () => { - dispatch(setMappedComplaints({ type: { type }, data: [] })); - }; - }, []); - - return ( - - ); -}; diff --git a/frontend/src/app/components/containers/complaints/complaints.tsx b/frontend/src/app/components/containers/complaints/complaints.tsx index aaba36ed7..91ecbf986 100644 --- a/frontend/src/app/components/containers/complaints/complaints.tsx +++ b/frontend/src/app/components/containers/complaints/complaints.tsx @@ -19,7 +19,7 @@ import { setActiveComplaintsViewType, } from "../../../store/reducers/app"; -import { ComplaintMap } from "./complaint-map"; +import { ComplaintMapWithServerSideClustering } from "./complaint-map-with-server-side-clustering"; import { useNavigate } from "react-router-dom"; import { ComplaintListTabs } from "./complaint-list-tabs"; import { COMPLAINT_TYPES, CEEB_TYPES } from "@apptypes/app/complaint-types"; @@ -45,7 +45,7 @@ export const Complaints: FC = ({ defaultComplaintType }) => { if (!storedComplaintType) dispatch(setActiveTab(defaultComplaintType)); }, [storedComplaintType, dispatch, defaultComplaintType]); const [complaintType, setComplaintType] = useState( - UserService.hasRole([Roles.CEEB]) ? CEEB_TYPES.ERS : storedComplaintType ?? defaultComplaintType, + UserService.hasRole([Roles.CEEB]) ? CEEB_TYPES.ERS : (storedComplaintType ?? defaultComplaintType), ); const storedComplaintViewType = useAppSelector(selectActiveComplaintsViewType); @@ -154,7 +154,7 @@ export const Complaints: FC = ({ defaultComplaintType }) => { searchQuery={search} /> ) : ( - diff --git a/frontend/src/app/components/mapping/leaflet-map-with-multiple-points.tsx b/frontend/src/app/components/mapping/leaflet-map-with-multiple-points.tsx deleted file mode 100644 index afaac287f..000000000 --- a/frontend/src/app/components/mapping/leaflet-map-with-multiple-points.tsx +++ /dev/null @@ -1,142 +0,0 @@ -import React, { useEffect, useRef, useState } from "react"; -import { MapContainer, TileLayer, Marker } from "react-leaflet"; -import MarkerClusterGroup from "react-leaflet-cluster"; -import "leaflet/dist/leaflet.css"; -import "react-leaflet-markercluster/dist/styles.min.css"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import ReactDOMServer from "react-dom/server"; -import { faMapMarkerAlt } from "@fortawesome/free-solid-svg-icons"; -import Leaflet, { LatLngExpression, Map } from "leaflet"; -import { ComplaintSummaryPopup } from "./complaint-summary-popup"; -import { useAppDispatch } from "@hooks/hooks"; -import { getComplaintById, setComplaint } from "@store/reducers/complaints"; -import { isEqual } from "lodash"; -import { BsInfoCircleFill } from "react-icons/bs"; -import { ComplaintMapItem } from "@apptypes/app/complaints/complaint-map-item"; -import { from } from "linq-to-typescript"; -import { MapGestureHandler } from "./map-gesture-handler"; -import { Alert } from "react-bootstrap"; - -interface MapProps { - complaintType: string; - markers: Array; - unmappedComplaints: number; -} - -const LeafletMapWithMultiplePoints: React.FC = ({ complaintType, markers, unmappedComplaints }) => { - const iconHTML = ReactDOMServer.renderToString(); - const mapRef = useRef(null); - const [markersState, setMarkersState] = useState>(markers); - - useEffect(() => { - if (mapRef.current && markersState.length > 0) { - // Calculate the bounds of all markers - const bounds = Leaflet.latLngBounds( - markersState.map((marker) => [marker.latitude, marker.longitude] as LatLngExpression), - ); - - // Fit the map to the bounds - mapRef.current.fitBounds(bounds, { padding: [35, 35] }); - } - }, [markersState]); - - // redux will update the location store when the complaint details are retrieved. We don't want this to trigger - // a re-render of the map to fit the markers on screen. So, let's compare the new markers against the marker state. - // If they're the same, don't re-center the map and don't zoom out. - useEffect(() => { - if (!isEqual(markersState, markers)) { - setMarkersState(markers); - } - }, [markers, markersState]); - - const customMarkerIcon = new Leaflet.DivIcon({ - html: iconHTML, - className: "map-marker", - iconSize: [40, 0], // Adjust icon size as needed - iconAnchor: [20, 40], // Adjust icon anchor point - }); - - const dispatch = useAppDispatch(); - - const handlePopupOpen = (id: string) => (e: L.PopupEvent) => { - dispatch(getComplaintById(id, complaintType)); - }; - - const handlePopupClose = (e: L.LeafletEvent) => { - dispatch(setComplaint(null)); - }; - - const renderInformationBanner = () => { - const showBar = () => { - if (unmappedComplaints >= 1) { - return true; - } else if (!from(markers).any()) { - return true; - } else { - return false; - } - }; - - const isPluralized = unmappedComplaints === 1 ? "" : "s"; - - if (showBar()) { - const bannerType = unmappedComplaints >= 1 ? "unmapped" : "no-results"; - const info = - unmappedComplaints >= 1 - ? `${unmappedComplaints} complaint${isPluralized} could not be mapped` - : "No complaints found using your current filters. Remove or change your filters to see complaints."; - - return ( - - - {info} - - ); - } - - return <>; - }; - - return ( -
- {renderInformationBanner()} - - - - - {markers.map((marker) => ( - - - - ))} - - -
- ); -}; - -export default LeafletMapWithMultiplePoints; diff --git a/frontend/src/app/components/mapping/leaflet-map-with-server-side-clustering.tsx b/frontend/src/app/components/mapping/leaflet-map-with-server-side-clustering.tsx new file mode 100644 index 000000000..679b83bcc --- /dev/null +++ b/frontend/src/app/components/mapping/leaflet-map-with-server-side-clustering.tsx @@ -0,0 +1,226 @@ +import React, { useEffect, useRef, useState } from "react"; +import { MapContainer, TileLayer, Marker, useMapEvents } from "react-leaflet"; +import "leaflet/dist/leaflet.css"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import ReactDOMServer from "react-dom/server"; +import { faMapMarkerAlt } from "@fortawesome/free-solid-svg-icons"; +import Leaflet, { LatLngExpression, Map } from "leaflet"; +import { ComplaintSummaryPopup } from "./complaint-summary-popup"; +import { useAppDispatch, useAppSelector } from "@hooks/hooks"; +import { getComplaintById, setComplaint } from "@store/reducers/complaints"; +import { from } from "linq-to-typescript"; +import { MapGestureHandler } from "./map-gesture-handler"; +import { Alert, Spinner } from "react-bootstrap"; +import { isLoading } from "@store/reducers/app"; +import Spiderfy from "./spiderfy"; + +interface MapProps { + complaintType: string; + handleMapMoved: (zoom: number, west: number, south: number, east: number, north: number) => void; + loadingMapData: boolean; + clusters: Array; + defaultClusterView: any; + unmappedCount: number; +} + +const LeafletMapWithServerSideClustering: React.FC = ({ + complaintType, + loadingMapData, + handleMapMoved, + clusters, + defaultClusterView, + unmappedCount, +}) => { + const loading = useAppSelector(isLoading); + + const iconHTML = ReactDOMServer.renderToString(); + const mapRef = useRef(null); + + const [popupOpen, setPopupOpen] = useState(false); + + const customMarkerIcon = new Leaflet.DivIcon({ + html: iconHTML, + className: "map-marker", + iconSize: [40, 0], // Adjust icon size as needed + iconAnchor: [20, 40], // Adjust icon anchor point + }); + + const dispatch = useAppDispatch(); + + const handlePopupOpen = (id: string) => { + dispatch(getComplaintById(id, complaintType)); + setPopupOpen(true); + }; + + const handlePopupClose = () => { + dispatch(setComplaint(null)); + setPopupOpen(false); + refreshMapData(); + }; + + useEffect(() => { + setPopupOpen(false); + if (defaultClusterView) { + if (clusters.length > 0) { + // Calculate the bounds of all markers + const bounds = Leaflet.latLngBounds( + clusters.map( + (marker) => [marker.geometry.coordinates[1], marker.geometry.coordinates[0]] as LatLngExpression, + ), + ); + + // Fit the map to the bounds + mapRef?.current?.fitBounds(bounds, { padding: [35, 35] }); + } else if (defaultClusterView.center && defaultClusterView.zoom) { + mapRef?.current?.setView(defaultClusterView.center, defaultClusterView.zoom); + } + } + }, [clusters, defaultClusterView]); + + const renderInformationBanner = () => { + const isPluralized = unmappedCount === 1 ? "" : "s"; + + const bannerType = unmappedCount >= 1 ? "unmapped" : "no-results"; + const info = + unmappedCount >= 1 + ? `${unmappedCount} complaint${isPluralized} could not be mapped` + : "No complaints found using your current filters. Remove or change your filters to see complaints."; + + return ( + + + {info} + + ); + }; + + const refreshMapData = () => { + const bounds = mapRef.current?.getBounds(); + if (bounds && mapRef?.current) { + handleMapMoved( + mapRef.current.getZoom(), + bounds.getWest(), + bounds.getSouth(), + bounds.getEast(), + bounds.getNorth(), + ); + } + }; + + const ServerSideClusteringHandler = () => { + useMapEvents({ + moveend: () => { + if (!popupOpen && !loading) { + refreshMapData(); + } + }, + }); + + return null; + }; + + const showInfoBar = unmappedCount >= 1 || !from(clusters).any(); + + return ( +
+ {showInfoBar && renderInformationBanner()} + {loadingMapData && !loading && ( + + )} + + + + + + {clusters.map((cluster) => { + const [longitude, latitude] = cluster.geometry.coordinates; + const { + id: clusterId, + cluster: isCluster, + point_count: pointCount, + point_count_abbreviated: pointCountAbbreviated, + zoom: clusterZoom, + } = cluster.properties; + let size; + if (pointCount < 5) { + size = "small"; + } else if (pointCount < 50) { + size = "medium"; + } else { + size = "large"; + } + + const customClusterIcon = new Leaflet.DivIcon({ + html: `
${pointCountAbbreviated}
`, + className: `marker-cluster marker-cluster-${size}`, + iconSize: [40, 40], + }); + + return isCluster ? ( + { + // What even is this logic + const flyToZoom = + (clusterZoom && Math.min(clusterZoom, 18)) || + Math.min(clusterZoom, Math.min((mapRef?.current?.getZoom() || 18) + 2, 18)); + + // If we're not fully zoomed in, zoom in to the cluster + mapRef.current?.flyTo([latitude, longitude], flyToZoom, { + duration: 0.5, + easeLinearity: 0.5, + }); + }, + }} + /> + ) : ( + { + event.target.closePopup(); + }, + }} + > + + + ); + })} +
+
+
+ ); +}; + +export default LeafletMapWithServerSideClustering; diff --git a/frontend/src/app/components/mapping/spiderfy.tsx b/frontend/src/app/components/mapping/spiderfy.tsx new file mode 100644 index 000000000..6dc8c8482 --- /dev/null +++ b/frontend/src/app/components/mapping/spiderfy.tsx @@ -0,0 +1,70 @@ +import React, { useEffect } from "react"; +import { useMap } from "react-leaflet"; +import L from "leaflet"; + +// Hacky, but there is no ES6 module for this library +import "overlapping-marker-spiderfier-leaflet/dist/oms"; +declare global { + interface Window { + OverlappingMarkerSpiderfier: any; + } +} + +interface SpiderfyProps { + onSpiderfy?: (markers: any[]) => void; + onUnspiderfy?: (markers: any) => void; + onClick?: (marker: any) => void; + handlePopupOpen?: (id: string) => void; + handlePopupClose?: () => void; + children?: React.ReactNode; +} + +const Spiderfy = (props: SpiderfyProps) => { + const map = useMap(); + // Get the OverlappingMarkerSpiderfier from the window object + const OverlappingMarkerSpiderfier = window.OverlappingMarkerSpiderfier; + // Create a new instance of the OverlappingMarkerSpiderfier whenever we get a new map instnace + const oms = React.useMemo(() => new OverlappingMarkerSpiderfier(map), [OverlappingMarkerSpiderfier, map]); + + // When the props change, we need to clear then rebind the event listeners again + useEffect(() => { + oms.clearListeners("spiderfy"); + oms.addListener("spiderfy", (markers: any[]) => { + markers.forEach((m) => m.closePopup()); //force to close popup + if (props.onSpiderfy) props.onSpiderfy(markers); + }); + + oms.clearListeners("unspiderfy"); + oms.addListener("unspiderfy", (markers: any) => { + if (props.onUnspiderfy) props.onUnspiderfy(markers); + }); + + oms.clearListeners("click"); + oms.addListener("click", (marker: any) => { + // Hacky, but event listeners here always run first before the map click event listener resulting in the popup never opening + // so we will delay by 100ms + setTimeout(() => { + // Hacky, but alt is being used to store the complaint id. Maybe later we could create + // our own custom marker class to add but it's not clear that will work with the spiderfier library used here + props.handlePopupOpen && props.handlePopupOpen(marker.options.alt); + marker.openPopup(); + marker.addOneTimeEventListener("popupclose", props.handlePopupClose); + }, 100); + + if (props.onClick) props.onClick(marker); + }); + }, [oms, props]); + + useEffect(() => { + map.eachLayer((layer) => { + // Hacky, but "RiseOnHover" is being used to identify non-clustered markers that should be spiderfied. + if (layer instanceof L.Marker && layer?.options?.riseOnHover) { + oms.addMarker(layer); + } + }); + }, [oms, map, props.children]); + + return
{props.children}
; +}; + +export default Spiderfy; diff --git a/frontend/src/app/store/migrations.ts b/frontend/src/app/store/migrations.ts index dca1ae84d..1702f4505 100644 --- a/frontend/src/app/store/migrations.ts +++ b/frontend/src/app/store/migrations.ts @@ -21,6 +21,7 @@ import { AddCat1TypeAndLocationType } from "./migrations/migration-21"; import { AddActiveComplaintsViewType } from "./migrations/migration-22"; import { AssessmentTypeUpdates } from "./migrations/migration-23"; import { AddComsEnrolledInd } from "./migrations/migration-24"; +import { UpdateMapLogicForClustering } from "./migrations/migration-25"; const BaseMigration = { 0: (state: any) => { @@ -56,6 +57,7 @@ migration = { ...AddActiveComplaintsViewType, ...AssessmentTypeUpdates, ...AddComsEnrolledInd, + ...UpdateMapLogicForClustering, }; export default migration; diff --git a/frontend/src/app/store/migrations/migration-25.ts b/frontend/src/app/store/migrations/migration-25.ts new file mode 100644 index 000000000..5a0626dba --- /dev/null +++ b/frontend/src/app/store/migrations/migration-25.ts @@ -0,0 +1,12 @@ +// Refresh the profile for coms access indicator +export const UpdateMapLogicForClustering = { + 25: (state: any) => { + return { + ...state, + complaints: { + ...state.complaints, + mappedComplaintsCount: { mapped: 0, unmapped: 0 }, + }, + }; + }, +}; diff --git a/frontend/src/app/store/reducers/complaints.ts b/frontend/src/app/store/reducers/complaints.ts index 8d9eb94a9..3e6c58f84 100644 --- a/frontend/src/app/store/reducers/complaints.ts +++ b/frontend/src/app/store/reducers/complaints.ts @@ -18,9 +18,6 @@ import { ToggleSuccess, ToggleError } from "@common/toast"; import { ComplaintSearchResults } from "@apptypes/api-params/complaint-results"; import { Coordinates } from "@apptypes/app/coordinate-type"; -import { MapSearchResults } from "@apptypes/complaints/map-return"; -import { ComplaintMapItem } from "@apptypes/app/complaints/complaint-map-item"; - import { WildlifeComplaint as WildlifeComplaintDto } from "@apptypes/app/complaints/wildlife-complaint"; import { AllegationComplaint as AllegationComplaintDto } from "@apptypes/app/complaints/allegation-complaint"; import { Complaint as ComplaintDto } from "@apptypes/app/complaints/complaint"; @@ -63,7 +60,7 @@ const initialState: ComplaintState = { allegation: { assigned: 0, unassigned: 0, total: 0, offices: [] }, }, - mappedItems: { items: [], unmapped: 0 }, + mappedComplaintsCount: { mapped: 0, unmapped: 0 }, webeocUpdates: [], actions: [], @@ -209,21 +206,22 @@ export const complaintSlice = createSlice({ return { ...state, complaintItems: updatedItems }; } }, - setMappedComplaints: (state, action) => { - const { mappedItems } = state; + setMappedComplaintsCount: (state, action) => { + const { mappedComplaintsCount } = current(state); const { - payload: { complaints, unmappedComplaints }, + payload: { mapped, unmapped }, } = action; const update = { - ...mappedItems, - items: complaints, - unmapped: unmappedComplaints, + mapped: mapped ?? mappedComplaintsCount.mapped, + unmapped: unmapped ?? mappedComplaintsCount.unmapped, }; - return { ...state, mappedItems: update }; + return { + ...state, + mappedComplaintsCount: update, + }; }, - setWebEOCUpdates: (state, action: PayloadAction) => { return { ...state, webeocUpdates: action.payload }; }, @@ -268,7 +266,7 @@ export const { updateGeneralComplaintByRow, updateAllegationComplaintByRow, updateGeneralIncidentComplaintByRow, - setMappedComplaints, + setMappedComplaintsCount, setWebEOCUpdates, setRelatedData, setActions, @@ -349,67 +347,6 @@ export const getComplaints = } }; -export const getMappedComplaints = - (complaintType: string, payload: ComplaintFilters): AppThunk => - async (dispatch, getState) => { - const { - sortColumn, - sortOrder, - regionCodeFilter, - areaCodeFilter, - zoneCodeFilter, - officerFilter, - natureOfComplaintFilter, - speciesCodeFilter, - startDateFilter, - endDateFilter, - violationFilter, - complaintStatusFilter, - complaintMethodFilter, - actionTakenFilter, - outcomeAnimalFilter, - outcomeAnimalStartDateFilter, - outcomeAnimalEndDateFilter, - page, - pageSize, - query, - } = payload; - - try { - dispatch(setComplaint(null)); - dispatch(setComplaintSearchParameters(payload)); - - let parameters = generateApiParameters(`${config.API_BASE_URL}/v1/complaint/map/search/${complaintType}`, { - sortBy: sortColumn, - orderBy: sortOrder, - region: regionCodeFilter?.value, - zone: zoneCodeFilter?.value, - community: areaCodeFilter?.value, - officerAssigned: officerFilter?.value, - natureOfComplaint: natureOfComplaintFilter?.value, - speciesCode: speciesCodeFilter?.value, - incidentReportedStart: startDateFilter, - incidentReportedEnd: endDateFilter, - violationCode: violationFilter?.value, - status: complaintStatusFilter?.value, - complaintMethod: complaintMethodFilter?.value, - actionTaken: actionTakenFilter?.value, - outcomeAnimal: outcomeAnimalFilter?.value, - outcomeAnimalStartDate: outcomeAnimalStartDateFilter, - outcomeAnimalEndDate: outcomeAnimalEndDateFilter, - page: page, - pageSize: pageSize, - query: query, - }); - - const response = await get(dispatch, parameters); - - dispatch(setMappedComplaints(response)); - } catch (error) { - console.log(`Unable to retrieve ${complaintType} complaints: ${error}`); - } - }; - export const getZoneAtAGlanceStats = (zone: string, type: ComplaintType): AppThunk => async (dispatch) => { @@ -823,45 +760,10 @@ export const selectComplaintsByType = export const selectTotalMappedComplaints = (state: RootState): number => { const { complaints: { - mappedItems: { items, unmapped }, - }, - } = state; - if (!items && !unmapped) return 0; - return items.length + unmapped; -}; - -export const selectTotalUnmappedComplaints = (state: RootState): number => { - const { - complaints: { - mappedItems: { unmapped }, + mappedComplaintsCount: { mapped, unmapped }, }, } = state; - - return unmapped; -}; - -export const selectMappedComplaints = (state: RootState): Array => { - const { - complaints: { - mappedItems: { items }, - }, - } = state; - - if (items) { - const records = items.map(({ id, location: { coordinates } }) => { - const record: ComplaintMapItem = { - id, - latitude: coordinates[Coordinates.Latitude], - longitude: coordinates[Coordinates.Longitude], - }; - - return record; - }); - - return records; - } else { - return new Array(); - } + return mapped + unmapped; }; export const selectComplaint = ( diff --git a/frontend/src/app/store/store.ts b/frontend/src/app/store/store.ts index 78085adba..41e8b0690 100644 --- a/frontend/src/app/store/store.ts +++ b/frontend/src/app/store/store.ts @@ -19,7 +19,7 @@ const persistConfig = { storage, blacklist: ["app"], whitelist: ["codeTables", "officers"], - version: 24, // This needs to be incremented every time a new migration is added + version: 25, // This needs to be incremented every time a new migration is added debug: true, migrate: createMigrate(migration, { debug: false }), }; diff --git a/frontend/src/app/types/complaints/complaint-filters/complaint-request-payload.ts b/frontend/src/app/types/complaints/complaint-filters/complaint-request-payload.ts index 256e760af..2d1f0506f 100644 --- a/frontend/src/app/types/complaints/complaint-filters/complaint-request-payload.ts +++ b/frontend/src/app/types/complaints/complaint-filters/complaint-request-payload.ts @@ -13,5 +13,10 @@ export interface ComplaintRequestPayload { startDateFilter?: Date; endDateFilter?: Date; complaintStatusFilter?: Option; + complaintMethodFilter?: Option; + actionTakenFilter?: Option; + outcomeAnimalFilter?: Option; + outcomeAnimalStartDateFilter?: Date; + outcomeAnimalEndDateFilter?: Date; query?: string; } diff --git a/frontend/src/app/types/complaints/map-return.ts b/frontend/src/app/types/complaints/map-return.ts index 3edf9325d..5eec575bc 100644 --- a/frontend/src/app/types/complaints/map-return.ts +++ b/frontend/src/app/types/complaints/map-return.ts @@ -1,9 +1,8 @@ -import { WildlifeComplaint } from "@apptypes/app/complaints/wildlife-complaint"; -import { AllegationComplaint as AllegationComplaintModel } from "@apptypes/app/complaints/allegation-complaint"; -import { AllegationComplaint } from "./allegation-complaint"; -import { HwcrComplaint } from "./hwcr-complaint"; - export interface MapSearchResults { - complaints: HwcrComplaint[] | AllegationComplaint[] | Array | Array; - unmappedComplaints: number; + clusters?: any; + mappedCount?: number; + unmappedCount?: number; + zoom?: number; + center?: Array; + debugLog?: string; } diff --git a/frontend/src/app/types/state/complaint-state.ts b/frontend/src/app/types/state/complaint-state.ts index 70411cf7d..503ef8b57 100644 --- a/frontend/src/app/types/state/complaint-state.ts +++ b/frontend/src/app/types/state/complaint-state.ts @@ -15,7 +15,7 @@ export interface ComplaintState { complaint: WildlifeComplaintDto | AllegationComplaintDto | GeneralInformationComplaintDto | null; zoneAtGlance: ZoneAtAGlanceState; complaintLocation: Feature | null; - mappedItems: MappedComplaintsState; + mappedComplaintsCount: MappedComplaintsCountState; webeocUpdates: WebEOCComplaintUpdateDTO[]; actions: ActionTaken[]; webeocChangeCount: number; @@ -28,8 +28,8 @@ export interface ComplaintCollection { general: Array; } -export interface MappedComplaintsState { - items: Array | Array | Array; +export interface MappedComplaintsCountState { + mapped: number; unmapped: number; } diff --git a/frontend/src/assets/sass/maps.scss b/frontend/src/assets/sass/maps.scss index 22145670b..5c37e18ae 100644 --- a/frontend/src/assets/sass/maps.scss +++ b/frontend/src/assets/sass/maps.scss @@ -182,3 +182,51 @@ color: #fff; } } + +.marker-cluster-small { + background-color: rgba(181, 226, 140, 0.6); +} + +.marker-cluster-small div { + background-color: rgba(110, 204, 57, 0.6); +} + +.marker-cluster-medium { + background-color: rgba(241, 211, 87, 0.6); +} + +.marker-cluster-medium div { + background-color: rgba(240, 194, 12, 0.6); +} + +.marker-cluster-large { + background-color: rgba(253, 156, 115, 0.6); +} + +.marker-cluster-large div { + background-color: rgba(241, 128, 23, 0.6); +} + +.marker-cluster { + background-clip: padding-box; + border-radius: 20px; +} + +.marker-cluster div { + width: 30px; + height: 30px; + margin-left: 5px; + margin-top: 5px; + + text-align: center; + border-radius: 15px; + font: + 12px "Helvetica Neue", + Arial, + Helvetica, + sans-serif; +} + +.marker-cluster span { + line-height: 30px; +} diff --git a/webeoc/package-lock.json b/webeoc/package-lock.json index ad3f2265c..4907510f3 100644 --- a/webeoc/package-lock.json +++ b/webeoc/package-lock.json @@ -1,12 +1,12 @@ { "name": "webeoc", - "version": "0.0.1", + "version": "0.28.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "webeoc", - "version": "0.0.1", + "version": "0.28.1", "license": "UNLICENSED", "dependencies": { "@nestjs/axios": "^3.0.3", diff --git a/webeoc/test/app.e2e-spec.ts b/webeoc/test/app.e2e-spec.ts index dde7438bb..c8e59103f 100644 --- a/webeoc/test/app.e2e-spec.ts +++ b/webeoc/test/app.e2e-spec.ts @@ -1,6 +1,6 @@ import { Test, TestingModule } from "@nestjs/testing"; import { INestApplication } from "@nestjs/common"; -import * as request from "supertest"; +import request from "supertest"; import { AppModule } from "./../src/app.module"; describe("AppController (e2e)", () => { From 5371a9d63038148aa7b837e3144b4cda6568ae44 Mon Sep 17 00:00:00 2001 From: Ryan Rondeau Date: Wed, 11 Dec 2024 09:20:14 -0800 Subject: [PATCH 2/4] chore: Adjust cpu requets for backend (#815) --- charts/app/templates/backend/templates/deployment.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/charts/app/templates/backend/templates/deployment.yaml b/charts/app/templates/backend/templates/deployment.yaml index 4b52a7e1a..667b3e197 100644 --- a/charts/app/templates/backend/templates/deployment.yaml +++ b/charts/app/templates/backend/templates/deployment.yaml @@ -97,7 +97,7 @@ spec: cpu: 450m memory: 150Mi requests: - cpu: 150m + cpu: 75m memory: 75Mi {{- with .Values.backend.nodeSelector }} nodeSelector: From 7600ddf661b605cdaef3695bce50c4328781ccb5 Mon Sep 17 00:00:00 2001 From: dmitri-korin-bcps <108112696+dmitri-korin-bcps@users.noreply.github.com> Date: Wed, 11 Dec 2024 10:26:32 -0800 Subject: [PATCH 3/4] fix: CE-1308-and-CE-1307 (#812) Co-authored-by: afwilcox --- .../outcomes/oucome-by-animal/edit-outcome.tsx | 16 ++++++++++++---- .../standalone-cancel-confirm-modal.tsx | 15 +++++++++++++-- 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/frontend/src/app/components/containers/complaints/outcomes/oucome-by-animal/edit-outcome.tsx b/frontend/src/app/components/containers/complaints/outcomes/oucome-by-animal/edit-outcome.tsx index 1df54a955..2c534c448 100644 --- a/frontend/src/app/components/containers/complaints/outcomes/oucome-by-animal/edit-outcome.tsx +++ b/frontend/src/app/components/containers/complaints/outcomes/oucome-by-animal/edit-outcome.tsx @@ -543,9 +543,13 @@ export const EditOutcome: FC = ({ id, index, outcome, assignedOfficer: of placeholder={"Select"} value={getDropdownOption(data.outcome, outcomes)} onChange={(evt) => { - showEditWarning(() => { + if (data?.outcome) { + showEditWarning(() => { + updateModel("outcome", evt?.value); + }); + } else { updateModel("outcome", evt?.value); - }); + } }} defaultOption={getDropdownOption(data.outcome, outcomes)} /> @@ -591,9 +595,13 @@ export const EditOutcome: FC = ({ id, index, outcome, assignedOfficer: of id="equipment-day-set" maxDate={new Date()} onChange={(input: Date) => { - showEditWarning(() => { + if (data?.date) { + showEditWarning(() => { + handleOutcomeDateChange(input); + }); + } else { handleOutcomeDateChange(input); - }); + } }} selectedDate={data?.date} placeholder={"Select"} diff --git a/frontend/src/app/components/modal/instances/standalone-cancel-confirm-modal.tsx b/frontend/src/app/components/modal/instances/standalone-cancel-confirm-modal.tsx index 8466bd337..59d778259 100644 --- a/frontend/src/app/components/modal/instances/standalone-cancel-confirm-modal.tsx +++ b/frontend/src/app/components/modal/instances/standalone-cancel-confirm-modal.tsx @@ -3,7 +3,7 @@ //-- where unable to use the global redux modals //-- -import { FC } from "react"; +import { FC, useEffect, useState } from "react"; import { Button, Col, Modal, Row } from "react-bootstrap"; type props = { @@ -25,11 +25,22 @@ export const StandaloneConfirmCancelModal: FC = ({ confirm, cancel, }) => { + const [showModal, setShowModal] = useState(false); + + useEffect(() => { + setShowModal(show); + }, [show]); + + const handleClose = () => { + cancel(); + }; + return ( {title && ( From ed8d13049bd1aa1aeb6f613ad34bb0899d20b3f8 Mon Sep 17 00:00:00 2001 From: afwilcox Date: Wed, 11 Dec 2024 11:02:23 -0800 Subject: [PATCH 4/4] chore: Fixes npm audit issues in package-lock.json (#816) Co-authored-by: Ryan Rondeau --- .../backend/templates/deployment.yaml | 2 +- frontend/package-lock.json | 396 +++++++++--------- 2 files changed, 207 insertions(+), 191 deletions(-) diff --git a/charts/app/templates/backend/templates/deployment.yaml b/charts/app/templates/backend/templates/deployment.yaml index 667b3e197..85b291419 100644 --- a/charts/app/templates/backend/templates/deployment.yaml +++ b/charts/app/templates/backend/templates/deployment.yaml @@ -97,7 +97,7 @@ spec: cpu: 450m memory: 150Mi requests: - cpu: 75m + cpu: 50m memory: 75Mi {{- with .Values.backend.nodeSelector }} nodeSelector: diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 07ce67069..7ee1620a3 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -4622,18 +4622,18 @@ } }, "node_modules/@types/eslint-scope": { - "version": "3.7.4", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz", - "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==", + "version": "3.7.7", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", + "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", "dependencies": { "@types/eslint": "*", "@types/estree": "*" } }, "node_modules/@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==" + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==" }, "node_modules/@types/express": { "version": "4.17.21", @@ -5506,133 +5506,133 @@ "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==" }, "node_modules/@webassemblyjs/ast": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", - "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", + "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", "dependencies": { - "@webassemblyjs/helper-numbers": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1" + "@webassemblyjs/helper-numbers": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2" } }, "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", - "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==" + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", + "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==" }, "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", - "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==" + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", + "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==" }, "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", - "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==" + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", + "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==" }, "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", - "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", + "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", + "@webassemblyjs/floating-point-hex-parser": "1.13.2", + "@webassemblyjs/helper-api-error": "1.13.2", "@xtuc/long": "4.2.2" } }, "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", - "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==" + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", + "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==" }, "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", - "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz", + "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/wasm-gen": "1.14.1" } }, "node_modules/@webassemblyjs/ieee754": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", - "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", + "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", "dependencies": { "@xtuc/ieee754": "^1.2.0" } }, "node_modules/@webassemblyjs/leb128": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", - "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", + "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", "dependencies": { "@xtuc/long": "4.2.2" } }, "node_modules/@webassemblyjs/utf8": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", - "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==" + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", + "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==" }, "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", - "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz", + "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/helper-wasm-section": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-opt": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", - "@webassemblyjs/wast-printer": "1.11.1" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/helper-wasm-section": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-opt": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1", + "@webassemblyjs/wast-printer": "1.14.1" } }, "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", - "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", + "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" } }, "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", - "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz", + "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1" } }, "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", - "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz", + "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-api-error": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" } }, "node_modules/@webassemblyjs/wast-printer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", - "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz", + "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", "dependencies": { - "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/ast": "1.14.1", "@xtuc/long": "4.2.2" } }, @@ -5684,14 +5684,6 @@ "acorn-walk": "^8.0.2" } }, - "node_modules/acorn-import-assertions": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", - "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", - "peerDependencies": { - "acorn": "^8" - } - }, "node_modules/acorn-jsx": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", @@ -6702,9 +6694,9 @@ "peer": true }, "node_modules/browserslist": { - "version": "4.22.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz", - "integrity": "sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==", + "version": "4.24.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz", + "integrity": "sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==", "funding": [ { "type": "opencollective", @@ -6720,10 +6712,10 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001565", - "electron-to-chromium": "^1.4.601", - "node-releases": "^2.0.14", - "update-browserslist-db": "^1.0.13" + "caniuse-lite": "^1.0.30001669", + "electron-to-chromium": "^1.5.41", + "node-releases": "^2.0.18", + "update-browserslist-db": "^1.1.1" }, "bin": { "browserslist": "cli.js" @@ -6929,9 +6921,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001570", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001570.tgz", - "integrity": "sha512-+3e0ASu4sw1SWaoCtvPeyXp+5PsjigkSt8OXZbF9StH5pQWbxEjLAZE3n8Aup5udop1uRiKA7a4utUk/uoSpUw==", + "version": "1.0.30001687", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001687.tgz", + "integrity": "sha512-0S/FDhf4ZiqrTUiQ39dKeUjYRjkv7lOZU1Dgif2rIqrTzX/1wV2hfKu9TOm1IHkdSijfLswxTFzl/cvir+SLSQ==", "funding": [ { "type": "opencollective", @@ -7468,9 +7460,9 @@ "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" }, "node_modules/cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", "peer": true, "engines": { "node": ">= 0.6" @@ -7567,9 +7559,9 @@ "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==" }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -8605,9 +8597,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.615", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.615.tgz", - "integrity": "sha512-/bKPPcgZVUziECqDc+0HkT87+0zhaWSZHNXqF8FLd2lQcptpmUFwoCSWjCdOng9Gdq+afKArPdEg/0ZW461Eng==" + "version": "1.5.72", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.72.tgz", + "integrity": "sha512-ZpSAUOZ2Izby7qnZluSrAlGgGQzucmFbN0n64dYzocYxnxV5ufurpj3VgEe4cUp7ir9LmeLxNYo8bVnlM8bQHw==" }, "node_modules/emittery": { "version": "0.13.1", @@ -8663,9 +8655,9 @@ } }, "node_modules/enhanced-resolve": { - "version": "5.12.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz", - "integrity": "sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==", + "version": "5.17.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", + "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" @@ -8887,9 +8879,9 @@ } }, "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "engines": { "node": ">=6" } @@ -10003,9 +9995,9 @@ } }, "node_modules/express": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.0.tgz", - "integrity": "sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==", + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", + "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", "peer": true, "dependencies": { "accepts": "~1.3.8", @@ -10013,7 +10005,7 @@ "body-parser": "1.20.3", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.6.0", + "cookie": "0.7.1", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", @@ -10027,7 +10019,7 @@ "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.10", + "path-to-regexp": "0.1.12", "proxy-addr": "~2.0.7", "qs": "6.13.0", "range-parser": "~1.2.1", @@ -10042,6 +10034,10 @@ }, "engines": { "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/express/node_modules/array-flatten": { @@ -10066,9 +10062,9 @@ "peer": true }, "node_modules/express/node_modules/path-to-regexp": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", - "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==", + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", "peer": true }, "node_modules/extend": { @@ -11305,9 +11301,9 @@ } }, "node_modules/http-proxy-middleware": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", - "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.7.tgz", + "integrity": "sha512-fgVY8AV7qU7z/MmXJ/rxwbrtQH4jBQ9m7kp3llF0liB7glmFeVZFBepQb32T3y8n8k2+AEYuMPCpinYW+/CuRA==", "peer": true, "dependencies": { "@types/http-proxy": "^1.17.8", @@ -11524,7 +11520,8 @@ "node_modules/ini": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "peer": true }, "node_modules/input-format": { "version": "0.3.8", @@ -11563,10 +11560,27 @@ "loose-envify": "^1.0.0" } }, - "node_modules/ip": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.1.tgz", - "integrity": "sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ==" + "node_modules/ip-address": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", + "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", + "dependencies": { + "jsbn": "1.1.0", + "sprintf-js": "^1.1.3" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/ip-address/node_modules/jsbn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", + "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==" + }, + "node_modules/ip-address/node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==" }, "node_modules/ipaddr.js": { "version": "2.0.1", @@ -14963,11 +14977,11 @@ } }, "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dependencies": { - "braces": "^3.0.2", + "braces": "^3.0.3", "picomatch": "^2.3.1" }, "engines": { @@ -15319,9 +15333,9 @@ } }, "node_modules/nanoid": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "version": "3.3.8", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", + "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", "funding": [ { "type": "github", @@ -15404,9 +15418,9 @@ "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==" }, "node_modules/node-releases": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", - "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==" + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==" }, "node_modules/normalize-path": { "version": "3.0.0", @@ -22678,9 +22692,9 @@ } }, "node_modules/schema-utils": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.2.tgz", - "integrity": "sha512-pvjEHOgWc9OWA/f/DE3ohBWTD6EleVLf7iFUkoSwAxttdBhB9QUebQgxER2kWueOvRJXPHNnyrvvh9eZINB8Eg==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", "dependencies": { "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", @@ -23039,15 +23053,15 @@ } }, "node_modules/socks": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", - "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", + "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==", "dependencies": { - "ip": "^2.0.0", + "ip-address": "^9.0.5", "smart-buffer": "^4.2.0" }, "engines": { - "node": ">= 10.13.0", + "node": ">= 10.0.0", "npm": ">= 3.0.0" } }, @@ -23126,12 +23140,14 @@ "node_modules/spdx-exceptions": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", - "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==" + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", + "dev": true }, "node_modules/spdx-expression-parse": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-4.0.0.tgz", "integrity": "sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==", + "dev": true, "dependencies": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" @@ -23140,7 +23156,8 @@ "node_modules/spdx-license-ids": { "version": "3.0.20", "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.20.tgz", - "integrity": "sha512-jg25NiDV/1fLtSgEgyvVyDunvaNHbuwF9lfNV17gSmPFAlYzdfNBlLtLzXTevwkPj7DhGbmN9VnmJIgLnhvaBw==" + "integrity": "sha512-jg25NiDV/1fLtSgEgyvVyDunvaNHbuwF9lfNV17gSmPFAlYzdfNBlLtLzXTevwkPj7DhGbmN9VnmJIgLnhvaBw==", + "dev": true }, "node_modules/spdy": { "version": "4.0.2", @@ -23949,12 +23966,12 @@ } }, "node_modules/terser": { - "version": "5.16.9", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.9.tgz", - "integrity": "sha512-HPa/FdTB9XGI2H1/keLFZHxl6WNvAI4YalHGtDQTlMnJcoqSab1UwL4l1hGEhs6/GmLHBZIg/YgB++jcbzoOEg==", + "version": "5.37.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.37.0.tgz", + "integrity": "sha512-B8wRRkmre4ERucLM/uXx4MOV5cbnOlVAqUst+1+iLKPI0dOgFO28f84ptoQt9HEI537PMzfYa/d+GEPKTRXmYA==", "dependencies": { - "@jridgewell/source-map": "^0.3.2", - "acorn": "^8.5.0", + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, @@ -23966,15 +23983,15 @@ } }, "node_modules/terser-webpack-plugin": { - "version": "5.3.7", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.7.tgz", - "integrity": "sha512-AfKwIktyP7Cu50xNjXF/6Qb5lBNzYaWpU6YfoX3uZicTx0zTy0stDDCsvjDapKsSDvOeWo5MEq4TmdBy2cNoHw==", + "version": "5.3.10", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", + "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", "dependencies": { - "@jridgewell/trace-mapping": "^0.3.17", + "@jridgewell/trace-mapping": "^0.3.20", "jest-worker": "^27.4.5", "schema-utils": "^3.1.1", "serialize-javascript": "^6.0.1", - "terser": "^5.16.5" + "terser": "^5.26.0" }, "engines": { "node": ">= 10.13.0" @@ -24612,9 +24629,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", - "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", + "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", "funding": [ { "type": "opencollective", @@ -24630,8 +24647,8 @@ } ], "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" + "escalade": "^3.2.0", + "picocolors": "^1.1.0" }, "bin": { "update-browserslist-db": "cli.js" @@ -24839,9 +24856,9 @@ } }, "node_modules/watchpack": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", - "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz", + "integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==", "dependencies": { "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" @@ -24873,33 +24890,32 @@ } }, "node_modules/webpack": { - "version": "5.79.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.79.0.tgz", - "integrity": "sha512-3mN4rR2Xq+INd6NnYuL9RC9GAmc1ROPKJoHhrZ4pAjdMFEkJJWrsPw8o2JjCIyQyTu7rTXYn4VG6OpyB3CobZg==", - "dependencies": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^1.0.0", - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/wasm-edit": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", - "acorn": "^8.7.1", - "acorn-import-assertions": "^1.7.6", - "browserslist": "^4.14.5", + "version": "5.97.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.97.1.tgz", + "integrity": "sha512-EksG6gFY3L1eFMROS/7Wzgrii5mBAFe4rIr3r2BTfo7bcc+DWwFZ4OJ/miOuHJO/A85HwyI4eQ0F6IKXesO7Fg==", + "dependencies": { + "@types/eslint-scope": "^3.7.7", + "@types/estree": "^1.0.6", + "@webassemblyjs/ast": "^1.14.1", + "@webassemblyjs/wasm-edit": "^1.14.1", + "@webassemblyjs/wasm-parser": "^1.14.1", + "acorn": "^8.14.0", + "browserslist": "^4.24.0", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.10.0", + "enhanced-resolve": "^5.17.1", "es-module-lexer": "^1.2.1", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.9", + "graceful-fs": "^4.2.11", "json-parse-even-better-errors": "^2.3.1", "loader-runner": "^4.2.0", "mime-types": "^2.1.27", "neo-async": "^2.6.2", - "schema-utils": "^3.1.0", + "schema-utils": "^3.2.0", "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.7", - "watchpack": "^2.4.0", + "terser-webpack-plugin": "^5.3.10", + "watchpack": "^2.4.1", "webpack-sources": "^3.2.3" }, "bin": { @@ -25542,9 +25558,9 @@ "peer": true }, "node_modules/workbox-build/node_modules/rollup": { - "version": "2.79.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz", - "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==", + "version": "2.79.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.2.tgz", + "integrity": "sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ==", "peer": true, "bin": { "rollup": "dist/bin/rollup"