diff --git a/.eslintrc.js b/.eslintrc.js index 61222b2c..5e2c3ba0 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -31,7 +31,8 @@ module.exports = { "valid-jsdoc": "warn", "no-useless-escape": "off", "no-use-before-define": "off", - "comma-dangle": "off" + "comma-dangle": "off", + "func-names": "off" }, "settings": { "import/resolver": { diff --git a/error.html b/error.html index fc8d855d..9fd6da1d 100644 --- a/error.html +++ b/error.html @@ -8,6 +8,8 @@ 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); })(window,document,'script','dataLayer','GTM-W2JQSNLL'); + + diff --git a/index.html b/index.html index 384a2a0d..cfb615f3 100644 --- a/index.html +++ b/index.html @@ -11,7 +11,7 @@ })(window,document,'script','dataLayer','GTM-W2JQSNLL'); - + ISIC Archive diff --git a/package-lock.json b/package-lock.json index 4ddff461..0319bccc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,10 +22,10 @@ "markdown-it-bracketed-spans": "^1.0.1", "markdown-it-container": "^3.0.0", "mouse-wheel-zoom": "^1.1.5", + "ol": "^10.6.1", "openseadragon": "^2.4.2", "promise-file-reader": "^1.0.3", "util": "^0.12.4", - "vanilla-js-wheel-zoom": "^8.0.0", "webix": "6.2.0", "webix-jet": "^1.5.3", "wheelzoom": "^4.0.1" @@ -43,7 +43,6 @@ "eslint": "^7.32.0", "eslint-config-xbsoftware": "^5.0.0-alpha.3", "eslint-import-resolver-alias": "^1.1.2", - "eslint-import-resolver-webpack": "^0.13.1", "eslint-plugin-import": "^2.25.1", "html-loader": "^5.0.0", "html-webpack-plugin": "^5.3.2", @@ -3001,19 +3000,27 @@ } }, "node_modules/@openid/appauth/node_modules/form-data": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", - "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", + "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", "mime-types": "^2.1.12" }, "engines": { "node": ">= 6" } }, + "node_modules/@petamoriken/float16": { + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@petamoriken/float16/-/float16-3.9.2.tgz", + "integrity": "sha512-VgffxawQde93xKxT3qap3OH+meZf7VaSB5Sqd4Rqc+FP5alWbpOyan/7tRbOAvynjpG3GpdtAuGU/NdhQpmrog==", + "license": "MIT" + }, "node_modules/@resonant/oauth-client": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@resonant/oauth-client/-/oauth-client-1.0.2.tgz", @@ -3317,6 +3324,12 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/rbush": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/rbush/-/rbush-4.0.0.tgz", + "integrity": "sha512-+N+2H39P8X+Hy1I5mC6awlTX54k3FhiUmvt7HWzGJZvF+syUAAxP/stwppS8JE84YHqFgRMv6fCy31202CMFxQ==", + "license": "MIT" + }, "node_modules/@types/retry": { "version": "0.12.2", "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz", @@ -4300,12 +4313,15 @@ } }, "node_modules/axios/node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", + "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", + "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", "mime-types": "^2.1.12" }, "engines": { @@ -4624,15 +4640,6 @@ "npm": "1.2.8000 || >= 1.4.16" } }, - "node_modules/body-parser/node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/body-parser/node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -4777,10 +4784,11 @@ } }, "node_modules/bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -5079,17 +5087,18 @@ } }, "node_modules/compression": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", - "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.8.1.tgz", + "integrity": "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==", "dev": true, + "license": "MIT", "dependencies": { - "accepts": "~1.3.5", - "bytes": "3.0.0", - "compressible": "~2.0.16", + "bytes": "3.1.2", + "compressible": "~2.0.18", "debug": "2.6.9", - "on-headers": "~1.0.2", - "safe-buffer": "5.1.2", + "negotiator": "~0.6.4", + "on-headers": "~1.1.0", + "safe-buffer": "5.2.1", "vary": "~1.1.2" }, "engines": { @@ -5111,6 +5120,37 @@ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true }, + "node_modules/compression/node_modules/negotiator": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", + "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -5492,12 +5532,13 @@ } }, "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", "dev": true, + "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -5863,6 +5904,12 @@ "node": ">= 0.4" } }, + "node_modules/earcut": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/earcut/-/earcut-3.0.2.tgz", + "integrity": "sha512-X7hshQbLyMJ/3RPhyObLARM2sNxxmRALLKx1+NVFFnQ9gKzmCrxm9+uLIAdBcvc8FNLpctqlQ2V6AE92Ol9UDQ==", + "license": "ISC" + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -5912,20 +5959,6 @@ "node": ">= 0.8" } }, - "node_modules/enhanced-resolve": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-0.9.1.tgz", - "integrity": "sha512-kxpoMgrdtkXZ5h0SeraBS1iRntpTpQ3R8ussdb38+UAFnMGX5DDyJXePm+OCHOcoXvHDw7mc2erbJBpDnl7TPw==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "memory-fs": "^0.2.0", - "tapable": "^0.1.8" - }, - "engines": { - "node": ">=0.6" - } - }, "node_modules/enquirer": { "version": "2.3.6", "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", @@ -6043,6 +6076,21 @@ "node": ">= 0.4" } }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-shim-unscopables": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", @@ -6240,70 +6288,6 @@ "ms": "^2.1.1" } }, - "node_modules/eslint-import-resolver-webpack": { - "version": "0.13.10", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-webpack/-/eslint-import-resolver-webpack-0.13.10.tgz", - "integrity": "sha512-ciVTEg7sA56wRMR772PyjcBRmyBMLS46xgzQZqt6cWBEKc7cK65ZSSLCTLVRu2gGtKyXUb5stwf4xxLBfERLFA==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^3.2.7", - "enhanced-resolve": "^0.9.1", - "find-root": "^1.1.0", - "hasown": "^2.0.2", - "interpret": "^1.4.0", - "is-core-module": "^2.15.1", - "is-regex": "^1.2.0", - "lodash": "^4.17.21", - "resolve": "^2.0.0-next.5", - "semver": "^5.7.2" - }, - "engines": { - "node": ">= 6" - }, - "peerDependencies": { - "eslint-plugin-import": ">=1.4.0", - "webpack": ">=1.11.0" - } - }, - "node_modules/eslint-import-resolver-webpack/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-import-resolver-webpack/node_modules/resolve": { - "version": "2.0.0-next.5", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", - "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/eslint-import-resolver-webpack/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver" - } - }, "node_modules/eslint-module-utils": { "version": "2.7.4", "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.4.tgz", @@ -6808,10 +6792,11 @@ } }, "node_modules/esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "estraverse": "^5.1.0" }, @@ -7250,13 +7235,6 @@ "url": "https://github.com/avajs/find-cache-dir?sponsor=1" } }, - "node_modules/find-root": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", - "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", - "dev": true, - "license": "MIT" - }, "node_modules/find-up": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", @@ -7324,14 +7302,17 @@ "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=" }, "node_modules/form-data": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", - "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.4.tgz", + "integrity": "sha512-f0cRzm6dkyVYV3nPoooP8XlccPQukegwhAnpoLcXy+X+A8KfpGOoXwDr9FLZd3wzgLaBGQBE3lY93Zm/i1JvIQ==", "dev": true, + "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.35" }, "engines": { "node": ">= 6" @@ -8192,16 +8173,6 @@ "node": ">= 0.4" } }, - "node_modules/interpret": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", - "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.10" - } - }, "node_modules/ipaddr.js": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz", @@ -10610,6 +10581,12 @@ "shell-quote": "^1.8.1" } }, + "node_modules/lerc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lerc/-/lerc-3.0.0.tgz", + "integrity": "sha512-Rm4J/WaHhRa93nCN2mwWDZFoRVF18G1f47C+kvQWyHGEZxFpTUi73p7lMVSAndyxGt6lJ2/CFbOcf9ra5p8aww==", + "license": "Apache-2.0" + }, "node_modules/less": { "version": "3.13.1", "resolved": "https://registry.npmjs.org/less/-/less-3.13.1.tgz", @@ -11044,13 +11021,6 @@ "dev": true, "license": "0BSD" }, - "node_modules/memory-fs": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.2.0.tgz", - "integrity": "sha512-+y4mDxU4rvXXu5UDSGCGNiesFmwCHuefGMoPCO1WYucNYj7DsLqrFaa2fXVI0H+NNiPTwwzKwspn9yTZqUGqng==", - "dev": true, - "license": "MIT" - }, "node_modules/merge-descriptors": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", @@ -11204,10 +11174,11 @@ "integrity": "sha512-YNFyJnO25kemSH30sOQf1MJpXZc6kBdAfEZM+9AO8Q3MgsEXmaO1jaeKUlKsLuMgxNZQWEpz0/wDRBQOd7fDKw==" }, "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" }, "node_modules/multicast-dns": { "version": "7.2.5", @@ -11461,6 +11432,48 @@ "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", "dev": true }, + "node_modules/ol": { + "version": "10.6.1", + "resolved": "https://registry.npmjs.org/ol/-/ol-10.6.1.tgz", + "integrity": "sha512-xp174YOwPeLj7c7/8TCIEHQ4d41tgTDDhdv6SqNdySsql5/MaFJEJkjlsYcvOPt7xA6vrum/QG4UdJ0iCGT1cg==", + "license": "BSD-2-Clause", + "dependencies": { + "@types/rbush": "4.0.0", + "earcut": "^3.0.0", + "geotiff": "^2.1.3", + "pbf": "4.0.1", + "rbush": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/openlayers" + } + }, + "node_modules/ol/node_modules/geotiff": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/geotiff/-/geotiff-2.1.3.tgz", + "integrity": "sha512-PT6uoF5a1+kbC3tHmZSUsLHBp2QJlHasxxxxPW47QIY1VBKpFB+FcDvX+MxER6UzgLQZ0xDzJ9s48B9JbOCTqA==", + "license": "MIT", + "dependencies": { + "@petamoriken/float16": "^3.4.7", + "lerc": "^3.0.0", + "pako": "^2.0.4", + "parse-headers": "^2.0.2", + "quick-lru": "^6.1.1", + "web-worker": "^1.2.0", + "xml-utils": "^1.0.2", + "zstddec": "^0.1.0" + }, + "engines": { + "node": ">=10.19" + } + }, + "node_modules/ol/node_modules/zstddec": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/zstddec/-/zstddec-0.1.0.tgz", + "integrity": "sha512-w2NTI8+3l3eeltKAdK8QpiLo/flRAr2p8AGeakfMZOXBxOg9HIu4LVDxBi81sYgVhFhdJjv1OrB5ssI8uFPoLg==", + "license": "MIT AND BSD-3-Clause" + }, "node_modules/on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", @@ -11474,10 +11487,11 @@ } }, "node_modules/on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", + "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -11610,6 +11624,12 @@ "node": ">=6" } }, + "node_modules/pako": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz", + "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==", + "license": "(MIT AND Zlib)" + }, "node_modules/param-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", @@ -11638,6 +11658,12 @@ "node": ">=6" } }, + "node_modules/parse-headers": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.6.tgz", + "integrity": "sha512-Tz11t3uKztEW5FEVZnj1ox8GKblWn+PvHY9TmJV5Mll2uHEwRdR/5Li1OlXoECjLYkApdhWy44ocONwXLiKO5A==", + "license": "MIT" + }, "node_modules/parse5": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", @@ -11736,6 +11762,18 @@ "node": ">=8" } }, + "node_modules/pbf": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pbf/-/pbf-4.0.1.tgz", + "integrity": "sha512-SuLdBvS42z33m8ejRbInMapQe8n0D3vN/Xd5fmWM3tufNgRQFBpaW2YVJxQZV4iPNqb0vEFvssMEo5w9c6BTIA==", + "license": "BSD-3-Clause", + "dependencies": { + "resolve-protobuf-schema": "^2.1.0" + }, + "bin": { + "pbf": "bin/pbf" + } + }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -11983,6 +12021,12 @@ "dev": true, "peer": true }, + "node_modules/protocol-buffers-schema": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-3.6.0.tgz", + "integrity": "sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw==", + "license": "MIT" + }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -12078,6 +12122,24 @@ } ] }, + "node_modules/quick-lru": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-6.1.2.tgz", + "integrity": "sha512-AAFUA5O1d83pIHEhJwWCq/RQcRukCkn/NSm2QsTEMle5f2hP0ChI2+3Xb051PZCkLryI/Ir1MVKviT2FIloaTQ==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/quickselect": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/quickselect/-/quickselect-3.0.0.tgz", + "integrity": "sha512-XdjUArbK4Bm5fLLvlm5KpTFOiOThgfWWI4axAZDWg4E/0mKdZyI9tNEfds27qCi1ze/vwTR16kvmmGhRra3c2g==", + "license": "ISC" + }, "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -12111,13 +12173,13 @@ "node": ">= 0.8" } }, - "node_modules/raw-body/node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "dev": true, - "engines": { - "node": ">= 0.8" + "node_modules/rbush": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/rbush/-/rbush-4.0.1.tgz", + "integrity": "sha512-IP0UpfeWQujYC8Jg162rMNc01Rf0gWMMAb2Uxus/Q0qOFw4lCcq6ZnQEZwUoJqWyUGJ9th7JjwI4yIWo+uvoAQ==", + "license": "MIT", + "dependencies": { + "quickselect": "^3.0.0" } }, "node_modules/react-is": { @@ -12370,6 +12432,15 @@ "node": ">=8" } }, + "node_modules/resolve-protobuf-schema": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/resolve-protobuf-schema/-/resolve-protobuf-schema-2.1.0.tgz", + "integrity": "sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ==", + "license": "MIT", + "dependencies": { + "protocol-buffers-schema": "^3.3.1" + } + }, "node_modules/retry": { "version": "0.13.1", "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", @@ -12576,12 +12647,6 @@ "node": ">= 0.8" } }, - "node_modules/send/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, "node_modules/send/node_modules/statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", @@ -13187,16 +13252,6 @@ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "dev": true }, - "node_modules/tapable": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.1.10.tgz", - "integrity": "sha512-jX8Et4hHg57mug1/079yitEKWGB3LCwoxByLsNim89LABq8NqgiX+6iYVOsq0vX8uJHkU+DZ5fnq95f800bEsQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.6" - } - }, "node_modules/terminal-link": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", @@ -13783,11 +13838,6 @@ "node": ">= 8" } }, - "node_modules/vanilla-js-wheel-zoom": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/vanilla-js-wheel-zoom/-/vanilla-js-wheel-zoom-8.0.0.tgz", - "integrity": "sha512-8bssI8g3eMACKrkfuEQvaYthoqqFhtbmt45d7m6Xw/8eV0Qr7MJE9gxDLbDwKFziENpkfquyTCdSURChapOiSQ==" - }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -13850,6 +13900,12 @@ "minimalistic-assert": "^1.0.0" } }, + "node_modules/web-worker": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/web-worker/-/web-worker-1.5.0.tgz", + "integrity": "sha512-RiMReJrTAiA+mBjGONMnjVDP2u3p9R1vkcGz6gDIrOMT3oGuYwX2WRMYI9ipkphSuE5XKEhydbhNEJh4NY9mlw==", + "license": "Apache-2.0" + }, "node_modules/webidl-conversions": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", @@ -14538,6 +14594,12 @@ "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", "dev": true }, + "node_modules/xml-utils": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/xml-utils/-/xml-utils-1.10.2.tgz", + "integrity": "sha512-RqM+2o1RYs6T8+3DzDSoTRAUfrvaejbVHcp3+thnAtDKo8LskR+HomLajEy5UjTz24rpka7AxVBRR3g2wTUkJA==", + "license": "CC0-1.0" + }, "node_modules/xml2js": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", @@ -16820,17 +16882,24 @@ }, "dependencies": { "form-data": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", - "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", + "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", "requires": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", "mime-types": "^2.1.12" } } } }, + "@petamoriken/float16": { + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@petamoriken/float16/-/float16-3.9.2.tgz", + "integrity": "sha512-VgffxawQde93xKxT3qap3OH+meZf7VaSB5Sqd4Rqc+FP5alWbpOyan/7tRbOAvynjpG3GpdtAuGU/NdhQpmrog==" + }, "@resonant/oauth-client": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@resonant/oauth-client/-/oauth-client-1.0.2.tgz", @@ -17110,6 +17179,11 @@ "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", "dev": true }, + "@types/rbush": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/rbush/-/rbush-4.0.0.tgz", + "integrity": "sha512-+N+2H39P8X+Hy1I5mC6awlTX54k3FhiUmvt7HWzGJZvF+syUAAxP/stwppS8JE84YHqFgRMv6fCy31202CMFxQ==" + }, "@types/retry": { "version": "0.12.2", "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz", @@ -17828,12 +17902,14 @@ }, "dependencies": { "form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", + "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", "requires": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", "mime-types": "^2.1.12" } } @@ -18068,12 +18144,6 @@ "unpipe": "1.0.0" }, "dependencies": { - "bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "dev": true - }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -18185,9 +18255,9 @@ } }, "bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", "dev": true }, "call-bind": { @@ -18409,17 +18479,17 @@ } }, "compression": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", - "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.8.1.tgz", + "integrity": "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==", "dev": true, "requires": { - "accepts": "~1.3.5", - "bytes": "3.0.0", - "compressible": "~2.0.16", + "bytes": "3.1.2", + "compressible": "~2.0.18", "debug": "2.6.9", - "on-headers": "~1.0.2", - "safe-buffer": "5.1.2", + "negotiator": "~0.6.4", + "on-headers": "~1.1.0", + "safe-buffer": "5.2.1", "vary": "~1.1.2" }, "dependencies": { @@ -18437,6 +18507,18 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true + }, + "negotiator": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", + "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", + "dev": true + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true } } }, @@ -18712,12 +18794,12 @@ } }, "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", "dev": true, "requires": { - "ms": "2.1.2" + "ms": "^2.1.3" } }, "decimal.js": { @@ -18981,6 +19063,11 @@ "gopd": "^1.2.0" } }, + "earcut": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/earcut/-/earcut-3.0.2.tgz", + "integrity": "sha512-X7hshQbLyMJ/3RPhyObLARM2sNxxmRALLKx1+NVFFnQ9gKzmCrxm9+uLIAdBcvc8FNLpctqlQ2V6AE92Ol9UDQ==" + }, "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -19017,17 +19104,6 @@ "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", "dev": true }, - "enhanced-resolve": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-0.9.1.tgz", - "integrity": "sha512-kxpoMgrdtkXZ5h0SeraBS1iRntpTpQ3R8ussdb38+UAFnMGX5DDyJXePm+OCHOcoXvHDw7mc2erbJBpDnl7TPw==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "memory-fs": "^0.2.0", - "tapable": "^0.1.8" - } - }, "enquirer": { "version": "2.3.6", "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", @@ -19115,6 +19191,17 @@ "es-errors": "^1.3.0" } }, + "es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "requires": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + } + }, "es-shim-unscopables": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", @@ -19399,52 +19486,6 @@ } } }, - "eslint-import-resolver-webpack": { - "version": "0.13.10", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-webpack/-/eslint-import-resolver-webpack-0.13.10.tgz", - "integrity": "sha512-ciVTEg7sA56wRMR772PyjcBRmyBMLS46xgzQZqt6cWBEKc7cK65ZSSLCTLVRu2gGtKyXUb5stwf4xxLBfERLFA==", - "dev": true, - "requires": { - "debug": "^3.2.7", - "enhanced-resolve": "^0.9.1", - "find-root": "^1.1.0", - "hasown": "^2.0.2", - "interpret": "^1.4.0", - "is-core-module": "^2.15.1", - "is-regex": "^1.2.0", - "lodash": "^4.17.21", - "resolve": "^2.0.0-next.5", - "semver": "^5.7.2" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "resolve": { - "version": "2.0.0-next.5", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", - "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", - "dev": true, - "requires": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - } - }, - "semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true - } - } - }, "eslint-module-utils": { "version": "2.7.4", "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.4.tgz", @@ -19682,9 +19723,9 @@ "dev": true }, "esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", "dev": true, "requires": { "estraverse": "^5.1.0" @@ -20023,12 +20064,6 @@ "pkg-dir": "^4.1.0" } }, - "find-root": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", - "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", - "dev": true - }, "find-up": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", @@ -20072,14 +20107,16 @@ "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=" }, "form-data": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", - "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.4.tgz", + "integrity": "sha512-f0cRzm6dkyVYV3nPoooP8XlccPQukegwhAnpoLcXy+X+A8KfpGOoXwDr9FLZd3wzgLaBGQBE3lY93Zm/i1JvIQ==", "dev": true, "requires": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.35" } }, "forwarded": { @@ -20689,12 +20726,6 @@ "side-channel": "^1.0.4" } }, - "interpret": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", - "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", - "dev": true - }, "ipaddr.js": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz", @@ -22445,6 +22476,11 @@ "shell-quote": "^1.8.1" } }, + "lerc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lerc/-/lerc-3.0.0.tgz", + "integrity": "sha512-Rm4J/WaHhRa93nCN2mwWDZFoRVF18G1f47C+kvQWyHGEZxFpTUi73p7lMVSAndyxGt6lJ2/CFbOcf9ra5p8aww==" + }, "less": { "version": "3.13.1", "resolved": "https://registry.npmjs.org/less/-/less-3.13.1.tgz", @@ -22749,12 +22785,6 @@ } } }, - "memory-fs": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.2.0.tgz", - "integrity": "sha512-+y4mDxU4rvXXu5UDSGCGNiesFmwCHuefGMoPCO1WYucNYj7DsLqrFaa2fXVI0H+NNiPTwwzKwspn9yTZqUGqng==", - "dev": true - }, "merge-descriptors": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", @@ -22863,9 +22893,9 @@ "integrity": "sha512-YNFyJnO25kemSH30sOQf1MJpXZc6kBdAfEZM+9AO8Q3MgsEXmaO1jaeKUlKsLuMgxNZQWEpz0/wDRBQOd7fDKw==" }, "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, "multicast-dns": { @@ -23050,6 +23080,40 @@ "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", "dev": true }, + "ol": { + "version": "10.6.1", + "resolved": "https://registry.npmjs.org/ol/-/ol-10.6.1.tgz", + "integrity": "sha512-xp174YOwPeLj7c7/8TCIEHQ4d41tgTDDhdv6SqNdySsql5/MaFJEJkjlsYcvOPt7xA6vrum/QG4UdJ0iCGT1cg==", + "requires": { + "@types/rbush": "4.0.0", + "earcut": "^3.0.0", + "geotiff": "^2.1.3", + "pbf": "4.0.1", + "rbush": "^4.0.0" + }, + "dependencies": { + "geotiff": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/geotiff/-/geotiff-2.1.3.tgz", + "integrity": "sha512-PT6uoF5a1+kbC3tHmZSUsLHBp2QJlHasxxxxPW47QIY1VBKpFB+FcDvX+MxER6UzgLQZ0xDzJ9s48B9JbOCTqA==", + "requires": { + "@petamoriken/float16": "^3.4.7", + "lerc": "^3.0.0", + "pako": "^2.0.4", + "parse-headers": "^2.0.2", + "quick-lru": "^6.1.1", + "web-worker": "^1.2.0", + "xml-utils": "^1.0.2", + "zstddec": "^0.1.0" + } + }, + "zstddec": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/zstddec/-/zstddec-0.1.0.tgz", + "integrity": "sha512-w2NTI8+3l3eeltKAdK8QpiLo/flRAr2p8AGeakfMZOXBxOg9HIu4LVDxBi81sYgVhFhdJjv1OrB5ssI8uFPoLg==" + } + } + }, "on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", @@ -23060,9 +23124,9 @@ } }, "on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", + "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==", "dev": true }, "once": { @@ -23154,6 +23218,11 @@ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true }, + "pako": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz", + "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==" + }, "param-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", @@ -23181,6 +23250,11 @@ "callsites": "^3.0.0" } }, + "parse-headers": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.6.tgz", + "integrity": "sha512-Tz11t3uKztEW5FEVZnj1ox8GKblWn+PvHY9TmJV5Mll2uHEwRdR/5Li1OlXoECjLYkApdhWy44ocONwXLiKO5A==" + }, "parse5": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", @@ -23266,6 +23340,14 @@ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "dev": true }, + "pbf": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pbf/-/pbf-4.0.1.tgz", + "integrity": "sha512-SuLdBvS42z33m8ejRbInMapQe8n0D3vN/Xd5fmWM3tufNgRQFBpaW2YVJxQZV4iPNqb0vEFvssMEo5w9c6BTIA==", + "requires": { + "resolve-protobuf-schema": "^2.1.0" + } + }, "picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -23443,6 +23525,11 @@ } } }, + "protocol-buffers-schema": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-3.6.0.tgz", + "integrity": "sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw==" + }, "proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -23510,6 +23597,16 @@ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", "dev": true }, + "quick-lru": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-6.1.2.tgz", + "integrity": "sha512-AAFUA5O1d83pIHEhJwWCq/RQcRukCkn/NSm2QsTEMle5f2hP0ChI2+3Xb051PZCkLryI/Ir1MVKviT2FIloaTQ==" + }, + "quickselect": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/quickselect/-/quickselect-3.0.0.tgz", + "integrity": "sha512-XdjUArbK4Bm5fLLvlm5KpTFOiOThgfWWI4axAZDWg4E/0mKdZyI9tNEfds27qCi1ze/vwTR16kvmmGhRra3c2g==" + }, "randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -23535,14 +23632,14 @@ "http-errors": "2.0.0", "iconv-lite": "0.4.24", "unpipe": "1.0.0" - }, - "dependencies": { - "bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "dev": true - } + } + }, + "rbush": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/rbush/-/rbush-4.0.1.tgz", + "integrity": "sha512-IP0UpfeWQujYC8Jg162rMNc01Rf0gWMMAb2Uxus/Q0qOFw4lCcq6ZnQEZwUoJqWyUGJ9th7JjwI4yIWo+uvoAQ==", + "requires": { + "quickselect": "^3.0.0" } }, "react-is": { @@ -23741,6 +23838,14 @@ "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true }, + "resolve-protobuf-schema": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/resolve-protobuf-schema/-/resolve-protobuf-schema-2.1.0.tgz", + "integrity": "sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ==", + "requires": { + "protocol-buffers-schema": "^3.3.1" + } + }, "retry": { "version": "0.13.1", "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", @@ -23889,12 +23994,6 @@ "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", "dev": true }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, "statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", @@ -24384,12 +24483,6 @@ } } }, - "tapable": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.1.10.tgz", - "integrity": "sha512-jX8Et4hHg57mug1/079yitEKWGB3LCwoxByLsNim89LABq8NqgiX+6iYVOsq0vX8uJHkU+DZ5fnq95f800bEsQ==", - "dev": true - }, "terminal-link": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", @@ -24828,11 +24921,6 @@ } } }, - "vanilla-js-wheel-zoom": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/vanilla-js-wheel-zoom/-/vanilla-js-wheel-zoom-8.0.0.tgz", - "integrity": "sha512-8bssI8g3eMACKrkfuEQvaYthoqqFhtbmt45d7m6Xw/8eV0Qr7MJE9gxDLbDwKFziENpkfquyTCdSURChapOiSQ==" - }, "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -24885,6 +24973,11 @@ "minimalistic-assert": "^1.0.0" } }, + "web-worker": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/web-worker/-/web-worker-1.5.0.tgz", + "integrity": "sha512-RiMReJrTAiA+mBjGONMnjVDP2u3p9R1vkcGz6gDIrOMT3oGuYwX2WRMYI9ipkphSuE5XKEhydbhNEJh4NY9mlw==" + }, "webidl-conversions": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", @@ -25357,6 +25450,11 @@ "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", "dev": true }, + "xml-utils": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/xml-utils/-/xml-utils-1.10.2.tgz", + "integrity": "sha512-RqM+2o1RYs6T8+3DzDSoTRAUfrvaejbVHcp3+thnAtDKo8LskR+HomLajEy5UjTz24rpka7AxVBRR3g2wTUkJA==" + }, "xml2js": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", diff --git a/package.json b/package.json index 5c3c3c9f..8d0530f5 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,6 @@ "eslint": "^7.32.0", "eslint-config-xbsoftware": "^5.0.0-alpha.3", "eslint-import-resolver-alias": "^1.1.2", - "eslint-import-resolver-webpack": "^0.13.1", "eslint-plugin-import": "^2.25.1", "html-loader": "^5.0.0", "html-webpack-plugin": "^5.3.2", @@ -54,10 +53,10 @@ "markdown-it-bracketed-spans": "^1.0.1", "markdown-it-container": "^3.0.0", "mouse-wheel-zoom": "^1.1.5", + "ol": "^10.6.1", "openseadragon": "^2.4.2", "promise-file-reader": "^1.0.3", "util": "^0.12.4", - "vanilla-js-wheel-zoom": "^8.0.0", "webix": "6.2.0", "webix-jet": "^1.5.3", "wheelzoom": "^4.0.1" diff --git a/sources/app.js b/sources/app.js index 1591f31b..8cf16cb1 100644 --- a/sources/app.js +++ b/sources/app.js @@ -89,7 +89,7 @@ webix.ready(() => { auth.refreshUserInfo(); } const root = app.getRoot(); - if (typeof (root.scrollTo) === "function") { + if (typeof root.scrollTo === "function") { root.scrollTo(0, 0); } }); diff --git a/sources/constants.js b/sources/constants.js index 839edb36..02390fff 100644 --- a/sources/constants.js +++ b/sources/constants.js @@ -185,15 +185,6 @@ export default { MISSING_KEY_VALUE: "missing key", COLLECTION_KEY: "collections", - DEFAULT_RIBBON_IMAGE_ICON_WIDTH: 14, - DEFAULT_RIBBON_IMAGE_ICON_HEIGHT: 14, - DEFAULT_RIBBON_ICON_CONTAINER_WIDTH: 18, - DEFAULT_RIBBON_ICON_CONTAINER_HEIGHT: 18, - DEFAULT_GALLERY_IMAGE_ICON_WIDTH: 18, - DEFAULT_GALLERY_IMAGE_ICON_HEIGHT: 18, - DEFAULT_GALLERY_IMAGE_ICON_CONTAINER_WIDTH: 22, - DEFAULT_GALLERY_IMAGE_ICON_CONTAINER_HEIGHT: 22, - DEFAULT_GALLERY_IMAGE_NAME_FONT_SIZE: 14, DEFAULT_GALLERY_IMAGE_WIDTH: 180, DEFAULT_GALLERY_IMAGE_HEIGHT: 123, diff --git a/sources/models/appliedFilters.js b/sources/models/appliedFilters.js index b9013318..2dce737b 100644 --- a/sources/models/appliedFilters.js +++ b/sources/models/appliedFilters.js @@ -4,7 +4,7 @@ import state from "./state"; const appliedFilters = new webix.DataCollection(); const appliedFilterBySearch = new webix.DataCollection(); -const showedFilters = new webix.DataCollection(); +const shownFilters = new webix.DataCollection(); let filterValue = ""; let filterByName; @@ -12,8 +12,8 @@ function getAppliedFilterBySearchCollection() { return appliedFilterBySearch; } -function getShowedFiltersCollection() { - return showedFilters; +function getShownFiltersCollection() { + return shownFilters; } function setAppliedFiltersToLocalStorage(appliedFiltersToStorage) { @@ -428,7 +428,7 @@ function getConditionsForApi() { if (diagnosisFilters.length !== 0) { conditions.operator = diagnosisFilters.length > 1 ? "OR" : ""; diagnosisFilters.forEach((d) => { - conditions.operands.push(...(_prepareCondition(d))); + conditions.operands.push(..._prepareCondition(d)); }); } let query = diagnosisFilters.length > 0 ? "(" : ""; @@ -457,7 +457,7 @@ function getConditionsForApi() { query += query === "" ? "" : " AND "; conditions.operator = groupedFilters.length > 1 ? "AND" : ""; groupedFilters.forEach((groupedFilter) => { - conditions.operands.push(...(_prepareCondition(groupedFilter))); + conditions.operands.push(..._prepareCondition(groupedFilter)); }); } conditions.operands.forEach((itemOfConditions, paramIndex) => { @@ -520,9 +520,9 @@ function getFiltersFromURL(filtersArray) { return data; } return null; - } else { - filterId = filter; } + filterId = filter; + const control = $$(filterId); if (control) { const data = control.config.filtersChangedData; @@ -554,9 +554,10 @@ function getAppliedCollectionsForApi() { /** * Get filters changed data for checkboxes - * @param {object} data - * @param {object} currentOption - * @param {String} optionName + * @param {Object} data + * @param {Object} currentOption + * @param {string} optionName + * @returns {Object} */ function getFiltersChangedData(data, currentOption, optionName) { const filtersChangedData = {}; @@ -576,10 +577,11 @@ function getFiltersChangedData(data, currentOption, optionName) { /** * - * @param {object} data - * @param {object} item - * @param {String} datatype - * @param {boolean} state + * @param {Object} data + * @param {Object} item + * @param {string} datatype + * @param {boolean} remove + * @returns {Object} */ function getFiltersChangeTreeItemData(data, item, datatype, remove) { const filtersChangedData = {}; @@ -617,7 +619,7 @@ export default { getAppliedFilterBySearchCollection, setFilterValue, getFilterValue, - getShowedFiltersCollection, + getShownFiltersCollection, getFiltersFromURL, convertAppliedFiltersToParams, getAppliedCollectionsForApi, diff --git a/sources/models/diagnosis.js b/sources/models/diagnosis.js index c11b536e..cd3659c9 100644 --- a/sources/models/diagnosis.js +++ b/sources/models/diagnosis.js @@ -1,3 +1,5 @@ +import ajaxActions from "app-services/ajaxActions"; + /** * @typedef {Object} Diagnosis * @property {number} level @@ -16,12 +18,20 @@ function getDiagnosisFlat() { return diagnosisFlat; } -function getDiagnosisDataForFilters() { - const data = convertDiagnosisToTreeArray(diagnosisTree); - return data; +async function getDiagnosisDataForFilters() { + const facets = await ajaxActions.getFacets(); + const diagnosisKeys = Object.keys(facets).filter(key => /^diagnosis_\d+$/.test(key)); + const diagnosisCountMap = new Map(); + + diagnosisKeys.forEach((key) => { + (facets[key].buckets || []).forEach((bucket) => { + diagnosisCountMap.set(bucket.key, bucket.doc_count ?? 0); + }); + }); + return convertDiagnosisToTreeArray(diagnosisTree, diagnosisCountMap); } -function convertDiagnosisToTreeArray(tree) { +function convertDiagnosisToTreeArray(tree, diagnosisCountMap) { const dataForFilters = []; const diagnosisKeys = Object.keys(tree); diagnosisKeys.forEach((k) => { @@ -33,9 +43,13 @@ function convertDiagnosisToTreeArray(tree) { diagnosisItem.datatype = "string"; diagnosisItem.level = diagnosisFlat[k].level; diagnosisItem.data = diagnosisFlat[k].children - ? convertDiagnosisToTreeArray(tree[k].children) + ? convertDiagnosisToTreeArray(tree[k].children, diagnosisCountMap) : null; diagnosisItem.parent = diagnosisFlat[k].parent; + const optionCount = diagnosisCountMap.get(k) ?? 0; + const optionChildrenCount = (diagnosisFlat[k].children || []) + .reduce((sum, childKey) => sum + (diagnosisCountMap.get(childKey) ?? 0), 0); + diagnosisItem.hasHiddenOption = optionCount > optionChildrenCount; dataForFilters.push(diagnosisItem); } }); diff --git a/sources/models/imagesFilters.js b/sources/models/imagesFilters.js index 24686959..34d4b7e1 100644 --- a/sources/models/imagesFilters.js +++ b/sources/models/imagesFilters.js @@ -31,8 +31,8 @@ const filtersIds = { fitzpatrickSkinType: "fitzpatrick_skin_type" }; -function getFiltersDataValues() { - const diagnosisData = diagnosisModel.getDiagnosisDataForFilters(); +async function getFiltersDataValues() { + const diagnosisData = await diagnosisModel.getDiagnosisDataForFilters(); const filtersDataValues = [ { label: "Diagnostic Attributes", @@ -198,14 +198,11 @@ function getFiltersDataValues() { return filtersDataValues; } -function getFiltersData(forceRebuild) { - return new Promise((resolve) => { - // we should rewrite the last item in filtersData (it is place for Database Attributes) - if (forceRebuild || !filtersData) { - filtersData = getFiltersDataValues(); - } - resolve(filtersData); - }); +async function getFiltersData(forceRebuild) { + if (forceRebuild || !filtersData) { + filtersData = await getFiltersDataValues(); + } + return filtersData; } export default { diff --git a/sources/services/ajaxActions.js b/sources/services/ajaxActions.js index 8541e5ed..875fa6ed 100644 --- a/sources/services/ajaxActions.js +++ b/sources/services/ajaxActions.js @@ -176,7 +176,8 @@ class AjaxActions { } }); return facets; - } catch (error) { + } + catch (error) { return parseError(error); } } diff --git a/sources/services/createStudy/createStudy.js b/sources/services/createStudy/createStudy.js index a0b2172b..0046203b 100644 --- a/sources/services/createStudy/createStudy.js +++ b/sources/services/createStudy/createStudy.js @@ -169,7 +169,6 @@ export default class CreateStudyService { this._createStudyButton.attachEvent("onItemClick", () => { let features = []; let annotatorsIds = []; - let imageIds = []; let questions = []; let nameRegEx = / /g; let studyName = this._studyNameTextView.getValue(); @@ -276,11 +275,6 @@ export default class CreateStudyService { let annotatorItem = this._annotatorsList.getItem(annotatorItemId); annotatorsIds.push(annotatorItem.isic_id); }); - this._imageDataView.find((obj) => { - if (obj.isic_id) { - imageIds.push(obj.isic_id); - } - }); return false; }); } diff --git a/sources/services/gallery/filter.js b/sources/services/gallery/filter.js index e2d6c6a2..659b1468 100644 --- a/sources/services/gallery/filter.js +++ b/sources/services/gallery/filter.js @@ -93,21 +93,6 @@ function _setDiagnosisFilterCounts(treeView, option, totalCount, currentCount) { treeView.updateItem(option.id, option); } -function _setDiagnosisFilterState(treeView, option, totalCount, currentCount) { - if ( - currentCount !== null - && currentCount < totalCount - && treeView.isBranch(option.id) - && !option.indeterminate - ) { - treeView.blockEvent(); - treeView.add({id: `${option.id}|empty`, hidden: true, name: ""}, 0, option.id); - treeView.uncheckItem(`${option.id}|empty`); - treeView.remove(`${option.id}|empty`); - treeView.unblockEvent(); - } -} - function updateFiltersFormControl(data) { if (!data) { return; @@ -155,22 +140,32 @@ function updateTreeCheckboxControl(data) { treeView.show(); } treeView.checkItem(data.id); - treeView.open(data.id); - const parentId = treeView.getParentId(data.id); - if (parentId) { - const parent = treeView.getItem(parentId); - changeParentState(treeView, parent); - } + openParentBranch(treeView, data.id); + setParentCheckboxState(treeView, data.id); treeView.unblockEvent(); } } -function changeParentState(treeView, option) { - treeView.open(option.id); - const parentId = treeView.getParentId(option.id); +function setParentCheckboxState(treeView, optionId) { + const parentId = treeView.getParentId(optionId); + if (!parentId) return; + + const parentItem = treeView.getItem(parentId); + if (parentItem.hasHiddenOption) { + treeView.add({id: `${parentId}|empty`, hidden: true, name: ""}, 0, parentId); + treeView.uncheckItem(`${parentId}|empty`); + treeView.remove(`${parentId}|empty`); + } + else { + setParentCheckboxState(treeView, parentId); + } +} + +function openParentBranch(treeView, optionId) { + treeView.open(optionId); + const parentId = treeView.getParentId(optionId); if (parentId) { - const parentOption = treeView.getItem(parentId); - changeParentState(treeView, parentOption); + openParentBranch(treeView, parentId); } } @@ -250,7 +245,6 @@ function updateFiltersCounts(countsAfterFiltration) { const option = treeView?.getItem(optionId); if (option) { _setDiagnosisFilterCounts(treeView, option, value.doc_count, currentCount); - _setDiagnosisFilterState(treeView, option, value.doc_count, currentCount); if (!displayDiagnosis.find(item => item === v)) { treeView.remove(optionId); } @@ -295,5 +289,4 @@ export default { prepareOptionName, updateFiltersCounts, updateFiltersFormControl, - changeParentState, }; diff --git a/sources/services/gallery/gallery.js b/sources/services/gallery/gallery.js index 8aee74a3..56f3f303 100644 --- a/sources/services/gallery/gallery.js +++ b/sources/services/gallery/gallery.js @@ -1,5 +1,4 @@ -import "wheelzoom"; -import WZoom from "vanilla-js-wheel-zoom"; +import {createZoomableImage, zoomImage} from "app-services/zoomImages"; import constants from "../../constants"; import appliedFilterModel from "../../models/appliedFilters"; @@ -14,7 +13,6 @@ import logger from "../../utils/logger"; import util from "../../utils/util"; import filtersFormElements from "../../views/subviews/gallery/parts/filtersFormElements"; import metadataPart from "../../views/subviews/gallery/parts/metadata"; -import imageWindow from "../../views/subviews/gallery/windows/imageWindow"; import ajax from "../ajaxActions"; import authService from "../auth"; import filterService from "./filter"; @@ -38,6 +36,8 @@ class GalleryService { contentHeaderTemplate, imageWindowInstance, imageWindowViewer, + imageWindowSlideButton, + imageWindowMetadataContainer, imageWindowMetadata, metadataWindow, metadataWindowMetadata, @@ -72,6 +72,8 @@ class GalleryService { this._contentHeaderTemplate = contentHeaderTemplate; this._imageWindow = imageWindowInstance; this._imageWindowViewer = imageWindowViewer; + this._imageWindowSlideButton = imageWindowSlideButton; + this._imageWindowMetadataContainer = imageWindowMetadataContainer; this._imageWindowMetadata = imageWindowMetadata; this._metadataWindow = metadataWindow; this._metadataWindowMetadata = metadataWindowMetadata; @@ -224,7 +226,6 @@ class GalleryService { this._searchInput.disable(); this._createStudyButton = this._view.$scope.getCreateStudyButton(); this._dataviewYCountSelection = this._view.$scope.getDataviewYCountSelection(); - this._imageTemplate = $$(imageWindow.getViewerId()); if (this._imageWindow) { [this._imageWindowZoomPlusButtons, this._imageZoomMunusButtons] = this._imageWindow?.$view.getElementsByClassName("zoom-btn"); } @@ -278,11 +279,7 @@ class GalleryService { if (newValue) { this._filtersForm.disable(); this._appliedFiltersList.disable(); - if (appliedFilterModel.count()) { - this._appliedFiltersList.clearAll(); - appliedFilterModel.clearAll(); - this._reload(); - } + clearAllFilters(); tooltipText = "Clear name filter"; this._searchEventsMethods(this._searchHandlerByName.bind(this), true); @@ -359,12 +356,10 @@ class GalleryService { this._dataviewYCountSelection?.attachEvent("onChange", (id, oldId, callUpdatePager = true) => { let newItemWidth; let newImageWidth; - let newInnerImageNameSize; const previousItemHeight = this._imagesDataview.type.height; let multiplier = constants.DEFAULT_GALLERY_IMAGE_HEIGHT / constants.DEFAULT_GALLERY_IMAGE_WIDTH; let dataviewWidth = this._imagesDataview.$width; - let fontSizeMultiplier = this._getInitialFontSizeMultiplier(); switch (id) { case constants.TWO_DATAVIEW_COLUMNS: { @@ -409,8 +404,6 @@ class GalleryService { } const newImageHeight = Math.round(multiplier * newImageWidth); - newInnerImageNameSize = Math.round(newImageHeight * fontSizeMultiplier); - util.setNewThumnailsNameFontSize(newInnerImageNameSize); util.setDataviewSelectionId(id); this._setDataviewColumns(newItemWidth, previousItemHeight, newImageWidth, newImageHeight); if (callUpdatePager) { @@ -497,51 +490,6 @@ class GalleryService { return true; }); - this._imageWindowTemplate?.attachEvent("onAfterRender", () => { - if (this._imageInstance) { - this.wzoom.destroy(); - } - if (this._imageWindow) { - this._imageInstance = this._imageWindow.$view.getElementsByClassName("zoomable-image")[0]; - } - const wzoomOptions = { - type: "image", - maxScale: 5, - zoomOnClick: false, - minScale: 1 - }; - this.wzoom = WZoom.create(this._imageInstance, wzoomOptions); - // TODO: check this - setTimeout(() => { - this.wzoom.transform(0, 0, 1); - }); - }); - - this._imageTemplate?.attachEvent("onBeforeRender", async (obj) => { - if (typeof galleryImagesUrls.getNormalImageUrl(obj.imageId) === "undefined") { - const item = await ajax.getImageItem(obj.imageId); - galleryImagesUrls.setNormalImageUrl(obj.imageId, item.files.full.url); - this._imageTemplate.refresh(); - } - return true; - }); - - this._imageTemplate?.attachEvent("onAfterRender", () => { - if (this._imageInstance) { - this.wzoom.destroy(); - } - if (this._imageWindow) { - this._imageInstance = this._imageWindow.$view.getElementsByClassName("zoomable-image")[0]; - } - const wzoomOptions = { - minScale: 1, - type: "image", - maxScale: 5, - speed: 1.2 - }; - this.wzoom = WZoom.create(this._imageInstance, wzoomOptions); - }); - this._imageWindowTemplateWithoutControls?.attachEvent("onBeforeRender", async (obj) => { if (obj.imageId && typeof galleryImagesUrls.getNormalImageUrl(obj.imageId) === "undefined") { const item = await ajax.getImageItem(obj.imageId); @@ -551,20 +499,22 @@ class GalleryService { return true; }); - this._imageWindowTemplateWithoutControls?.attachEvent("onAfterRender", () => { - if (this._imageInstance) { - this.wzoom.destroy(); + const getZoomableImageNode = () => this._imageWindow.$view.getElementsByClassName("zoomable-image")[0]; + + const initZoomableImage = async () => { + this._zoomableImageProperties = await createZoomableImage(getZoomableImageNode()); + }; + + this._imageWindowTemplate?.attachEvent("onAfterRender", initZoomableImage); + this._imageWindowTemplateWithoutControls?.attachEvent("onAfterRender", initZoomableImage); + + this._imageWindowSlideButton?.attachEvent("onChange", (shouldShowMetadata) => { + if (shouldShowMetadata) { + this._imageWindowMetadataContainer.show(); + } + else { + this._imageWindowMetadataContainer.hide(); } - if (this._imageWindow) { - this._imageInstance = this._imageWindow.$view.getElementsByClassName("zoomable-image")[0]; - } - const wzoomOptions = { - minScale: 1, - type: "image", - maxScale: 5, - speed: 1.2 - }; - this.wzoom = WZoom.create(this._imageInstance, wzoomOptions); }); this._imagesDataview.on_click["resize-icon"] = (e, id) => { @@ -595,28 +545,28 @@ class GalleryService { this._imageWindowZoomButtons?.define("onClick", { "btn-plus": () => { - this._zoomImage("plus"); + zoomImage(this._zoomableImageProperties, true); }, "btn-minus": () => { - this._zoomImage("minus"); + zoomImage(this._zoomableImageProperties, false); } }); this._leftLandImageWindowZoomButton?.define("onClick", { "land-btn-plus": () => { - this._zoomImage("plus"); + zoomImage(this._zoomableImageProperties, true); }, "land-btn-minus": () => { - this._zoomImage("minus"); + zoomImage(this._zoomableImageProperties, false); } }); this._rightLandImageWindowZoomButton?.define("onClick", { "land-btn-plus": () => { - this._zoomImage("plus"); + zoomImage(this._zoomableImageProperties, true); }, "land-btn-minus": () => { - this._zoomImage("minus"); + zoomImage(this._zoomableImageProperties, false); } }); @@ -1312,19 +1262,11 @@ class GalleryService { } } - // expandedFilters - array of filter that should be initially expanded - _createFilters(expandedFilters, forceRebuild) { - let expandedFiltersKeys = []; - if (expandedFilters && expandedFilters.length) { - expandedFiltersKeys = expandedFilters.map((item) => { - if (item.view === constants.FILTER_ELEMENT_TYPE.TREE_CHECKBOX) { - return item.id; - } - return item.key; - }); - } + // appliedFilters - array of filter that should be initially expanded + _createFilters(appliedFilters, forceRebuild) { + const appliedFiltersKeys = (appliedFilters || []).map(item => item.key); return filtersData.getFiltersData(forceRebuild).then((data) => { - const elements = filtersFormElements.transformToFormFormat(data, expandedFiltersKeys); + const elements = filtersFormElements.transformToFormFormat(data, appliedFiltersKeys); this.clearFilterForm(); this._filtersForm = this._view.$scope.getFiltersForm(); webix.ui(elements, this._filtersForm); @@ -1555,14 +1497,8 @@ class GalleryService { this._imagesDataview.refresh(); } - _getInitialFontSizeMultiplier() { - const initialFontSize = constants.DEFAULT_GALLERY_IMAGE_NAME_FONT_SIZE; - const initialImageWidth = constants.DEFAULT_GALLERY_IMAGE_WIDTH; - return initialFontSize / initialImageWidth; - } - _clearActiveListData(clearModifyObjects) { - this._activeCartList.data.each(item => { + this._activeCartList.data.each((item) => { item.imageShown = false; }); this._activeCartList.clearAll(); @@ -1631,15 +1567,6 @@ class GalleryService { } } - _zoomImage(buttonIcon) { - if (buttonIcon === "plus") { - this.wzoom.zoomUp(); - } - else if (buttonIcon === "minus") { - this.wzoom.zoomDown(); - } - } - _removeTooltipForDataview(templateView) { const tooltipClassName = constants.TOOLTIP_CLASS_NAME_FOR_DATAVIEW; Array.from(templateView.$view.querySelectorAll("span")).forEach((element) => { diff --git a/sources/services/gallery/multiimageLesionWindow.js b/sources/services/gallery/multiimageLesionWindow.js index 00e586e0..6bc7d4a9 100644 --- a/sources/services/gallery/multiimageLesionWindow.js +++ b/sources/services/gallery/multiimageLesionWindow.js @@ -1,3 +1,5 @@ +import {createZoomableImage} from "app-services/zoomImages"; + import constants from "../../constants"; import galleryImagesUrls from "../../models/galleryImagesUrls"; import lesionWindowImagesUrls from "../../models/lesionWindowImagesUrls"; @@ -55,11 +57,20 @@ export default class MultiLesionWindowService { } async init() { - this._leftImage.attachEvent("onBeforeRender", this.updateImage); - this._leftImage.attachEvent("onAfterLoad", this.updateImage); + const initZoomableImage = async (imageObj) => { + imageObj._zoomableImageProperties = await createZoomableImage( + this.getZoomableImageNode(imageObj.$view) + ); + }; - this._rightImage.attachEvent("onBeforeRender", this.updateImage); - this._rightImage.attachEvent("onAfterLoad", this.updateImage); + const images = [this._leftImage, this._rightImage]; + images.forEach((imageObj) => { + imageObj.attachEvent("onBeforeRender", this.updateImage); + imageObj.attachEvent("onAfterRender", async () => { + await initZoomableImage(imageObj); + }); + imageObj.attachEvent("onAfterLoad", this.updateImage); + }); this._fullScreenButton.attachEvent("onItemClick", () => { this.changeWindowMode(); }); this._windowedButton.attachEvent("onItemClick", () => { this.changeWindowMode(); }); @@ -376,11 +387,15 @@ export default class MultiLesionWindowService { } } + getZoomableImageNode(containerNode) { + return containerNode.getElementsByClassName("zoomable-image")[0]; + } + changeWindowMode() { if (this._fullscreen) { this._fullscreen = false; - this._window.define("width", 1240); - this._window.define("height", 750); + this._window.define("width", this._window.config.initialWidth); + this._window.define("height", this._window.config.initialHeight); this._window.define("position", "center"); this._fullScreenButton.show(); this._windowedButton.hide(); @@ -393,6 +408,7 @@ export default class MultiLesionWindowService { this._fullScreenButton.hide(); this._windowedButton.show(); } + this.searchImagesByQueryHandler(); } diff --git a/sources/services/gallery/searchSuggest.js b/sources/services/gallery/searchSuggest.js index 3958f2c7..fb123c46 100644 --- a/sources/services/gallery/searchSuggest.js +++ b/sources/services/gallery/searchSuggest.js @@ -57,15 +57,74 @@ function attachEvents(searchSuggest, searchInput, toggleButton) { // remove default behavior suggestList.detachEvent("onItemClick"); + const getAffectedSuggestTreeItems = (clickedItem, selectedIds) => { + const suggestData = suggestList.serialize(); + const isClickedItemSelected = suggestList.isSelected(clickedItem.id); + + const itemParents = suggestData.filter( + suggestItem => clickedItem.optionId.includes(suggestItem.optionId) + && suggestItem.optionId !== clickedItem.optionId + ).sort((a, b) => b.level - a.level); + + const itemChildren = suggestData.filter( + suggestItem => suggestItem.optionId.includes(clickedItem.optionId) + && suggestItem.optionId !== clickedItem.optionId + ); + + if (isClickedItemSelected) { + return [...itemParents, ...itemChildren]; + } + + const affectedParents = []; + let directChild = clickedItem; + for (const parent of itemParents) { + const directChildOptionId = directChild.optionId; + const nonSelectedChildren = suggestData.filter(item => item.optionId.includes(parent.optionId) + && item.optionId !== parent.optionId + && item.level === parent.level + 1 + && item.optionId !== directChildOptionId + && !selectedIds.includes(item.id)); + directChild = parent; + if (!parent.hasHiddenOption && nonSelectedChildren.length === 0) { + affectedParents.push(parent); + } + else { + break; + } + } + + return [...affectedParents, ...itemChildren]; + }; + // add new behavior suggestList.attachEvent("onItemClick", (id, event) => { - const item = suggestList.getItem(id); + const clickedItem = suggestList.getItem(id); + const isClickedItemSelected = suggestList.isSelected(id); + const isTreeCheckbox = clickedItem.key === "diagnosis"; + + if (isTreeCheckbox) { + const suggestItemsToToggle = + getAffectedSuggestTreeItems(clickedItem, suggestList.getSelectedId()); + const suggestIdsToToggle = suggestItemsToToggle.map(suggestItem => suggestItem.id); + + suggestList.blockEvent(); + if (!isClickedItemSelected) { + suggestList.select(suggestIdsToToggle, true); + } + else { + suggestIdsToToggle.forEach((suggestIdToToggle) => { + suggestList.unselect(suggestIdToToggle); + }); + } + suggestList.unblockEvent(); + } + const appliedFilters = appliedFiltersModel.getFiltersArray(); const filterIds = appliedFilters.map(a => a.id); - if (item.key === "diagnosis") { + if (clickedItem.key === "diagnosis") { /** @type {webix.ui.treetable} */ - const diagnosisTree = $$(`treeTable-${item.key}`); - const controlId = item.optionId; + const diagnosisTree = $$(`treeTable-${clickedItem.key}`); + const controlId = clickedItem.optionId; const control = diagnosisTree.getItem(controlId); if (control) { if (diagnosisTree.isChecked(controlId)) { @@ -83,7 +142,7 @@ function attachEvents(searchSuggest, searchInput, toggleButton) { } } else { - const controlId = item.optionId; + const controlId = clickedItem.optionId; /** @type {webix.ui.checkbox} */ const control = $$(controlId); if (control) { @@ -99,23 +158,27 @@ function attachEvents(searchSuggest, searchInput, toggleButton) { searchSuggest.attachEvent("onShow", () => { const filters = appliedFiltersModel.getFiltersArray(); const suggestData = suggestList.serialize(); - const selectedItems = []; - filters.forEach((f) => { - const found = suggestData.find((item) => { - if (f.id === item.optionId) { - return true; - } - return false; - }); - if (found) { - // for treeCheckbox we use f.key|f.id, for other cases we use f.id - const id = f.view === "treeCheckbox" ? `${f.key}|${f.id}` : f.id; - selectedItems.push(id); + + const selectedTreeIds = filters + .filter(filter => filter.view === "treeCheckbox") + .map(filter => `${filter.key}|${filter.optionId}`); + + const suggestIdsToSelect = filters.flatMap((filter) => { + const suggestItemToSelect = suggestData.find(item => item.optionId === filter.id); + if (!suggestItemToSelect) return []; + const isTreeCheckbox = filter.view === "treeCheckbox"; + if (!isTreeCheckbox) { + return [suggestItemToSelect.id]; } + const suggestTreeItemsToSelect = + [suggestItemToSelect, ...getAffectedSuggestTreeItems(suggestItemToSelect, selectedTreeIds)]; + return suggestTreeItemsToSelect.map(item => item.id); }); + suggestList.blockEvent(); - suggestList.select(selectedItems); + suggestList.select(suggestIdsToSelect); suggestList.unblockEvent(); + foundCountTemplate.parse({count: suggestList.count()}); foundCountPopup.define("width", searchSuggest.config.width); foundCountPopup.resize(); diff --git a/sources/services/gallery/suggest.js b/sources/services/gallery/suggest.js index 0950f48d..e228706a 100644 --- a/sources/services/gallery/suggest.js +++ b/sources/services/gallery/suggest.js @@ -66,6 +66,7 @@ function formSuggestionsFromOptions(parent) { value, level: o.level, optionId: o.id, + hasHiddenOption: o.hasHiddenOption, }); if (o.data) { suggestions.push(...formSuggestionsFromData(o)); @@ -91,12 +92,19 @@ function formSuggestionsFromOptions(parent) { function formSuggestionsFromData(parent) { const suggestions = []; parent.data?.forEach((d) => { - const valueArray = d.id.split("|").map((v, index) => (index < 2 ? v.toUpperCase() : v)); + const valueArray = d.id.split("|").map((v, index) => { + if (index < 2) { + return v.toUpperCase(); + } + return v; + }); suggestions.push({ id: `diagnosis|${d.id}`, key: "diagnosis", optionId: d.id, value: valueArray.join("|") ?? "", + level: d.level, + hasHiddenOption: d.hasHiddenOption, }); if (d.data) { suggestions.push(...formSuggestionsFromData(d)); diff --git a/sources/services/zoomImages.js b/sources/services/zoomImages.js new file mode 100644 index 00000000..8360484a --- /dev/null +++ b/sources/services/zoomImages.js @@ -0,0 +1,197 @@ +import Map from "ol/Map"; +import View from "ol/View"; +import ImageLayer from "ol/layer/Image"; +import TileLayer from "ol/layer/WebGLTile"; +import GeoTIFF from "ol/source/GeoTIFF"; +import ImageStatic from "ol/source/ImageStatic"; + +import galleryImagesUrls from "app-models/galleryImagesUrls"; + +import util from "../utils/util"; + +const MOBILE_PORTRAIT_SIZE = "90vw"; +const MOBILE_LANDSCAPE_SIZE = "90vh"; +const DESKTOP_SIZE = "100%"; + +/** + * @typedef {import("ol/View").default} OlView + * @typedef {import("ol/Map").default} OlMap + */ + +/** + * @typedef {Object} ZoomableImageProperties + * @property {OlView} view + * @property {OlMap} map + * @property {Array} defaultExtent + */ + +/** + * Creates and initializes an OpenLayers View with zoom functionality for the given HTML element + * Works with jpg/png/tif formats + * @param {HTMLElement} htmlElement with isic_id attribute + * @returns {Promise} + */ +export async function createZoomableImage(htmlElement) { + const imageUrl = galleryImagesUrls.getNormalImageUrl(htmlElement?.getAttribute("isic_id")); + if (!htmlElement || !imageUrl) return null; + + const imageUrlLowerCase = imageUrl.toLowerCase(); + const isTifImage = imageUrlLowerCase.endsWith(".tif") || imageUrlLowerCase.endsWith(".tiff"); + + let extent; + let layer; + if (isTifImage) { + const source = new GeoTIFF({sources: [{url: imageUrl}]}); + const sourceView = await source.getView(); + extent = sourceView.extent; + layer = new TileLayer({source}); + } + else { + const loadImage = url => new Promise((resolve, reject) => { + const img = new Image(); + img.src = url; + img.onload = () => resolve(img); + img.onerror = reject; + }); + + const img = await loadImage(imageUrl); + extent = [0, 0, img.width, img.height]; + + const source = new ImageStatic({ + url: imageUrl, + imageExtent: extent, + }); + layer = new ImageLayer({source}); + } + + const imageView = new View({extent}); + const imageMap = new Map({ + target: htmlElement, + layers: [layer], + view: imageView, + controls: [], + }); + + const zoomableImageProperties = { + view: imageView, + map: imageMap, + defaultExtent: extent, + }; + + setImageViewExtent(zoomableImageProperties, htmlElement, extent); + attachResizeObserver(htmlElement, zoomableImageProperties); + + return zoomableImageProperties; +} + +/** + * Resizes image element and restores image view extent when parent element resizes + * @param {HTMLElement} htmlElement + * @param {ZoomableImageProperties} properties + * @returns {void} + */ +function attachResizeObserver(htmlElement, properties) { + let previousExtent = properties.defaultExtent; + properties.view.on("change", () => { + previousExtent = properties.view.calculateExtent(properties.map.getSize()); + }); + + const resizeObserver = new ResizeObserver(() => { + setImageViewExtent(properties, htmlElement, previousExtent); + }); + resizeObserver.observe(htmlElement.parentElement); +} + +/** + * @param {ZoomableImageProperties} properties + * @param {HTMLElement} htmlElement + * @param {Array} extent + * @returns {void} + */ +function setImageViewExtent(properties, htmlElement, extent) { + const [minX, minY, maxX, maxY] = properties.defaultExtent; + const width = maxX - minX; + const height = maxY - minY; + setImageContainerSize(htmlElement, width, height); + properties.map.updateSize(); + properties.view.fit(extent, {size: properties.map.getSize()}); +} + +/** + * @param {HTMLElement} container + * @param {number} width + * @param {number} height + * @returns {void} + */ +function setImageContainerSize(container, width, height) { + const parent = container.parentElement; + if (!parent) return; + + const parentRect = parent.getBoundingClientRect(); + const imgAspectRatio = height / width; + const parentAspectRatio = parentRect.height / parentRect.width; + + const mobileImageContainerSize = util.isPortrait() ? MOBILE_PORTRAIT_SIZE : MOBILE_LANDSCAPE_SIZE; + const imageContainerSize = util.isMobilePhone() ? mobileImageContainerSize : DESKTOP_SIZE; + + if (parentAspectRatio > imgAspectRatio) { + container.style.width = imageContainerSize; + container.style.height = "auto"; + } + else { + container.style.height = imageContainerSize; + container.style.width = "auto"; + } + container.style.aspectRatio = `${width} / ${height}`; +} + +/** + * @param {ZoomableImageProperties} properties + * @param {boolean} isZoomIn + * @returns {void} + */ +export function zoomImage(properties, isZoomIn) { + const imageView = properties.view; + if (!imageView) return; + + const minZoom = imageView.getMinZoom(); + const maxZoom = imageView.getMaxZoom(); + const zoom = imageView.getZoom() ?? minZoom; + const newZoom = isZoomIn ? Math.min(zoom + 0.5, maxZoom) : Math.max(zoom - 0.5, minZoom); + const newCenter = getAdjustedCenter(properties, newZoom); + + imageView.animate({zoom: newZoom, center: newCenter, duration: 250}); +} + +/** + * @param {ZoomableImageProperties} properties + * @param {number} newZoom + * @returns {Array} + */ +function getAdjustedCenter(properties, newZoom) { + const mapSize = properties.map.getSize(); + const resolution = properties.view.getResolutionForZoom(newZoom); + const visibleWidth = mapSize[0] * resolution; + const visibleHeight = mapSize[1] * resolution; + + const [minX, minY, maxX, maxY] = properties.defaultExtent; + const imageWidth = maxX - minX; + const imageHeight = maxY - minY; + const imageCenterX = (minX + maxX) / 2; + const imageCenterY = (minY + maxY) / 2; + + const minCenterX = minX + visibleWidth / 2; + const maxCenterX = maxX - visibleWidth / 2; + const minCenterY = minY + visibleHeight / 2; + const maxCenterY = maxY - visibleHeight / 2; + + const currentCenter = properties.view.getCenter(); + const newCenterX = imageWidth <= visibleWidth + ? imageCenterX + : Math.min(Math.max(currentCenter[0], minCenterX), maxCenterX); + const newCenterY = imageHeight <= visibleHeight + ? imageCenterY + : Math.min(Math.max(currentCenter[1], minCenterY), maxCenterY); + + return [newCenterX, newCenterY]; +} diff --git a/sources/styles/buttons.less b/sources/styles/buttons.less index 5113c6b0..ae6154ef 100644 --- a/sources/styles/buttons.less +++ b/sources/styles/buttons.less @@ -145,6 +145,11 @@ .webix_label_right { padding-left: 7.5px; } + + .webix_el_group { + display: flex; + align-items: center; + } } .cmn-toggle-box{ display: inline-block; diff --git a/sources/styles/common.less b/sources/styles/common.less index 56134d37..079c6a49 100644 --- a/sources/styles/common.less +++ b/sources/styles/common.less @@ -263,7 +263,7 @@ a, .link { font-weight: 600; text-align: center; position: absolute; - left: 50%; + left: calc(50% - 10px); } } } @@ -271,34 +271,23 @@ a, .link { /* gallery-images-badge */ .gallery-images-badge { background-color: #3C87CB; - font-size: 8px; - line-height: 10px; - text-align: center; color: #FFFFFF; - border: 1px; - border-radius: 10px; - height: 13px; - width: 13px; + display: flex; + justify-content: center; + align-items: center; + width: 60%; + height: 60%; + top: -30%; + border-radius: 50%; padding: 2px; text-align: center; + font-size: 50cqw; position: absolute; - right: -5px; - top: -5px; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; } -.gallery-images-badge_1 { - top: -5px; - right: -5px; -} - -.gallery-images-badge_2 { - top: -5px; - right: 13px; -} - .disabled-badge { background-color: #cccccc; } diff --git a/sources/styles/pages.less b/sources/styles/pages.less index 444431cc..f607903a 100644 --- a/sources/styles/pages.less +++ b/sources/styles/pages.less @@ -1124,7 +1124,7 @@ border-color: @lines-color; } -.collapssible-filter, .collapssible-filter-tree { +.collapsible-filter, .collapsible-filter-tree { padding-left: 19px; position: relative; text-transform: uppercase; @@ -1145,7 +1145,7 @@ .transition(all .2s ease-in-out); } - &.showed-filter { + &.shown-filter { &:before { .transform(rotate(90deg)); } @@ -1157,7 +1157,7 @@ } } -.collapssible-filter-tree { +.collapsible-filter-tree { padding-left: 0px; border-width: 0px !important; padding-left: 19px; @@ -1258,6 +1258,7 @@ position: absolute; top: 0; left: 0; + right: 0; z-index: 10; width: 100%; height: 100%; @@ -1402,86 +1403,90 @@ /* mobile-gallery-images-info */ .mobile-gallery-images-info { - font-size: 20px; display: flex; justify-content: space-between; - padding: 5px 30px; - border-width: 0px; + align-items: center; + padding: 0px 30px; + + .thumbnails-name { + font-size: 20px; + line-height: 30px; + } } /* gallery-images-container */ .gallery-images-header { - padding-bottom: 5px; - background: rgba(255,255,255,.60); + container-type: size; + background: rgba(255, 255, 255, 0.6); + display: flex; + justify-content: space-around; + align-items: center; + height: ~"min(35%, 28px)"; + width: 100%; .thumbnails-name { - color: rgba(0,0,0,0.8); - font-size: 14px; + color: rgba(0, 0, 0, 0.8); + font-size: ~"min(8cqw, 28px)"; font-weight: 500; - line-height: 20px; - margin-right: 35px; - padding: 5px 0 0 15px; text-align: left; } + .gallery-images-checkbox { - float: right; - padding-right: 12px; + height: 80%; + aspect-ratio: 1 / 1; + margin: 0; } } -.gallery-images-checkbox { - overflow: hidden; - .checkbox-ctrl { - .webix_el_group { - padding-bottom: 2px; - .box-sizing(border-box); - } - } +.gallery-images-buttons { + display: flex; + flex-wrap: nowrap; + justify-content: center; } -.gallery-images-buttons { - text-align: center; +.gallery-images-info .gallery-images-buttons { + column-gap: ~"min(5%, 8px)"; position: absolute; left: 0; - bottom: 0px; + bottom: ~"min(5%, 10px)"; width: 100%; + height: ~"min(30%, 22px)"; } -.gallery-images-button-elem, .gallery-images-button-elem-disabled { - display: inline-block; - vertical-align: top; - width: 22px; +.mobile-gallery-images-info .gallery-images-buttons { + column-gap: 16px; height: 22px; - margin: 0 4px; } -.gallery-images-button-elem-disabled { - background-color: #cccccc; - pointer-events: none; + +.gallery-images-button-elem { + container-type: size; + height: 100%; + aspect-ratio: 1 / 1; } -.gallery-images-button-elem-disabled:active { - background-color: #cccccc; + +.gallery-images-button-elem.disabled { pointer-events: none; } .gallery-images-button { - display: block; - line-height: 0; + height: 100%; + aspect-ratio: 1 / 1; + display: flex; + align-items: center; + justify-content: center; .box-sizing(border-box); - padding: 1px; border: 1px solid @lines-color; .border-radius(2px); background-color: #FFFFFF; - text-align: center; .transition(all .2s ease-in-out); .gallery-icon-svg { - display: inline-block; - vertical-align: middle; + width: 85%; + height: 85%; } - .gallery-icon-svg, .gallery-icon-use { - width: 18px; - height: 18px; + width: 100%; + height: 100%; } .gallery-icon-use { @@ -1497,10 +1502,6 @@ } } -.gallery-images-footer { - -} - .mobile-gallery-header-logo { cursor: pointer; } @@ -1511,12 +1512,6 @@ font-weight: bold; } -.gallery-header-mobile-context { - .webix_template { - position: relative; - } -} - .webix_view.webix_control.webix_el_button.filtered .webix_img_btn .fas.fa-filter{ color: @select-color; } @@ -2198,7 +2193,6 @@ padding: 0; cursor: pointer; border-radius: 50%; - margin: 10px; //box-shadow: 0 2px #999; &.btn-plus { left: 100px; diff --git a/sources/styles/popups.less b/sources/styles/popups.less index 8f2129a2..fb602db5 100644 --- a/sources/styles/popups.less +++ b/sources/styles/popups.less @@ -201,11 +201,6 @@ justify-content: center; user-select: none; height: 100%; - .zoomable-image { - max-height:100%; - max-width:100%; - object-fit: contain; - } } .prev, .next { @@ -335,6 +330,11 @@ .container { position: relative; .vertical-slider-left, .vertical-slider-right { + .webix_scroll_cont { + display: flex; + align-items: center; + flex-direction: column; + } position: absolute; border: none; z-index: 10; @@ -403,7 +403,7 @@ } .vertical-slider-right { - left: 10px; + left: 18px; } .multi-image-lesion-window__image-label { @@ -411,6 +411,7 @@ font-weight: 500; font-size: 14px; line-height: 16px; + text-align: center; } .footer-template { @@ -460,6 +461,7 @@ .webix_inp_static { border: none; padding-left: 0px; + padding-top: 2px; } .webix_input_icon.wxi-menu-down, .webix_input_icon.wxi-menu-down:focus { outline: none; diff --git a/sources/utils/util.js b/sources/utils/util.js index fb1b31ab..0111baf5 100644 --- a/sources/utils/util.js +++ b/sources/utils/util.js @@ -250,83 +250,49 @@ function getFilterLabelId(filterId) { return `filter-label-${filterId || ""}` } -function getImageIconDimensions() { - const initialIconWidth = constants.DEFAULT_GALLERY_IMAGE_ICON_WIDTH; - const initialIconHeight = constants.DEFAULT_GALLERY_IMAGE_ICON_HEIGHT; - const initialIconContainerWidth = constants.DEFAULT_GALLERY_IMAGE_ICON_CONTAINER_WIDTH; - const initialIconContainerHeight = constants.DEFAULT_GALLERY_IMAGE_ICON_CONTAINER_HEIGHT; - const defaultIconWidthDifference = initialIconContainerWidth - initialIconWidth; - const deafultIconHeightDifference = initialIconContainerHeight - initialIconHeight; - - let bottomOffsetPercentage; - let newIconWidth; - let newIconHeight; - let newIconContainerWidth; - let newIconContainerHeight; - let iconContainerDimensions; - let iconDimensions; - let dataviewItemWidth = getDataviewItemWidth(); - - if (dataviewItemWidth <= 110) { - if (dataviewItemWidth > 100) { - newIconContainerWidth = initialIconWidth - 1; - newIconContainerHeight = initialIconHeight - 1; - newIconWidth = newIconContainerWidth - defaultIconWidthDifference; - newIconHeight = newIconContainerHeight - deafultIconHeightDifference; - bottomOffsetPercentage = -8; - } - else if (dataviewItemWidth <= 100 && dataviewItemWidth > 95) { - newIconContainerWidth = initialIconWidth - 2; - newIconContainerHeight = initialIconHeight - 2; - newIconWidth = newIconContainerWidth - defaultIconWidthDifference; - newIconHeight = newIconContainerHeight - deafultIconHeightDifference; - bottomOffsetPercentage = -10; - } - else if (dataviewItemWidth <= 95) { - newIconContainerWidth = initialIconWidth - 3; - newIconContainerHeight = initialIconHeight - 3; - newIconWidth = newIconContainerWidth - defaultIconWidthDifference; - newIconHeight = newIconContainerHeight - deafultIconHeightDifference; - bottomOffsetPercentage = -12; - } - iconContainerDimensions = { - width: newIconContainerWidth, - height: newIconContainerHeight - }; - - iconDimensions = { - width: newIconWidth, - height: newIconHeight - }; - } - else { - iconContainerDimensions = { - width: initialIconContainerWidth, - height: initialIconContainerHeight - }; - - iconDimensions = { - width: initialIconWidth, - height: initialIconHeight - }; - bottomOffsetPercentage = 0; - } - return [iconContainerDimensions, iconDimensions, bottomOffsetPercentage]; -} +/** + * @param {string} iconId + * @param {boolean} isIconEnabled + * @param {string} tooltipText + * @param {string} gtmClass + * @param {string} iconBadges + * @returns {string} + */ +function getIconButton(iconId, isIconEnabled, tooltipText, gtmClass, iconBadges) { + const buttonClass = `gallery-images-button-elem ${isIconEnabled ? '' : 'disabled'} tooltip-container tooltip-gallery-images`; + return ` +
+ + + + + + ${tooltipText} + ${iconBadges} +
+ `; +}; -function setNewThumnailsNameFontSize(nameFontSize) { - if (nameFontSize > 28) { - nameFontSize = 28; - } - else if (nameFontSize < 7.5) { - nameFontSize = 7.5; - } - webix.storage.local.put(`thumbnailsNameFontSize-${getUserId()}`, nameFontSize); -} +/** + * @param {string} badgeText + * @param {string} tooltipText + * @param {boolean} isEnabledBadge + * @param {boolean} isLeftBadge + * @returns {string} + */ +function getIconBadge(badgeText, tooltipText, isEnabledBadge, isLeftBadge) { + const badgeAbilityClass = isEnabledBadge ? "" : "disabled-badge"; + + const iconBadgeStyle = ` + ${isLeftBadge ? `transform: translateX(-50%); left: 0;` : `transform: translateX(50%); right: 0;`} + `; -function getNewThumnailsNameFontSize() { - let fontSize = webix.storage.local.get(`thumbnailsNameFontSize-${getUserId()}`); - return fontSize || 14; + return ` + + ${badgeText} + + ${tooltipText} + `; } function separateThousandsInNumber(number) { @@ -570,9 +536,8 @@ export default { getDataviewItemHeight, setDataviewSelectionId, getDataviewSelectionId, - getImageIconDimensions, - setNewThumnailsNameFontSize, - getNewThumnailsNameFontSize, + getIconButton, + getIconBadge, separateThousandsInNumber, isObjectEmpty, angleIconChange, diff --git a/sources/views/components/collapser.js b/sources/views/components/collapser.js index 19e6b740..2610303a 100644 --- a/sources/views/components/collapser.js +++ b/sources/views/components/collapser.js @@ -68,7 +68,8 @@ function getConfig(collapsedViewId, config) { webix.ui.resize(); if (collapsedViewId === constants.ID_GALLERY_RIGHT_PANEL) { util.setHiddenGalleryCartList(isOpen); - } else if (collapsedViewId === constants.ID_GALLERY_LEFT_PANEL) { + } + else if (collapsedViewId === constants.ID_GALLERY_LEFT_PANEL) { util.setHiddenGalleryLeftPanel(isOpen); } changeDataviewItemDimensions(collapsedView); diff --git a/sources/views/components/slideButton.js b/sources/views/components/slideButton.js index 855b3d3b..32d96d0d 100644 --- a/sources/views/components/slideButton.js +++ b/sources/views/components/slideButton.js @@ -23,9 +23,9 @@ webix.protoUI({ const checked = config.checkValue === config.value; - const className = `webix_inp_checkbox_border webix_el_group webix_checkbox_${(checked ? "1" : "0")}`; + const className = `webix_inp_checkbox_border webix_el_group webix_checkbox_${checked ? "1" : "0"}`; const ch = `
- +
`; diff --git a/sources/views/components/types/sideBarType.js b/sources/views/components/types/sideBarType.js index 658a258f..2b9e38b8 100644 --- a/sources/views/components/types/sideBarType.js +++ b/sources/views/components/types/sideBarType.js @@ -5,7 +5,7 @@ webix.type(webix.ui.tree, { let html = ""; for (let i = 1; i <= obj.$level; i++) { if (i === obj.$level && obj.$count) { - let icon = `fas fa-caret-${(obj.open ? "down" : "right")}`; + let icon = `fas fa-caret-${obj.open ? "down" : "right"}`; html += ``; } } diff --git a/sources/views/header/mobileHeader.js b/sources/views/header/mobileHeader.js index abd2ad05..48828798 100644 --- a/sources/views/header/mobileHeader.js +++ b/sources/views/header/mobileHeader.js @@ -9,16 +9,9 @@ import uploadWindow from "./windows/uploadTypeWindow"; const ID_LOGOUT_PANEL = `logout-panel-id-${webix.uid()}`; const ID_LOGIN_MENU = `login-menu-id-${webix.uid()}`; const ID_LOGIN_PANEL = `login-panel-id-${webix.uid()}`; -const ID_MENU_PANEL = `menu-panel-id-${webix.uid()}`; export default class MobileHeader extends JetView { config() { - const menuPanel = { - view: "sidebar", - id: ID_MENU_PANEL, - data: [] - }; - const logo = { template: "ISIC", css: "mobile-header-logo", diff --git a/sources/views/mobileTop.js b/sources/views/mobileTop.js index 0ec04942..6ce35be6 100644 --- a/sources/views/mobileTop.js +++ b/sources/views/mobileTop.js @@ -1,7 +1,5 @@ import {JetView} from "webix-jet"; -import MobileHeader from "./header/mobileHeader"; - export default class MobileTopView extends JetView { config() { const ui = { diff --git a/sources/views/subviews/createDataset/createDataset.js b/sources/views/subviews/createDataset/createDataset.js index ffc86307..9c76f2f1 100644 --- a/sources/views/subviews/createDataset/createDataset.js +++ b/sources/views/subviews/createDataset/createDataset.js @@ -1,4 +1,5 @@ import {JetView} from "webix-jet"; + import authService from "../../../services/auth"; import licensesWindow from "./windows/licenseInfo"; diff --git a/sources/views/subviews/createStudy/windows/imagesSelectionWindow.js b/sources/views/subviews/createStudy/windows/imagesSelectionWindow.js index 8998279a..9bb57ada 100644 --- a/sources/views/subviews/createStudy/windows/imagesSelectionWindow.js +++ b/sources/views/subviews/createStudy/windows/imagesSelectionWindow.js @@ -89,7 +89,7 @@ export default class ImagesSelectionWindow extends JetView {