From 525ff421acc675e5e93bbe066aa89cf29e5362e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrian=20Or=C5=82=C3=B3w?= <adrian.orlow@fishbrain.com> Date: Wed, 25 Oct 2023 14:20:00 +0200 Subject: [PATCH] feat: move map init hook logic to redux --- .env | 1 + .eslintrc.json | 4 +- package-lock.json | 381 ++++++++++++++++++ package.json | 1 + prettier.config.js | 1 + .../MapViewer/utils/config/getMapTileUrl.ts | 15 + .../MapViewer/utils/config/useOlMapConfig.ts | 8 +- .../Map/MapViewer/utils/init/useFirstStage.ts | 23 -- .../Map/MapViewer/utils/init/useOlMapInit.ts | 9 - .../MapViewer/utils/init/useSecondStage.ts | 44 -- .../Map/MapViewer/utils/init/useThirdStage.ts | 38 -- .../Map/MapViewer/utils/useOlMap.ts | 2 - src/components/SPA/MinervaSPA.component.tsx | 30 +- src/redux/backgrounds/background.selectors.ts | 2 +- src/redux/map/map.middleware.ts | 46 +++ src/redux/map/map.reducers.ts | 24 +- src/redux/map/map.slice.ts | 5 +- src/redux/map/map.thunks.ts | 31 ++ src/redux/map/map.types.ts | 9 + src/redux/models/models.thunks.test.ts | 10 +- src/redux/project/project.selectors.ts | 2 +- src/redux/root/init.selectors.ts | 13 + src/redux/root/mapStages.selectors.ts | 40 -- src/redux/store.ts | 4 +- src/utils/getUpdatedMapData.ts | 29 ++ src/utils/map/useHandleMapChange.ts | 40 -- yarn.lock | 190 ++++++++- 27 files changed, 774 insertions(+), 228 deletions(-) create mode 100644 src/components/Map/MapViewer/utils/config/getMapTileUrl.ts delete mode 100644 src/components/Map/MapViewer/utils/init/useFirstStage.ts delete mode 100644 src/components/Map/MapViewer/utils/init/useOlMapInit.ts delete mode 100644 src/components/Map/MapViewer/utils/init/useSecondStage.ts delete mode 100644 src/components/Map/MapViewer/utils/init/useThirdStage.ts create mode 100644 src/redux/map/map.middleware.ts create mode 100644 src/redux/map/map.thunks.ts create mode 100644 src/redux/root/init.selectors.ts delete mode 100644 src/redux/root/mapStages.selectors.ts create mode 100644 src/utils/getUpdatedMapData.ts delete mode 100644 src/utils/map/useHandleMapChange.ts diff --git a/.env b/.env index 3f191e1f..470be3d7 100644 --- a/.env +++ b/.env @@ -1,5 +1,6 @@ NEXT_PUBLIC_BASE_API_URL = 'https://corsproxy.io/?https://lux1.atcomp.pl/minerva/api' NEXT_PUBLIC_BASE_NEW_API_URL = 'https://corsproxy.io/?https://lux1.atcomp.pl/minerva/new_api/' +BASE_MAP_IMAGES_URL = 'https://lux1.atcomp.pl/' NEXT_PUBLIC_PROJECT_ID = 'pdmap_appu_test' ZOD_SEED = 997 diff --git a/.eslintrc.json b/.eslintrc.json index e60a21f0..3ed8a0da 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -10,6 +10,7 @@ "plugin:react/recommended", "plugin:jsx-a11y/recommended", "plugin:@next/next/recommended", + "plugin:prettier/recommended", "prettier", "next" ], @@ -87,7 +88,8 @@ "callees": ["twMerge"], "config": "./tailwind.config.ts" } - ] + ], + "prettier/prettier": "error" }, "overrides": [ { diff --git a/package-lock.json b/package-lock.json index cbe12b20..f41b1125 100644 --- a/package-lock.json +++ b/package-lock.json @@ -50,6 +50,7 @@ "eslint-plugin-import": "^2.28.1", "eslint-plugin-jsx-a11y": "^6.7.1", "eslint-plugin-n": "^16.1.0", + "eslint-plugin-prettier": "^5.0.1", "eslint-plugin-promise": "^6.1.1", "eslint-plugin-react": "^7.33.2", "eslint-plugin-react-hooks": "^4.6.0", @@ -1885,6 +1886,26 @@ "resolved": "https://registry.npmjs.org/@petamoriken/float16/-/float16-3.8.4.tgz", "integrity": "sha512-kB+NJ5Br56ZhElKsf0pM7/PQfrDdDVMRz8f0JM6eVOGE+L89z9hwcst9QvWBBnazzuqGTGtPsJNZoQ1JdNiGSQ==" }, + "node_modules/@pkgr/utils": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@pkgr/utils/-/utils-2.4.2.tgz", + "integrity": "sha512-POgTXhjrTfbTV63DiFXav4lBHiICLKKwDeaKn9Nphwj7WH6m0hMMCaJkMyRWjgtPFyRKRVoMXXjczsTQRDEhYw==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "fast-glob": "^3.3.0", + "is-glob": "^4.0.3", + "open": "^9.1.0", + "picocolors": "^1.0.0", + "tslib": "^2.6.0" + }, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, "node_modules/@reduxjs/toolkit": { "version": "1.9.6", "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.9.6.tgz", @@ -3208,6 +3229,15 @@ "tweetnacl": "^0.14.3" } }, + "node_modules/big-integer": { + "version": "1.6.51", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", + "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, "node_modules/binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -3239,6 +3269,18 @@ "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", "dev": true }, + "node_modules/bplist-parser": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.2.0.tgz", + "integrity": "sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==", + "dev": true, + "dependencies": { + "big-integer": "^1.6.44" + }, + "engines": { + "node": ">= 5.10.0" + } + }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -3347,6 +3389,21 @@ "semver": "^7.0.0" } }, + "node_modules/bundle-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-3.0.0.tgz", + "integrity": "sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==", + "dev": true, + "dependencies": { + "run-applescript": "^5.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/busboy": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", @@ -4379,6 +4436,150 @@ "node": ">=0.10.0" } }, + "node_modules/default-browser": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-4.0.0.tgz", + "integrity": "sha512-wX5pXO1+BrhMkSbROFsyxUm0i/cJEScyNhA4PPxc41ICuv05ZZB/MX28s8aZx6xjmatvebIapF6hLEKEcpneUA==", + "dev": true, + "dependencies": { + "bundle-name": "^3.0.0", + "default-browser-id": "^3.0.0", + "execa": "^7.1.1", + "titleize": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser-id": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-3.0.0.tgz", + "integrity": "sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA==", + "dev": true, + "dependencies": { + "bplist-parser": "^0.2.0", + "untildify": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser/node_modules/execa": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz", + "integrity": "sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.1", + "human-signals": "^4.3.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^3.0.7", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": "^14.18.0 || ^16.14.0 || >=18.0.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/default-browser/node_modules/human-signals": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", + "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", + "dev": true, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/default-browser/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser/node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser/node_modules/npm-run-path": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", + "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", + "dev": true, + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser/node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser/node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/defaults": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", @@ -4404,6 +4605,18 @@ "node": ">= 0.4" } }, + "node_modules/define-lazy-prop": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/define-properties": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", @@ -5211,6 +5424,35 @@ "eslint": ">=7.0.0" } }, + "node_modules/eslint-plugin-prettier": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.0.1.tgz", + "integrity": "sha512-m3u5RnR56asrwV/lDC4GHorlW75DsFfmUcjfCYylTUs85dBRnB7VM6xG8eCMJdeDRnppzmxZVf1GEPJvl1JmNg==", + "dev": true, + "dependencies": { + "prettier-linter-helpers": "^1.0.0", + "synckit": "^0.8.5" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/prettier" + }, + "peerDependencies": { + "@types/eslint": ">=8.0.0", + "eslint": ">=8.0.0", + "prettier": ">=3.0.0" + }, + "peerDependenciesMeta": { + "@types/eslint": { + "optional": true + }, + "eslint-config-prettier": { + "optional": true + } + } + }, "node_modules/eslint-plugin-promise": { "version": "6.1.1", "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.1.1.tgz", @@ -5730,6 +5972,12 @@ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true + }, "node_modules/fast-glob": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", @@ -6882,6 +7130,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-docker": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "dev": true, + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -6944,6 +7207,24 @@ "node": ">=0.10.0" } }, + "node_modules/is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "dev": true, + "dependencies": { + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-installed-globally": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", @@ -7206,6 +7487,33 @@ "node": ">=0.10.0" } }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-wsl/node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true, + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/isarray": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", @@ -9784,6 +10092,24 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/open": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/open/-/open-9.1.0.tgz", + "integrity": "sha512-OS+QTnw1/4vrf+9hh1jc1jnYjzSG4ttTBB8UxOwAnInG3Uo4ssetzC1ihqaIHjLJnA5GGlRl6QlZXOTQhRBUvg==", + "dev": true, + "dependencies": { + "default-browser": "^4.0.0", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/optionator": { "version": "0.9.3", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", @@ -10282,6 +10608,18 @@ "url": "https://github.com/prettier/prettier?sponsor=1" } }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/prettier-plugin-tailwindcss": { "version": "0.5.6", "resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.5.6.tgz", @@ -11077,6 +11415,21 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/run-applescript": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-5.0.0.tgz", + "integrity": "sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==", + "dev": true, + "dependencies": { + "execa": "^5.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/run-async": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", @@ -11720,6 +12073,22 @@ "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", "dev": true }, + "node_modules/synckit": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.5.tgz", + "integrity": "sha512-L1dapNV6vu2s/4Sputv8xGsCdAVlb5nRDMFU/E27D44l5U6cw1g0dGd45uLc+OXjNMmF4ntiMdCimzcjFKQI8Q==", + "dev": true, + "dependencies": { + "@pkgr/utils": "^2.3.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, "node_modules/tailwind-merge": { "version": "1.14.0", "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-1.14.0.tgz", @@ -11841,6 +12210,18 @@ "readable-stream": "3" } }, + "node_modules/titleize": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/titleize/-/titleize-3.0.0.tgz", + "integrity": "sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/tmp": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", diff --git a/package.json b/package.json index c359766c..c6c19cd6 100644 --- a/package.json +++ b/package.json @@ -64,6 +64,7 @@ "eslint-plugin-import": "^2.28.1", "eslint-plugin-jsx-a11y": "^6.7.1", "eslint-plugin-n": "^16.1.0", + "eslint-plugin-prettier": "^5.0.1", "eslint-plugin-promise": "^6.1.1", "eslint-plugin-react": "^7.33.2", "eslint-plugin-react-hooks": "^4.6.0", diff --git a/prettier.config.js b/prettier.config.js index fd41c7ea..eec5dca5 100644 --- a/prettier.config.js +++ b/prettier.config.js @@ -6,6 +6,7 @@ const config = { plugins: [import('prettier-plugin-tailwindcss')], tailwindConfig: './tailwind.config.ts', tailwindFunctions: ['twMerge'], + tabWidth: 2, }; module.exports = config; diff --git a/src/components/Map/MapViewer/utils/config/getMapTileUrl.ts b/src/components/Map/MapViewer/utils/config/getMapTileUrl.ts new file mode 100644 index 00000000..0ba5eed4 --- /dev/null +++ b/src/components/Map/MapViewer/utils/config/getMapTileUrl.ts @@ -0,0 +1,15 @@ +import { BASE_MAP_IMAGES_URL } from '@/constants'; + +export const getMapTileUrl = ({ + projectDirectory, + currentBackgroundImagePath, +}: { + projectDirectory?: string; + currentBackgroundImagePath: string; +}): string => { + if (!projectDirectory) { + return ''; + } + + return `${BASE_MAP_IMAGES_URL}/map_images/${projectDirectory}/${currentBackgroundImagePath}/{z}/{x}/{y}.PNG`; +}; diff --git a/src/components/Map/MapViewer/utils/config/useOlMapConfig.ts b/src/components/Map/MapViewer/utils/config/useOlMapConfig.ts index 42d07a05..2a584d87 100644 --- a/src/components/Map/MapViewer/utils/config/useOlMapConfig.ts +++ b/src/components/Map/MapViewer/utils/config/useOlMapConfig.ts @@ -1,5 +1,4 @@ /* eslint-disable no-magic-numbers */ -import { BASE_MAP_IMAGES_URL } from '@/constants'; import { OPTIONS } from '@/constants/map'; import { currentBackgroundImagePathSelector } from '@/redux/backgrounds/background.selectors'; import { mapDataPositionSelector, mapDataSizeSelector } from '@/redux/map/map.selectors'; @@ -12,6 +11,7 @@ import TileLayer from 'ol/layer/Tile'; import { XYZ } from 'ol/source'; import { useMemo } from 'react'; import { useSelector } from 'react-redux'; +import { getMapTileUrl } from './getMapTileUrl'; interface UseOlMapConfigResult { view: View; @@ -45,18 +45,18 @@ export const useOlMapConfig = (): UseOlMapConfigResult => { ); const tileLayer = useMemo( - () => + (): TileLayer<XYZ> => new TileLayer({ visible: true, source: new XYZ({ - url: `${BASE_MAP_IMAGES_URL}/map_images/${project?.directory}/${currentBackgroundImagePath}/{z}/{x}/{y}.PNG`, + url: getMapTileUrl({ projectDirectory: project?.directory, currentBackgroundImagePath }), maxZoom: mapSize.maxZoom, minZoom: mapSize.minZoom, tileSize: mapSize.tileSize, wrapX: OPTIONS.wrapXInTileLayer, }), }), - [mapSize, currentBackgroundImagePath, project], + [mapSize, currentBackgroundImagePath, project?.directory], ); return { diff --git a/src/components/Map/MapViewer/utils/init/useFirstStage.ts b/src/components/Map/MapViewer/utils/init/useFirstStage.ts deleted file mode 100644 index 0b8af2ed..00000000 --- a/src/components/Map/MapViewer/utils/init/useFirstStage.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { PROJECT_ID } from '@/constants'; -import { useAppDispatch } from '@/redux/hooks/useAppDispatch'; -import { getProjectById } from '@/redux/project/project.thunks'; -import { mapLoadingFirstStageInitializedSelector } from '@/redux/root/mapStages.selectors'; -import { useCallback, useEffect } from 'react'; -import { useSelector } from 'react-redux'; - -export const useFirstStage = (): void => { - const dispatch = useAppDispatch(); - const isInitialized = useSelector(mapLoadingFirstStageInitializedSelector); - - const initProjectData = useCallback((): void => { - dispatch(getProjectById(PROJECT_ID)); - }, [dispatch]); - - useEffect(() => { - if (isInitialized) { - return; - } - - initProjectData(); - }, [initProjectData, isInitialized]); -}; diff --git a/src/components/Map/MapViewer/utils/init/useOlMapInit.ts b/src/components/Map/MapViewer/utils/init/useOlMapInit.ts deleted file mode 100644 index 2e993841..00000000 --- a/src/components/Map/MapViewer/utils/init/useOlMapInit.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { useFirstStage } from './useFirstStage'; -import { useSecondStage } from './useSecondStage'; -import { useThirdStage } from './useThirdStage'; - -export const useOlMapInit = (): void => { - useFirstStage(); - useSecondStage(); - useThirdStage(); -}; diff --git a/src/components/Map/MapViewer/utils/init/useSecondStage.ts b/src/components/Map/MapViewer/utils/init/useSecondStage.ts deleted file mode 100644 index 360a56c8..00000000 --- a/src/components/Map/MapViewer/utils/init/useSecondStage.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { getAllBackgroundsByProjectId } from '@/redux/backgrounds/backgrounds.thunks'; -import { useAppDispatch } from '@/redux/hooks/useAppDispatch'; -import { getAllModelsByProjectId } from '@/redux/models/models.thunks'; -import { getAllPublicOverlaysByProjectId } from '@/redux/overlays/overlays.thunks'; -import { projectDataSelector } from '@/redux/project/project.selectors'; -import { - mapLoadingFirstStageCompletedSelector, - mapLoadingSecondStageInitializedSelector, -} from '@/redux/root/mapStages.selectors'; -import { AppDispatch } from '@/redux/store'; -import { Project } from '@/types/models'; -import { useCallback, useEffect } from 'react'; -import { useSelector } from 'react-redux'; - -const getMapDataAction = - (project: Project) => - (dispatch: AppDispatch): void => { - dispatch(getAllBackgroundsByProjectId(project.projectId)); - dispatch(getAllPublicOverlaysByProjectId(project.projectId)); - dispatch(getAllModelsByProjectId(project.projectId)); - }; - -export const useSecondStage = (): void => { - const dispatch = useAppDispatch(); - const project = useSelector(projectDataSelector); - const isPreviousCompleted = useSelector(mapLoadingFirstStageCompletedSelector); - const isInitialized = useSelector(mapLoadingSecondStageInitializedSelector); - - const initMapData = useCallback((): void => { - if (!project) { - return; - } - - dispatch(getMapDataAction(project)); - }, [dispatch, project]); - - useEffect(() => { - if (!isPreviousCompleted || isInitialized) { - return; - } - - initMapData(); - }, [initMapData, isInitialized, isPreviousCompleted]); -}; diff --git a/src/components/Map/MapViewer/utils/init/useThirdStage.ts b/src/components/Map/MapViewer/utils/init/useThirdStage.ts deleted file mode 100644 index bb6572a0..00000000 --- a/src/components/Map/MapViewer/utils/init/useThirdStage.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { backgroundsDataSelector } from '@/redux/backgrounds/background.selectors'; -import { mapDataSelector } from '@/redux/map/map.selectors'; -import { modelsDataSelector } from '@/redux/models/models.selectors'; -import { mapLoadingAllStagesCompletedSelector } from '@/redux/root/mapStages.selectors'; -import { useHandleMapChange } from '@/utils/map/useHandleMapChange'; -import { useCallback, useEffect } from 'react'; -import { useSelector } from 'react-redux'; - -const FIRST = 0; - -export const useThirdStage = (): void => { - const map = useSelector(mapDataSelector); - const models = useSelector(modelsDataSelector); - const backgrounds = useSelector(backgroundsDataSelector); - const loadingCompleted = useSelector(mapLoadingAllStagesCompletedSelector); - const handleMapChange = useHandleMapChange(); - - const setDefaultMapModelData = useCallback(() => { - const defaultBackground = backgrounds?.[FIRST]; - const defaultModel = models?.[FIRST]; - if (map.modelId || !defaultModel || !defaultBackground) { - return; - } - - handleMapChange({ - model: defaultModel, - background: defaultBackground, - }); - }, [backgrounds, models, map, handleMapChange]); - - useEffect(() => { - if (!loadingCompleted) { - return; - } - - setDefaultMapModelData(); - }, [setDefaultMapModelData, loadingCompleted]); -}; diff --git a/src/components/Map/MapViewer/utils/useOlMap.ts b/src/components/Map/MapViewer/utils/useOlMap.ts index c17fc281..ca82591a 100644 --- a/src/components/Map/MapViewer/utils/useOlMap.ts +++ b/src/components/Map/MapViewer/utils/useOlMap.ts @@ -2,7 +2,6 @@ import Map from 'ol/Map'; import React, { MutableRefObject, useEffect, useState } from 'react'; import { MapInstance } from '../MapViewer.types'; import { useOlMapConfig } from './config/useOlMapConfig'; -import { useOlMapInit } from './init/useOlMapInit'; interface UseOlMapInput { target?: HTMLElement; @@ -18,7 +17,6 @@ export const useOlMap: UseOlMap = ({ target } = {}) => { const mapRef = React.useRef<null | HTMLDivElement>(null); const [mapInstance, setMapInstance] = useState<MapInstance>(undefined); const mapConfig = useOlMapConfig(); - useOlMapInit(); useEffect(() => { // checking if innerHTML is empty due to possibility of target element cloning by openlayers map instance diff --git a/src/components/SPA/MinervaSPA.component.tsx b/src/components/SPA/MinervaSPA.component.tsx index c9b53815..6703ea8c 100644 --- a/src/components/SPA/MinervaSPA.component.tsx +++ b/src/components/SPA/MinervaSPA.component.tsx @@ -1,10 +1,15 @@ -import { Manrope } from '@next/font/google'; -import { twMerge } from 'tailwind-merge'; -import { Map } from '@/components/Map'; import { FunctionalArea } from '@/components/FunctionalArea'; +import { Map } from '@/components/Map'; +import { PROJECT_ID } from '@/constants'; import { useAppDispatch } from '@/redux/hooks/useAppDispatch'; +import { initMapData } from '@/redux/map/map.thunks'; +import { getProjectById } from '@/redux/project/project.thunks'; +import { initDataLoadingInitialized } from '@/redux/root/init.selectors'; +import { AppDispatch } from '@/redux/store'; +import { Manrope } from '@next/font/google'; import { useEffect } from 'react'; -import { getModels } from '@/redux/models/models.thunks'; +import { useSelector } from 'react-redux'; +import { twMerge } from 'tailwind-merge'; const manrope = Manrope({ variable: '--font-manrope', @@ -13,12 +18,25 @@ const manrope = Manrope({ subsets: ['latin'], }); +/* prettier-ignore */ +const getInitStoreData = + () => + (dispatch: AppDispatch): void => { + dispatch(getProjectById(PROJECT_ID)); + dispatch(initMapData()); + }; + export const MinervaSPA = (): JSX.Element => { const dispatch = useAppDispatch(); + const storeInitialized = useSelector(initDataLoadingInitialized); useEffect(() => { - dispatch(getModels()); - }, [dispatch]); + if (storeInitialized) { + return; + } + + dispatch(getInitStoreData()); + }, [dispatch, storeInitialized]); return ( <div className={twMerge('relative', manrope.variable)}> diff --git a/src/redux/backgrounds/background.selectors.ts b/src/redux/backgrounds/background.selectors.ts index 01b6ed81..16b23397 100644 --- a/src/redux/backgrounds/background.selectors.ts +++ b/src/redux/backgrounds/background.selectors.ts @@ -6,7 +6,7 @@ export const backgroundsSelector = createSelector(rootSelector, state => state.b export const backgroundsDataSelector = createSelector( backgroundsSelector, - backgrounds => backgrounds.data || [], + backgrounds => backgrounds?.data || [], ); export const currentBackgroundSelector = createSelector( diff --git a/src/redux/map/map.middleware.ts b/src/redux/map/map.middleware.ts new file mode 100644 index 00000000..dc1e99e7 --- /dev/null +++ b/src/redux/map/map.middleware.ts @@ -0,0 +1,46 @@ +import { MapModel } from '@/types/models'; +import { getUpdatedMapData } from '@/utils/getUpdatedMapData'; +import { Middleware, MiddlewareAPI, PayloadAction } from '@reduxjs/toolkit'; +import { modelsDataSelector } from '../models/models.selectors'; +import type { AppDispatch, RootState } from '../store'; +import { setMapData } from './map.slice'; +import { InitMapDataActionPayload, SetMapDataActionPayload } from './map.types'; + +type AllowedAction = PayloadAction<SetMapDataActionPayload | InitMapDataActionPayload>; + +const ALLOWED_ACTIONS = ['map/setMapData', 'map/initMapData']; + +const checkIfIsActionValid = (action: AllowedAction, state: RootState): boolean => { + const isAllowedAction = ALLOWED_ACTIONS.some(allowedAction => + action.type.includes(allowedAction), + ); + const isModelIdTheSame = state.map.data.modelId === action.payload?.modelId; + + return isAllowedAction && !isModelIdTheSame; +}; + +const getUpdatedModel = (action: AllowedAction, state: RootState): MapModel | undefined => { + const models = modelsDataSelector(state); + return models.find(model => model.idObject === action?.payload?.modelId); +}; + +/* prettier-ignore */ +export const mapMiddleware: Middleware = + ({ getState, dispatch }: MiddlewareAPI<AppDispatch, RootState>) => + (next: AppDispatch) => + // eslint-disable-next-line consistent-return + (action: AllowedAction) => { + const state = getState(); + const isActionValid = checkIfIsActionValid(action, state); + const updatedModel = getUpdatedModel(action, state); + const returnValue = next(action); + + if (!isActionValid || !updatedModel) { + return returnValue; + } + + const updatedMapData = getUpdatedMapData({ model: updatedModel }); + dispatch(setMapData(updatedMapData)); + + return returnValue; + }; diff --git a/src/redux/map/map.reducers.ts b/src/redux/map/map.reducers.ts index 95d76325..51f7faab 100644 --- a/src/redux/map/map.reducers.ts +++ b/src/redux/map/map.reducers.ts @@ -1,9 +1,21 @@ -import { PayloadAction } from '@reduxjs/toolkit'; -import { MapData, MapState } from './map.types'; +import { ActionReducerMapBuilder } from '@reduxjs/toolkit'; +import { initMapData } from './map.thunks'; +import { MapState, SetMapDataAction } from './map.types'; -export const setMapDataReducer = ( - state: MapState, - action: PayloadAction<Partial<MapData> | undefined>, -): void => { +export const setMapDataReducer = (state: MapState, action: SetMapDataAction): void => { state.data = { ...state.data, ...action.payload }; }; + +export const getMapReducers = (builder: ActionReducerMapBuilder<MapState>): void => { + builder.addCase(initMapData.pending, state => { + state.loading = 'pending'; + }); + builder.addCase(initMapData.fulfilled, (state, action) => { + state.data = { ...state.data, ...action.payload }; + state.loading = 'succeeded'; + }); + builder.addCase(initMapData.rejected, state => { + state.loading = 'failed'; + // TODO to discuss manage state of failure + }); +}; diff --git a/src/redux/map/map.slice.ts b/src/redux/map/map.slice.ts index 62b95df2..3565dc25 100644 --- a/src/redux/map/map.slice.ts +++ b/src/redux/map/map.slice.ts @@ -1,6 +1,6 @@ import { createSlice } from '@reduxjs/toolkit'; import { MAP_DATA_INITIAL_STATE } from './map.constants'; -import { setMapDataReducer } from './map.reducers'; +import { getMapReducers, setMapDataReducer } from './map.reducers'; import { MapState } from './map.types'; const initialState: MapState = { @@ -15,6 +15,9 @@ const mapSlice = createSlice({ reducers: { setMapData: setMapDataReducer, }, + extraReducers: builder => { + getMapReducers(builder); + }, }); export const { setMapData } = mapSlice.actions; diff --git a/src/redux/map/map.thunks.ts b/src/redux/map/map.thunks.ts new file mode 100644 index 00000000..481d5cfb --- /dev/null +++ b/src/redux/map/map.thunks.ts @@ -0,0 +1,31 @@ +import { PROJECT_ID } from '@/constants'; +import { createAsyncThunk } from '@reduxjs/toolkit'; +import { backgroundsDataSelector } from '../backgrounds/background.selectors'; +import { getAllBackgroundsByProjectId } from '../backgrounds/backgrounds.thunks'; +import { modelsDataSelector } from '../models/models.selectors'; +import { getModels } from '../models/models.thunks'; +import { getAllPublicOverlaysByProjectId } from '../overlays/overlays.thunks'; +import type { AppDispatch, RootState } from '../store'; +import { InitMapDataActionPayload } from './map.types'; + +const FIRST = 0; + +export const initMapData = createAsyncThunk< + InitMapDataActionPayload, + void, + { dispatch: AppDispatch; state: RootState } +>('map/initMapData', async (_, { dispatch, getState }): Promise<InitMapDataActionPayload> => { + await Promise.all([ + dispatch(getAllBackgroundsByProjectId(PROJECT_ID)), + dispatch(getAllPublicOverlaysByProjectId(PROJECT_ID)), + dispatch(getModels()), + ]); + + const state = getState(); + const models = modelsDataSelector(state); + const backgrounds = backgroundsDataSelector(state); + const modelId = models[FIRST].idObject; + const backgroundId = backgrounds[FIRST].id; + + return { modelId, backgroundId }; +}); diff --git a/src/redux/map/map.types.ts b/src/redux/map/map.types.ts index ac46d776..108648dc 100644 --- a/src/redux/map/map.types.ts +++ b/src/redux/map/map.types.ts @@ -1,5 +1,6 @@ import { FetchDataState } from '@/types/fetchDataState'; import { Point } from '@/types/map'; +import { PayloadAction } from '@reduxjs/toolkit'; export interface MapSize { width: number; @@ -24,3 +25,11 @@ export type MapData = { }; export type MapState = FetchDataState<MapData, MapData>; + +export type SetMapDataActionPayload = Partial<MapData> | undefined; + +export type SetMapDataAction = PayloadAction<SetMapDataActionPayload>; + +export type InitMapDataActionPayload = { modelId: number; backgroundId: number }; + +export type InitMapDataAction = PayloadAction<SetMapDataAction>; diff --git a/src/redux/models/models.thunks.test.ts b/src/redux/models/models.thunks.test.ts index 3d85a15e..a8daf71d 100644 --- a/src/redux/models/models.thunks.test.ts +++ b/src/redux/models/models.thunks.test.ts @@ -1,12 +1,12 @@ -import { HttpStatusCode } from 'axios'; -import { mockNetworkResponse } from '@/utils/mockNetworkResponse'; +import { modelsFixture } from '@/models/fixtures/modelsFixture'; +import { apiPath } from '@/redux/apiPath'; +import { ModelsState } from '@/redux/models/models.types'; import { ToolkitStoreWithSingleSlice, createStoreInstanceUsingSliceReducer, } from '@/utils/createStoreInstanceUsingSliceReducer'; -import { ModelsState } from '@/redux/models/models.types'; -import { apiPath } from '@/redux/apiPath'; -import { modelsFixture } from '@/models/fixtures/modelsFixture'; +import { mockNetworkResponse } from '@/utils/mockNetworkResponse'; +import { HttpStatusCode } from 'axios'; import modelsReducer from './models.slice'; import { getModels } from './models.thunks'; diff --git a/src/redux/project/project.selectors.ts b/src/redux/project/project.selectors.ts index 9ba0ec03..2725956a 100644 --- a/src/redux/project/project.selectors.ts +++ b/src/redux/project/project.selectors.ts @@ -3,4 +3,4 @@ import { rootSelector } from '../root/root.selectors'; export const projectSelector = createSelector(rootSelector, state => state.project); -export const projectDataSelector = createSelector(projectSelector, project => project.data); +export const projectDataSelector = createSelector(projectSelector, project => project?.data); diff --git a/src/redux/root/init.selectors.ts b/src/redux/root/init.selectors.ts new file mode 100644 index 00000000..82176735 --- /dev/null +++ b/src/redux/root/init.selectors.ts @@ -0,0 +1,13 @@ +import { createSelector } from '@reduxjs/toolkit'; +import { backgroundsSelector } from '../backgrounds/background.selectors'; +import { modelsSelector } from '../models/models.selectors'; +import { overlaysSelector } from '../overlays/overlays.selectors'; +import { projectSelector } from '../project/project.selectors'; + +export const initDataLoadingInitialized = createSelector( + projectSelector, + backgroundsSelector, + modelsSelector, + overlaysSelector, + (...selectors) => selectors.every(selector => selector.loading !== 'idle'), +); diff --git a/src/redux/root/mapStages.selectors.ts b/src/redux/root/mapStages.selectors.ts deleted file mode 100644 index cda0f3b2..00000000 --- a/src/redux/root/mapStages.selectors.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { createSelector } from '@reduxjs/toolkit'; -import { backgroundsSelector } from '../backgrounds/background.selectors'; -import { modelsSelector } from '../models/models.selectors'; -import { overlaysSelector } from '../overlays/overlays.selectors'; -import { projectSelector } from '../project/project.selectors'; - -export const mapLoadingFirstStageInitializedSelector = createSelector( - projectSelector, - project => project.loading !== 'idle', -); - -export const mapLoadingFirstStageCompletedSelector = createSelector( - projectSelector, - project => project.loading === 'succeeded', -); - -export const mapLoadingSecondStageInitializedSelector = createSelector( - backgroundsSelector, - modelsSelector, - overlaysSelector, - (backgrounds, models, overlays) => - [backgrounds.loading, models.loading, overlays.loading].every(loading => loading !== 'idle'), -); - -export const mapLoadingSecondStageCompletedSelector = createSelector( - backgroundsSelector, - modelsSelector, - overlaysSelector, - (backgrounds, models, overlays) => - [backgrounds.loading, models.loading, overlays.loading].every( - loading => loading === 'succeeded', - ), -); - -export const mapLoadingAllStagesCompletedSelector = createSelector( - mapLoadingFirstStageCompletedSelector, - mapLoadingSecondStageCompletedSelector, - (firstStageCompleted, secondStageCompleted) => - [firstStageCompleted, secondStageCompleted].every(completed => completed === true), -); diff --git a/src/redux/store.ts b/src/redux/store.ts index 0c59b4e1..e1ecab61 100644 --- a/src/redux/store.ts +++ b/src/redux/store.ts @@ -9,7 +9,8 @@ import modelsReducer from '@/redux/models/models.slice'; import overlaysReducer from '@/redux/overlays/overlays.slice'; import projectReducer from '@/redux/project/project.slice'; import searchReducer from '@/redux/search/search.slice'; -import { configureStore } from '@reduxjs/toolkit'; +import { applyMiddleware, configureStore } from '@reduxjs/toolkit'; +import { mapMiddleware } from './map/map.middleware'; export const reducers = { search: searchReducer, @@ -28,6 +29,7 @@ export const reducers = { export const store = configureStore({ reducer: reducers, devTools: true, + enhancers: [applyMiddleware(mapMiddleware)], }); export type StoreType = typeof store; diff --git a/src/utils/getUpdatedMapData.ts b/src/utils/getUpdatedMapData.ts new file mode 100644 index 00000000..7bbc1329 --- /dev/null +++ b/src/utils/getUpdatedMapData.ts @@ -0,0 +1,29 @@ +import { DEFAULT_ZOOM } from '@/constants/map'; +import { MapData } from '@/redux/map/map.types'; +import { MapModel } from '@/types/models'; + +interface GetUpdatedMapDataArgs { + model: MapModel; +} + +type GetUpdatedMapDataResult = Pick<MapData, 'modelId' | 'size' | 'position'> & { + backgroundId?: number; +}; + +const HALF = 2; + +export const getUpdatedMapData = ({ model }: GetUpdatedMapDataArgs): GetUpdatedMapDataResult => ({ + modelId: model.idObject, + size: { + width: model.width, + height: model.height, + tileSize: model.tileSize, + minZoom: model.minZoom, + maxZoom: model.maxZoom, + }, + position: { + x: model.defaultCenterX || model.width / HALF, + y: model.defaultCenterY || model.height / HALF, + z: model.defaultZoomLevel || DEFAULT_ZOOM, + }, +}); diff --git a/src/utils/map/useHandleMapChange.ts b/src/utils/map/useHandleMapChange.ts deleted file mode 100644 index 94bcaf91..00000000 --- a/src/utils/map/useHandleMapChange.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { DEFAULT_ZOOM } from '@/constants/map'; -import { useAppDispatch } from '@/redux/hooks/useAppDispatch'; -import { setMapData } from '@/redux/map/map.slice'; -import { MapBackground, MapModel } from '@/types/models'; - -interface HandleMapChangeArgs { - model: MapModel; - background?: MapBackground; -} - -type UseHandleMapChangeFunction = (args: HandleMapChangeArgs) => void; - -const HALF = 2; - -export const useHandleMapChange = (): UseHandleMapChangeFunction => { - const dispatch = useAppDispatch(); - - const handleMapChange = ({ model, background }: HandleMapChangeArgs): void => { - dispatch( - setMapData({ - modelId: model.idObject, - backgroundId: background?.id, - size: { - width: model.width, - height: model.height, - tileSize: model.tileSize, - minZoom: model.minZoom, - maxZoom: model.maxZoom, - }, - position: { - x: model.defaultCenterX || model.width / HALF, - y: model.defaultCenterY || model.height / HALF, - z: model.defaultZoomLevel || DEFAULT_ZOOM, - }, - }), - ); - }; - - return handleMapChange; -}; diff --git a/yarn.lock b/yarn.lock index 4a3561b2..c865fa74 100644 --- a/yarn.lock +++ b/yarn.lock @@ -878,6 +878,18 @@ "resolved" "https://registry.npmjs.org/@petamoriken/float16/-/float16-3.8.4.tgz" "version" "3.8.4" +"@pkgr/utils@^2.3.1": + "integrity" "sha512-POgTXhjrTfbTV63DiFXav4lBHiICLKKwDeaKn9Nphwj7WH6m0hMMCaJkMyRWjgtPFyRKRVoMXXjczsTQRDEhYw==" + "resolved" "https://registry.npmjs.org/@pkgr/utils/-/utils-2.4.2.tgz" + "version" "2.4.2" + dependencies: + "cross-spawn" "^7.0.3" + "fast-glob" "^3.3.0" + "is-glob" "^4.0.3" + "open" "^9.1.0" + "picocolors" "^1.0.0" + "tslib" "^2.6.0" + "@reduxjs/toolkit@^1.9.6": "integrity" "sha512-Gc4ikl90ORF4viIdAkY06JNUnODjKfGxZRwATM30EdHq8hLSVoSrwXne5dd739yenP5bJxAX7tLuOWK5RPGtrw==" "resolved" "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.9.6.tgz" @@ -1780,6 +1792,11 @@ dependencies: "tweetnacl" "^0.14.3" +"big-integer@^1.6.44": + "integrity" "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==" + "resolved" "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz" + "version" "1.6.51" + "binary-extensions@^2.0.0": "integrity" "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==" "resolved" "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz" @@ -1804,6 +1821,13 @@ "resolved" "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz" "version" "3.7.2" +"bplist-parser@^0.2.0": + "integrity" "sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==" + "resolved" "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.2.0.tgz" + "version" "0.2.0" + dependencies: + "big-integer" "^1.6.44" + "brace-expansion@^1.1.7": "integrity" "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==" "resolved" "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz" @@ -1861,6 +1885,13 @@ dependencies: "semver" "^7.0.0" +"bundle-name@^3.0.0": + "integrity" "sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==" + "resolved" "https://registry.npmjs.org/bundle-name/-/bundle-name-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "run-applescript" "^5.0.0" + "busboy@1.6.0": "integrity" "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==" "resolved" "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz" @@ -2437,6 +2468,11 @@ "resolved" "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz" "version" "10.4.3" +"decode-uri-component@^0.2.2": + "integrity" "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==" + "resolved" "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz" + "version" "0.2.2" + "dedent@^1.0.0": "integrity" "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==" "resolved" "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz" @@ -2481,6 +2517,24 @@ "resolved" "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz" "version" "4.3.1" +"default-browser-id@^3.0.0": + "integrity" "sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA==" + "resolved" "https://registry.npmjs.org/default-browser-id/-/default-browser-id-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "bplist-parser" "^0.2.0" + "untildify" "^4.0.0" + +"default-browser@^4.0.0": + "integrity" "sha512-wX5pXO1+BrhMkSbROFsyxUm0i/cJEScyNhA4PPxc41ICuv05ZZB/MX28s8aZx6xjmatvebIapF6hLEKEcpneUA==" + "resolved" "https://registry.npmjs.org/default-browser/-/default-browser-4.0.0.tgz" + "version" "4.0.0" + dependencies: + "bundle-name" "^3.0.0" + "default-browser-id" "^3.0.0" + "execa" "^7.1.1" + "titleize" "^3.0.0" + "defaults@^1.0.3": "integrity" "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==" "resolved" "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz" @@ -2497,6 +2551,11 @@ "gopd" "^1.0.1" "has-property-descriptors" "^1.0.0" +"define-lazy-prop@^3.0.0": + "integrity" "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==" + "resolved" "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz" + "version" "3.0.0" + "define-properties@^1.1.3", "define-properties@^1.1.4", "define-properties@^1.2.0", "define-properties@^1.2.1": "integrity" "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==" "resolved" "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz" @@ -2954,6 +3013,14 @@ "resolve" "^1.22.2" "semver" "^7.5.3" +"eslint-plugin-prettier@^5.0.1": + "integrity" "sha512-m3u5RnR56asrwV/lDC4GHorlW75DsFfmUcjfCYylTUs85dBRnB7VM6xG8eCMJdeDRnppzmxZVf1GEPJvl1JmNg==" + "resolved" "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.0.1.tgz" + "version" "5.0.1" + dependencies: + "prettier-linter-helpers" "^1.0.0" + "synckit" "^0.8.5" + "eslint-plugin-promise@^6.0.0", "eslint-plugin-promise@^6.1.1": "integrity" "sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==" "resolved" "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.1.1.tgz" @@ -3022,7 +3089,7 @@ "resolved" "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz" "version" "3.4.3" -"eslint@*", "eslint@^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8", "eslint@^3 || ^4 || ^5 || ^6 || ^7 || ^8", "eslint@^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0", "eslint@^6.0.0 || ^7.0.0 || ^8.0.0", "eslint@^6.0.0 || ^7.0.0 || >=8.0.0", "eslint@^7.0.0 || ^8.0.0", "eslint@^7.23.0 || ^8.0.0", "eslint@^7.32.0 || ^8.2.0", "eslint@^7.5.0 || ^8.0.0", "eslint@^8.0.1", "eslint@^8.49.0", "eslint@>=7.0.0", "eslint@>=8": +"eslint@*", "eslint@^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8", "eslint@^3 || ^4 || ^5 || ^6 || ^7 || ^8", "eslint@^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0", "eslint@^6.0.0 || ^7.0.0 || ^8.0.0", "eslint@^6.0.0 || ^7.0.0 || >=8.0.0", "eslint@^7.0.0 || ^8.0.0", "eslint@^7.23.0 || ^8.0.0", "eslint@^7.32.0 || ^8.2.0", "eslint@^7.5.0 || ^8.0.0", "eslint@^8.0.1", "eslint@^8.49.0", "eslint@>=7.0.0", "eslint@>=8", "eslint@>=8.0.0": "integrity" "sha512-FOnOGSuFuFLv/Sa+FDVRZl4GGVAAFFi8LecRsI5a1tMO5HIE8nCm4ivAlzt4dT3ol/PaaGC0rJEEXQmHJBGoOg==" "resolved" "https://registry.npmjs.org/eslint/-/eslint-8.50.0.tgz" "version" "8.50.0" @@ -3133,6 +3200,21 @@ "signal-exit" "^3.0.3" "strip-final-newline" "^2.0.0" +"execa@^7.1.1": + "integrity" "sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==" + "resolved" "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz" + "version" "7.2.0" + dependencies: + "cross-spawn" "^7.0.3" + "get-stream" "^6.0.1" + "human-signals" "^4.3.0" + "is-stream" "^3.0.0" + "merge-stream" "^2.0.0" + "npm-run-path" "^5.1.0" + "onetime" "^6.0.0" + "signal-exit" "^3.0.7" + "strip-final-newline" "^3.0.0" + "execa@4.1.0": "integrity" "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==" "resolved" "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz" @@ -3228,7 +3310,12 @@ "resolved" "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz" "version" "3.1.3" -"fast-glob@^3.2.12", "fast-glob@^3.2.5", "fast-glob@^3.2.9", "fast-glob@^3.3.1": +"fast-diff@^1.1.2": + "integrity" "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==" + "resolved" "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz" + "version" "1.3.0" + +"fast-glob@^3.2.12", "fast-glob@^3.2.5", "fast-glob@^3.2.9", "fast-glob@^3.3.0", "fast-glob@^3.3.1": "integrity" "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==" "resolved" "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz" "version" "3.3.1" @@ -3291,6 +3378,11 @@ dependencies: "to-regex-range" "^5.0.1" +"filter-obj@^1.1.0": + "integrity" "sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==" + "resolved" "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz" + "version" "1.1.0" + "find-node-modules@^2.1.2": "integrity" "sha512-UC2I2+nx1ZuOBclWVNdcnbDR5dlrOdVb7xNjmT/lHE+LsgztWks3dG7boJ37yTS/venXw84B/mAW9uHVoC5QRg==" "resolved" "https://registry.npmjs.org/find-node-modules/-/find-node-modules-2.1.3.tgz" @@ -4015,6 +4107,16 @@ dependencies: "has-tostringtag" "^1.0.0" +"is-docker@^2.0.0": + "integrity" "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==" + "resolved" "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz" + "version" "2.2.1" + +"is-docker@^3.0.0": + "integrity" "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==" + "resolved" "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz" + "version" "3.0.0" + "is-extglob@^2.1.1": "integrity" "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==" "resolved" "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz" @@ -4056,6 +4158,13 @@ dependencies: "is-extglob" "^2.1.1" +"is-inside-container@^1.0.0": + "integrity" "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==" + "resolved" "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz" + "version" "1.0.0" + dependencies: + "is-docker" "^3.0.0" + "is-installed-globally@~0.4.0": "integrity" "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==" "resolved" "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz" @@ -4209,6 +4318,13 @@ "resolved" "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz" "version" "1.0.2" +"is-wsl@^2.2.0": + "integrity" "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==" + "resolved" "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz" + "version" "2.2.0" + dependencies: + "is-docker" "^2.0.0" + "isarray@^2.0.5": "integrity" "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" "resolved" "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz" @@ -5243,7 +5359,12 @@ "resolved" "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz" "version" "1.4.0" -"next@13.4.19": +"next-router-mock@^0.9.10": + "integrity" "sha512-bK6sRb/xGNFgHVUZuvuApn6KJBAKTPiP36A7a9mO77U4xQO5ukJx9WHlU67Tv8AuySd09pk0+Hu8qMVIAmLO6A==" + "resolved" "https://registry.npmjs.org/next-router-mock/-/next-router-mock-0.9.10.tgz" + "version" "0.9.10" + +"next@>=10.0.0", "next@13.4.19": "integrity" "sha512-HuPSzzAbJ1T4BD8e0bs6B9C1kWQ6gv8ykZoRWs5AQoiIuqbGHHdQO7Ljuvg05Q0Z24E2ABozHe6FxDvI6HfyAw==" "resolved" "https://registry.npmjs.org/next/-/next-13.4.19.tgz" "version" "13.4.19" @@ -5440,6 +5561,16 @@ dependencies: "mimic-fn" "^4.0.0" +"open@^9.1.0": + "integrity" "sha512-OS+QTnw1/4vrf+9hh1jc1jnYjzSG4ttTBB8UxOwAnInG3Uo4ssetzC1ihqaIHjLJnA5GGlRl6QlZXOTQhRBUvg==" + "resolved" "https://registry.npmjs.org/open/-/open-9.1.0.tgz" + "version" "9.1.0" + dependencies: + "default-browser" "^4.0.0" + "define-lazy-prop" "^3.0.0" + "is-inside-container" "^1.0.0" + "is-wsl" "^2.2.0" + "optionator@^0.9.3": "integrity" "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==" "resolved" "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz" @@ -5708,12 +5839,19 @@ "resolved" "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz" "version" "2.8.8" +"prettier-linter-helpers@^1.0.0": + "integrity" "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==" + "resolved" "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz" + "version" "1.0.0" + dependencies: + "fast-diff" "^1.1.2" + "prettier-plugin-tailwindcss@^0.5.6": "integrity" "sha512-2Xgb+GQlkPAUCFi3sV+NOYcSI5XgduvDBL2Zt/hwJudeKXkyvRS65c38SB0yb9UB40+1rL83I6m0RtlOQ8eHdg==" "resolved" "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.5.6.tgz" "version" "0.5.6" -"prettier@^3.0", "prettier@^3.0.3": +"prettier@^3.0", "prettier@^3.0.3", "prettier@>=3.0.0": "integrity" "sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==" "resolved" "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz" "version" "3.0.3" @@ -5817,6 +5955,16 @@ dependencies: "side-channel" "^1.0.4" +"query-string@7.1.3": + "integrity" "sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg==" + "resolved" "https://registry.npmjs.org/query-string/-/query-string-7.1.3.tgz" + "version" "7.1.3" + dependencies: + "decode-uri-component" "^0.2.2" + "filter-obj" "^1.1.0" + "split-on-first" "^1.0.0" + "strict-uri-encode" "^2.0.0" + "querystringify@^2.1.1": "integrity" "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" "resolved" "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz" @@ -5897,7 +6045,7 @@ "react-is" "^18.0.0" "use-sync-external-store" "^1.0.0" -"react@^16.3.2 || ^17.0.0 || ^18.0.0", "react@^16.8 || ^17.0 || ^18.0", "react@^16.8.0 || ^17.0.0 || ^18.0.0", "react@^16.8.0-0 || ^17.0.0 || ^18.0.0", "react@^16.9.0 || ^17.0.0 || ^18", "react@^18.0.0", "react@^18.2.0", "react@>= 16.8.0 || 17.x.x || ^18.0.0-0", "react@18.2.0": +"react@^16.3.2 || ^17.0.0 || ^18.0.0", "react@^16.8 || ^17.0 || ^18.0", "react@^16.8.0 || ^17.0.0 || ^18.0.0", "react@^16.8.0-0 || ^17.0.0 || ^18.0.0", "react@^16.9.0 || ^17.0.0 || ^18", "react@^18.0.0", "react@^18.2.0", "react@>= 16.8.0 || 17.x.x || ^18.0.0-0", "react@>=17.0.0", "react@18.2.0": "integrity" "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==" "resolved" "https://registry.npmjs.org/react/-/react-18.2.0.tgz" "version" "18.2.0" @@ -6124,6 +6272,13 @@ dependencies: "glob" "^7.1.3" +"run-applescript@^5.0.0": + "integrity" "sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==" + "resolved" "https://registry.npmjs.org/run-applescript/-/run-applescript-5.0.0.tgz" + "version" "5.0.0" + dependencies: + "execa" "^5.0.0" + "run-async@^2.4.0": "integrity" "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==" "resolved" "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz" @@ -6328,6 +6483,11 @@ "resolved" "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.15.tgz" "version" "3.0.15" +"split-on-first@^1.0.0": + "integrity" "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==" + "resolved" "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz" + "version" "1.1.0" + "split2@^3.0.0", "split2@^3.2.2": "integrity" "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==" "resolved" "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz" @@ -6374,6 +6534,11 @@ "resolved" "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz" "version" "1.1.0" +"strict-uri-encode@^2.0.0": + "integrity" "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==" + "resolved" "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz" + "version" "2.0.0" + "string_decoder@^1.1.1": "integrity" "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==" "resolved" "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz" @@ -6566,6 +6731,14 @@ "resolved" "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz" "version" "3.2.4" +"synckit@^0.8.5": + "integrity" "sha512-L1dapNV6vu2s/4Sputv8xGsCdAVlb5nRDMFU/E27D44l5U6cw1g0dGd45uLc+OXjNMmF4ntiMdCimzcjFKQI8Q==" + "resolved" "https://registry.npmjs.org/synckit/-/synckit-0.8.5.tgz" + "version" "0.8.5" + dependencies: + "@pkgr/utils" "^2.3.1" + "tslib" "^2.5.0" + "tailwind-merge@^1.14.0": "integrity" "sha512-3mFKyCo/MBcgyOTlrY8T7odzZFx+w+qKSMAmdFzRvqBfLlSigU6TZnlFHK0lkMwj9Bj8OYU+9yW9lmGuS0QEnQ==" "resolved" "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-1.14.0.tgz" @@ -6654,6 +6827,11 @@ dependencies: "readable-stream" "3" +"titleize@^3.0.0": + "integrity" "sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ==" + "resolved" "https://registry.npmjs.org/titleize/-/titleize-3.0.0.tgz" + "version" "3.0.0" + "tmp@^0.0.33": "integrity" "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==" "resolved" "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz" @@ -6751,7 +6929,7 @@ "resolved" "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz" "version" "1.14.1" -"tslib@^2.1.0", "tslib@^2.4.0": +"tslib@^2.1.0", "tslib@^2.4.0", "tslib@^2.5.0", "tslib@^2.6.0": "integrity" "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" "resolved" "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz" "version" "2.6.2" -- GitLab