diff --git a/e2e/features/layers/layer-picker-test.spec.js b/e2e/features/layers/layer-picker-test.spec.js index 393ff29ada..ce26c7b033 100644 --- a/e2e/features/layers/layer-picker-test.spec.js +++ b/e2e/features/layers/layer-picker-test.spec.js @@ -112,7 +112,7 @@ test('Closing and reopening layer picker restores state.', async () => { layerDetails, layerDetailsDateRange } = selectors - await page.locator('.product-outter-list-case .search-row:nth-child(1)').click() + await page.locator('.product-outer-list-case .search-row:nth-child(1)').click() await expect(layerDetailHeader).toContainText('Corrected Reflectance') await layersModalCloseButton.click() await expect(layersAll).not.toBeVisible() diff --git a/e2e/features/layers/recent-layers-mobile-test.spec.js b/e2e/features/layers/recent-layers-mobile-test.spec.js index b7d7caa349..fc897b9c93 100644 --- a/e2e/features/layers/recent-layers-mobile-test.spec.js +++ b/e2e/features/layers/recent-layers-mobile-test.spec.js @@ -52,7 +52,7 @@ test('Recent tab shows layers that were selected', async () => { test('Clear list button empties the entire list', async () => { await page.locator('#clear-recent-layers').click() - const productList = await page.locator('.product-outter-list-case.layers-all') + const productList = await page.locator('.product-outer-list-case.layers-all') const noResults = await page.locator('.no-results') await expect(productList).not.toBeVisible() await expect(noResults).toBeVisible() diff --git a/e2e/features/layers/recent-layers-test.spec.js b/e2e/features/layers/recent-layers-test.spec.js index 5f5f189bfa..2f89803b09 100644 --- a/e2e/features/layers/recent-layers-test.spec.js +++ b/e2e/features/layers/recent-layers-test.spec.js @@ -58,7 +58,7 @@ test('Removing individual layers updates the list', async () => { test('Clear list button empties the entire list', async () => { await page.locator('#clear-recent-layers').click() - const productList = await page.locator('.product-outter-list-case.layers-all') + const productList = await page.locator('.product-outer-list-case.layers-all') const noResults = await page.locator('.no-results') await expect(productList).not.toBeVisible() await expect(noResults).toBeVisible() diff --git a/package-lock.json b/package-lock.json index 1a6fca9708..bd7e1df029 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "worldview", - "version": "4.6.0", + "version": "4.7.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "worldview", - "version": "4.6.0", + "version": "4.7.0", "hasInstallScript": true, "license": "NASA-1.3", "dependencies": { @@ -19,7 +19,7 @@ "@khanisak/temperature-converter": "^2.0.1", "@redux-devtools/extension": "^3.2.5", "bluebird": "3.7.2", - "bootstrap": "5.2.3", + "bootstrap": "^5.3.0", "cachai": "^1.0.2", "compression": "^1.7.4", "coordinate-parser": "^1.0.7", @@ -39,8 +39,8 @@ "moment": "^2.29.4", "moment-locales-webpack-plugin": "^1.2.0", "node-dir": "^0.1.17", - "ol": "7.3.0", - "ol-mapbox-style": "^10.4.0", + "ol": "^7.4.0", + "ol-mapbox-style": "^10.6.0", "p-queue": "^7.3.4", "proj4": "2.9.0", "prop-types": "^15.8.1", @@ -53,7 +53,7 @@ "react-infinite-scroller": "^1.2.6", "react-joyride": "^2.5.4", "react-mobile-datepicker": "^4.0.2", - "react-redux": "^8.0.5", + "react-redux": "^8.0.7", "react-resizable": "^3.0.5", "react-swipe-to-delete-component": "1.0.5", "react-visibility-sensor": "^5.1.1", @@ -73,11 +73,11 @@ "what-input": "^5.2.12" }, "devDependencies": { - "@babel/core": "^7.21.8", + "@babel/core": "^7.22.1", "@babel/eslint-parser": "^7.21.8", "@babel/plugin-proposal-class-properties": "^7.18.6", "@babel/preset-env": "^7.21.5", - "@babel/preset-react": "^7.18.6", + "@babel/preset-react": "^7.22.3", "@playwright/test": "^1.34.3", "@pmmmwh/react-refresh-webpack-plugin": "^0.5.10", "@webpack-cli/serve": "^2.0.4", @@ -88,7 +88,7 @@ "cheerio": "^1.0.0-rc.12", "clean-webpack-plugin": "^4.0.0", "cross-env": "^7.0.3", - "css-loader": "^6.7.3", + "css-loader": "^6.8.1", "css-minimizer-webpack-plugin": "^5.0.0", "css-url-relative-plugin": "^1.1.0", "cssnano": "^6.0.1", @@ -118,7 +118,7 @@ "node-ssh": "^13.1.0", "npm-run-all": "^4.1.5", "patch-package": "^7.0.0", - "postcss": "^8.4.23", + "postcss": "^8.4.24", "postcss-loader": "^7.3.1", "react-refresh": "^0.14.0", "react-test-renderer": "^17.0.2", @@ -133,8 +133,8 @@ "stylelint-high-performance-animation": "^1.8.0", "tar": "^6.1.15", "terser-webpack-plugin": "^5.3.9", - "webpack": "^5.84.1", - "webpack-bundle-analyzer": "^4.8.0", + "webpack": "^5.85.0", + "webpack-bundle-analyzer": "^4.9.0", "webpack-cli": "^5.1.1", "webpack-dev-middleware": "^6.1.1", "webpack-dev-server": "^4.15.0", @@ -169,7 +169,7 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.21.7", + "version": "7.22.3", "dev": true, "license": "MIT", "engines": { @@ -177,20 +177,20 @@ } }, "node_modules/@babel/core": { - "version": "7.21.8", + "version": "7.22.1", "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.21.4", - "@babel/generator": "^7.21.5", - "@babel/helper-compilation-targets": "^7.21.5", - "@babel/helper-module-transforms": "^7.21.5", - "@babel/helpers": "^7.21.5", - "@babel/parser": "^7.21.8", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.5", - "@babel/types": "^7.21.5", + "@babel/generator": "^7.22.0", + "@babel/helper-compilation-targets": "^7.22.1", + "@babel/helper-module-transforms": "^7.22.1", + "@babel/helpers": "^7.22.0", + "@babel/parser": "^7.22.0", + "@babel/template": "^7.21.9", + "@babel/traverse": "^7.22.1", + "@babel/types": "^7.22.0", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -223,11 +223,11 @@ } }, "node_modules/@babel/generator": { - "version": "7.21.5", + "version": "7.22.3", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.21.5", + "@babel/types": "^7.22.3", "@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" @@ -273,11 +273,11 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.21.5", + "version": "7.22.1", "dev": true, "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.21.5", + "@babel/compat-data": "^7.22.0", "@babel/helper-validator-option": "^7.21.0", "browserslist": "^4.21.3", "lru-cache": "^5.1.1", @@ -356,7 +356,7 @@ } }, "node_modules/@babel/helper-environment-visitor": { - "version": "7.21.5", + "version": "7.22.1", "dev": true, "license": "MIT", "engines": { @@ -419,18 +419,18 @@ } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.21.5", + "version": "7.22.1", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-environment-visitor": "^7.21.5", + "@babel/helper-environment-visitor": "^7.22.1", "@babel/helper-module-imports": "^7.21.4", "@babel/helper-simple-access": "^7.21.5", "@babel/helper-split-export-declaration": "^7.18.6", "@babel/helper-validator-identifier": "^7.19.1", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.5", - "@babel/types": "^7.21.5" + "@babel/template": "^7.21.9", + "@babel/traverse": "^7.22.1", + "@babel/types": "^7.22.0" }, "engines": { "node": ">=6.9.0" @@ -558,13 +558,13 @@ } }, "node_modules/@babel/helpers": { - "version": "7.21.5", + "version": "7.22.3", "dev": true, "license": "MIT", "dependencies": { - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.5", - "@babel/types": "^7.21.5" + "@babel/template": "^7.21.9", + "@babel/traverse": "^7.22.1", + "@babel/types": "^7.22.3" }, "engines": { "node": ">=6.9.0" @@ -583,7 +583,7 @@ } }, "node_modules/@babel/parser": { - "version": "7.21.8", + "version": "7.22.4", "dev": true, "license": "MIT", "bin": { @@ -963,11 +963,11 @@ } }, "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.18.6", + "version": "7.21.4", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" + "@babel/helper-plugin-utils": "^7.20.2" }, "engines": { "node": ">=6.9.0" @@ -1445,15 +1445,15 @@ } }, "node_modules/@babel/plugin-transform-react-jsx": { - "version": "7.20.13", + "version": "7.22.3", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/plugin-syntax-jsx": "^7.18.6", - "@babel/types": "^7.20.7" + "@babel/helper-module-imports": "^7.21.4", + "@babel/helper-plugin-utils": "^7.21.5", + "@babel/plugin-syntax-jsx": "^7.21.4", + "@babel/types": "^7.22.3" }, "engines": { "node": ">=6.9.0" @@ -1725,14 +1725,14 @@ } }, "node_modules/@babel/preset-react": { - "version": "7.18.6", + "version": "7.22.3", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/helper-validator-option": "^7.18.6", + "@babel/helper-plugin-utils": "^7.21.5", + "@babel/helper-validator-option": "^7.21.0", "@babel/plugin-transform-react-display-name": "^7.18.6", - "@babel/plugin-transform-react-jsx": "^7.18.6", + "@babel/plugin-transform-react-jsx": "^7.22.3", "@babel/plugin-transform-react-jsx-development": "^7.18.6", "@babel/plugin-transform-react-pure-annotations": "^7.18.6" }, @@ -1759,31 +1759,31 @@ } }, "node_modules/@babel/template": { - "version": "7.20.7", + "version": "7.21.9", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.18.6", - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7" + "@babel/code-frame": "^7.21.4", + "@babel/parser": "^7.21.9", + "@babel/types": "^7.21.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.21.5", + "version": "7.22.4", "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.21.4", - "@babel/generator": "^7.21.5", - "@babel/helper-environment-visitor": "^7.21.5", + "@babel/generator": "^7.22.3", + "@babel/helper-environment-visitor": "^7.22.1", "@babel/helper-function-name": "^7.21.0", "@babel/helper-hoist-variables": "^7.18.6", "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.21.5", - "@babel/types": "^7.21.5", + "@babel/parser": "^7.22.4", + "@babel/types": "^7.22.4", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -1792,7 +1792,7 @@ } }, "node_modules/@babel/types": { - "version": "7.21.5", + "version": "7.22.4", "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.21.5", @@ -2139,8 +2139,7 @@ }, "node_modules/@eslint/js": { "version": "8.41.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.41.0.tgz", - "integrity": "sha512-LxcyMGxwmTh2lY9FwHPGWOHmYFCZvbrFCBZL4FzSSsxsRPuhrYUg/49/0KDfW8tnIEaEHtfmn6+NPN+1DqaNmA==", + "license": "MIT", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } @@ -3199,8 +3198,6 @@ }, "node_modules/@playwright/test": { "version": "1.34.3", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.34.3.tgz", - "integrity": "sha512-zPLef6w9P6T/iT6XDYG3mvGOqOyb6eHaV9XtkunYs0+OzxBtrPAAaHotc0X+PJ00WPPnLfFBTl7mf45Mn8DBmw==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -4071,8 +4068,7 @@ }, "node_modules/acorn-import-assertions": { "version": "1.9.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", - "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", + "license": "MIT", "peerDependencies": { "acorn": "^8" } @@ -4840,7 +4836,7 @@ "license": "ISC" }, "node_modules/bootstrap": { - "version": "5.2.3", + "version": "5.3.0", "funding": [ { "type": "github", @@ -4853,7 +4849,7 @@ ], "license": "MIT", "peerDependencies": { - "@popperjs/core": "^2.11.6" + "@popperjs/core": "^2.11.7" } }, "node_modules/brace-expansion": { @@ -5647,14 +5643,14 @@ } }, "node_modules/css-loader": { - "version": "6.7.3", + "version": "6.8.1", "dev": true, "license": "MIT", "dependencies": { "icss-utils": "^5.1.0", - "postcss": "^8.4.19", + "postcss": "^8.4.21", "postcss-modules-extract-imports": "^3.0.0", - "postcss-modules-local-by-default": "^4.0.0", + "postcss-modules-local-by-default": "^4.0.3", "postcss-modules-scope": "^3.0.0", "postcss-modules-values": "^4.0.0", "postcss-value-parser": "^4.2.0", @@ -6654,8 +6650,7 @@ }, "node_modules/eslint": { "version": "8.41.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.41.0.tgz", - "integrity": "sha512-WQDQpzGBOP5IrXPo4Hc0814r4/v2rrIsB0rhT7jtunIalgg6gYXWhRMOejVO8yH21T/FGaxjmFjBMNqcIlmH1Q==", + "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.4.0", @@ -7940,10 +7935,8 @@ }, "node_modules/fsevents": { "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "dev": true, - "hasInstallScript": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -8079,9 +8072,8 @@ }, "node_modules/glob": { "version": "10.2.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.2.6.tgz", - "integrity": "sha512-U/rnDpXJGF414QQQZv5uVsabTVxMSwzS5CH0p3DRCIV6ownl4f7PzGnkGmvlum2wB+9RlJWJZ6ACU1INnBqiPA==", "dev": true, + "license": "ISC", "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^2.0.3", @@ -8116,18 +8108,16 @@ }, "node_modules/glob/node_modules/brace-expansion": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } }, "node_modules/glob/node_modules/minimatch": { "version": "9.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.1.tgz", - "integrity": "sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -8244,8 +8234,7 @@ }, "node_modules/graphemer": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==" + "license": "MIT" }, "node_modules/gzip-size": { "version": "6.0.0", @@ -9261,9 +9250,8 @@ }, "node_modules/jest-canvas-mock": { "version": "2.5.1", - "resolved": "https://registry.npmjs.org/jest-canvas-mock/-/jest-canvas-mock-2.5.1.tgz", - "integrity": "sha512-IVnRiz+v4EYn3ydM/pBo8GW/J+nU/Hg5gHBQQOUQhdRyNfvHnabB8ReqARLO0p+kvQghqr4V0tA92CF3JcUSRg==", "dev": true, + "license": "MIT", "dependencies": { "cssfontparser": "^1.2.1", "moo-color": "^1.0.2" @@ -10921,9 +10909,8 @@ }, "node_modules/jiti": { "version": "1.18.2", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.18.2.tgz", - "integrity": "sha512-QAdOptna2NYiSSpv0O/BwoHBSmz4YhpzJHyi+fnMRTXFjp7B8i/YG5Z8IfusxB1ufjcD2Sre1F3R+nX3fvy7gg==", "dev": true, + "license": "MIT", "bin": { "jiti": "bin/jiti.js" } @@ -11485,9 +11472,8 @@ }, "node_modules/mini-css-extract-plugin": { "version": "2.7.6", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.7.6.tgz", - "integrity": "sha512-Qk7HcgaPkGG6eD77mLvZS1nmxlao3j+9PkrT9Uc7HAE1id3F41+DdBRYRYkbyfNRGzm8/YWtzhw7nVPmwhqTQw==", "dev": true, + "license": "MIT", "dependencies": { "schema-utils": "^4.0.0" }, @@ -12038,12 +12024,12 @@ "license": "MIT" }, "node_modules/ol": { - "version": "7.3.0", + "version": "7.4.0", "license": "BSD-2-Clause", "dependencies": { "earcut": "^2.2.3", "geotiff": "^2.0.7", - "ol-mapbox-style": "^9.2.0", + "ol-mapbox-style": "^10.1.0", "pbf": "3.2.1", "rbush": "^3.0.1" }, @@ -12053,19 +12039,12 @@ } }, "node_modules/ol-mapbox-style": { - "version": "10.5.0", + "version": "10.6.0", "license": "BSD-2-Clause", "dependencies": { "@mapbox/mapbox-gl-style-spec": "^13.23.1", - "mapbox-to-css-font": "^2.4.1" - } - }, - "node_modules/ol/node_modules/ol-mapbox-style": { - "version": "9.7.0", - "license": "BSD-2-Clause", - "dependencies": { - "@mapbox/mapbox-gl-style-spec": "^13.23.1", - "mapbox-to-css-font": "^2.4.1" + "mapbox-to-css-font": "^2.4.1", + "ol": "^7.3.0" } }, "node_modules/on-finished": { @@ -12686,8 +12665,6 @@ }, "node_modules/playwright-core": { "version": "1.34.3", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.34.3.tgz", - "integrity": "sha512-2pWd6G7OHKemc5x1r1rp8aQcpvDh7goMBZlJv6Co5vCNLVcQJdhxRL09SGaY6HcyHH9aT4tiynZabMofVasBYw==", "dev": true, "license": "Apache-2.0", "bin": { @@ -12706,7 +12683,7 @@ } }, "node_modules/postcss": { - "version": "8.4.23", + "version": "8.4.24", "dev": true, "funding": [ { @@ -12825,9 +12802,8 @@ }, "node_modules/postcss-loader": { "version": "7.3.2", - "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-7.3.2.tgz", - "integrity": "sha512-c7qDlXErX6n0VT+LUsW+nwefVtTu3ORtVvK8EXuUIDcxo+b/euYqpuHlJAvePb0Af5e8uMjR/13e0lTuYifaig==", "dev": true, + "license": "MIT", "dependencies": { "cosmiconfig": "^8.1.3", "jiti": "^1.18.2", @@ -13003,7 +12979,7 @@ } }, "node_modules/postcss-modules-local-by-default": { - "version": "4.0.0", + "version": "4.0.3", "dev": true, "license": "MIT", "dependencies": { @@ -13650,8 +13626,7 @@ }, "node_modules/react-image-crop": { "version": "10.1.4", - "resolved": "https://registry.npmjs.org/react-image-crop/-/react-image-crop-10.1.4.tgz", - "integrity": "sha512-bEc/SfJRPU06ApivtzuNmofEH3rqf1WsKgWNwloiZ4ttCB37DEETwR4KsQb+KkW87srvRtWpCbOhPs0a4TVAKw==", + "license": "ISC", "dependencies": { "clsx": "^1.2.1" }, @@ -13722,7 +13697,7 @@ "license": "MIT" }, "node_modules/react-redux": { - "version": "8.0.5", + "version": "8.0.7", "license": "MIT", "dependencies": { "@babel/runtime": "^7.12.1", @@ -13733,14 +13708,18 @@ "use-sync-external-store": "^1.0.0" }, "peerDependencies": { + "@reduxjs/toolkit": "^1 || ^2.0.0-beta.0", "@types/react": "^16.8 || ^17.0 || ^18.0", "@types/react-dom": "^16.8 || ^17.0 || ^18.0", "react": "^16.8 || ^17.0 || ^18.0", "react-dom": "^16.8 || ^17.0 || ^18.0", "react-native": ">=0.59", - "redux": "^4" + "redux": "^4 || ^5.0.0-beta.0" }, "peerDependenciesMeta": { + "@reduxjs/toolkit": { + "optional": true + }, "@types/react": { "optional": true }, @@ -13880,8 +13859,7 @@ }, "node_modules/reactstrap": { "version": "9.1.10", - "resolved": "https://registry.npmjs.org/reactstrap/-/reactstrap-9.1.10.tgz", - "integrity": "sha512-VMDiQNV8hKug1GFOHEymYUYxDnueYl44F+wREABuYy2RgvzDq7OL7T/T8OpUz6JAA+f9LeeHohXxFbpb+a/VmA==", + "license": "MIT", "dependencies": { "@babel/runtime": "^7.12.5", "@popperjs/core": "^2.6.0", @@ -14472,9 +14450,8 @@ }, "node_modules/sass-loader": { "version": "13.3.1", - "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-13.3.1.tgz", - "integrity": "sha512-cBTxmgyVA1nXPvIK4brjJMXOMJ2v2YrQEuHqLw3LylGb3gsR6jAvdjHMcy/+JGTmmIF9SauTrLLR7bsWDMWqgg==", "dev": true, + "license": "MIT", "dependencies": { "klona": "^2.0.6", "neo-async": "^2.6.2" @@ -15384,8 +15361,6 @@ }, "node_modules/stylelint": { "version": "15.6.2", - "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-15.6.2.tgz", - "integrity": "sha512-fjQWwcdUye4DU+0oIxNGwawIPC5DvG5kdObY5Sg4rc87untze3gC/5g/ikePqVjrAsBUZjwMN+pZsAYbDO6ArQ==", "dev": true, "license": "MIT", "dependencies": { @@ -15713,9 +15688,8 @@ }, "node_modules/tar": { "version": "6.1.15", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.15.tgz", - "integrity": "sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==", "dev": true, + "license": "ISC", "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", @@ -15754,8 +15728,7 @@ }, "node_modules/terser-webpack-plugin": { "version": "5.3.9", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz", - "integrity": "sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==", + "license": "MIT", "dependencies": { "@jridgewell/trace-mapping": "^0.3.17", "jest-worker": "^27.4.5", @@ -16406,9 +16379,8 @@ } }, "node_modules/webpack": { - "version": "5.84.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.84.1.tgz", - "integrity": "sha512-ZP4qaZ7vVn/K8WN/p990SGATmrL1qg4heP/MrVneczYtpDGJWlrgZv55vxaV2ul885Kz+25MP2kSXkPe3LZfmg==", + "version": "5.85.0", + "license": "MIT", "dependencies": { "@types/eslint-scope": "^3.7.3", "@types/estree": "^1.0.0", @@ -16452,7 +16424,7 @@ } }, "node_modules/webpack-bundle-analyzer": { - "version": "4.8.0", + "version": "4.9.0", "dev": true, "license": "MIT", "dependencies": { @@ -16540,8 +16512,6 @@ }, "node_modules/webpack-cli": { "version": "5.1.1", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-5.1.1.tgz", - "integrity": "sha512-OLJwVMoXnXYH2ncNGU8gxVpUtm3ybvdioiTvHgUyBuyMLKiVvWy+QObzBsMtp5pH7qQoEuWgeEUQ/sU3ZJFzAw==", "dev": true, "license": "MIT", "dependencies": { @@ -16613,9 +16583,8 @@ }, "node_modules/webpack-dev-middleware": { "version": "6.1.1", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-6.1.1.tgz", - "integrity": "sha512-y51HrHaFeeWir0YO4f0g+9GwZawuigzcAdRNon6jErXy/SqV/+O6eaVAzDqE6t3e3NpGeR5CS+cCDaTC+V3yEQ==", "dev": true, + "license": "MIT", "dependencies": { "colorette": "^2.0.10", "memfs": "^3.4.12", @@ -16820,8 +16789,7 @@ }, "node_modules/webpack/node_modules/enhanced-resolve": { "version": "5.14.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.14.1.tgz", - "integrity": "sha512-Vklwq2vDKtl0y/vtwjSesgJ5MYS7Etuk5txS8VdKL4AOS1aUlD96zqIfsOSLQsdv3xgMRbtkWM8eG9XDfKUPow==", + "license": "MIT", "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" @@ -16832,8 +16800,7 @@ }, "node_modules/webpack/node_modules/tapable": { "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "license": "MIT", "engines": { "node": ">=6" } @@ -17139,8 +17106,6 @@ }, "node_modules/xml2js": { "version": "0.6.0", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.0.tgz", - "integrity": "sha512-eLTh0kA8uHceqesPqSE+VvO1CDDJWMwlQfB6LuN6T8w6MaDJ8Txm8P7s5cHD0miF0V+GGTZrDQfxPZQVsur33w==", "dev": true, "license": "MIT", "dependencies": { @@ -17246,23 +17211,23 @@ } }, "@babel/compat-data": { - "version": "7.21.7", + "version": "7.22.3", "dev": true }, "@babel/core": { - "version": "7.21.8", + "version": "7.22.1", "dev": true, "requires": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.21.4", - "@babel/generator": "^7.21.5", - "@babel/helper-compilation-targets": "^7.21.5", - "@babel/helper-module-transforms": "^7.21.5", - "@babel/helpers": "^7.21.5", - "@babel/parser": "^7.21.8", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.5", - "@babel/types": "^7.21.5", + "@babel/generator": "^7.22.0", + "@babel/helper-compilation-targets": "^7.22.1", + "@babel/helper-module-transforms": "^7.22.1", + "@babel/helpers": "^7.22.0", + "@babel/parser": "^7.22.0", + "@babel/template": "^7.21.9", + "@babel/traverse": "^7.22.1", + "@babel/types": "^7.22.0", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -17280,10 +17245,10 @@ } }, "@babel/generator": { - "version": "7.21.5", + "version": "7.22.3", "dev": true, "requires": { - "@babel/types": "^7.21.5", + "@babel/types": "^7.22.3", "@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" @@ -17316,10 +17281,10 @@ } }, "@babel/helper-compilation-targets": { - "version": "7.21.5", + "version": "7.22.1", "dev": true, "requires": { - "@babel/compat-data": "^7.21.5", + "@babel/compat-data": "^7.22.0", "@babel/helper-validator-option": "^7.21.0", "browserslist": "^4.21.3", "lru-cache": "^5.1.1", @@ -17374,7 +17339,7 @@ } }, "@babel/helper-environment-visitor": { - "version": "7.21.5", + "version": "7.22.1", "dev": true }, "@babel/helper-explode-assignable-expression": { @@ -17413,17 +17378,17 @@ } }, "@babel/helper-module-transforms": { - "version": "7.21.5", + "version": "7.22.1", "dev": true, "requires": { - "@babel/helper-environment-visitor": "^7.21.5", + "@babel/helper-environment-visitor": "^7.22.1", "@babel/helper-module-imports": "^7.21.4", "@babel/helper-simple-access": "^7.21.5", "@babel/helper-split-export-declaration": "^7.18.6", "@babel/helper-validator-identifier": "^7.19.1", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.5", - "@babel/types": "^7.21.5" + "@babel/template": "^7.21.9", + "@babel/traverse": "^7.22.1", + "@babel/types": "^7.22.0" } }, "@babel/helper-optimise-call-expression": { @@ -17501,12 +17466,12 @@ } }, "@babel/helpers": { - "version": "7.21.5", + "version": "7.22.3", "dev": true, "requires": { - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.5", - "@babel/types": "^7.21.5" + "@babel/template": "^7.21.9", + "@babel/traverse": "^7.22.1", + "@babel/types": "^7.22.3" } }, "@babel/highlight": { @@ -17518,7 +17483,7 @@ } }, "@babel/parser": { - "version": "7.21.8", + "version": "7.22.4", "dev": true }, "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { @@ -17730,10 +17695,10 @@ } }, "@babel/plugin-syntax-jsx": { - "version": "7.18.6", + "version": "7.21.4", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.18.6" + "@babel/helper-plugin-utils": "^7.20.2" } }, "@babel/plugin-syntax-logical-assignment-operators": { @@ -17992,14 +17957,14 @@ } }, "@babel/plugin-transform-react-jsx": { - "version": "7.20.13", + "version": "7.22.3", "dev": true, "requires": { "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/plugin-syntax-jsx": "^7.18.6", - "@babel/types": "^7.20.7" + "@babel/helper-module-imports": "^7.21.4", + "@babel/helper-plugin-utils": "^7.21.5", + "@babel/plugin-syntax-jsx": "^7.21.4", + "@babel/types": "^7.22.3" } }, "@babel/plugin-transform-react-jsx-development": { @@ -18177,13 +18142,13 @@ } }, "@babel/preset-react": { - "version": "7.18.6", + "version": "7.22.3", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/helper-validator-option": "^7.18.6", + "@babel/helper-plugin-utils": "^7.21.5", + "@babel/helper-validator-option": "^7.21.0", "@babel/plugin-transform-react-display-name": "^7.18.6", - "@babel/plugin-transform-react-jsx": "^7.18.6", + "@babel/plugin-transform-react-jsx": "^7.22.3", "@babel/plugin-transform-react-jsx-development": "^7.18.6", "@babel/plugin-transform-react-pure-annotations": "^7.18.6" } @@ -18199,32 +18164,32 @@ } }, "@babel/template": { - "version": "7.20.7", + "version": "7.21.9", "dev": true, "requires": { - "@babel/code-frame": "^7.18.6", - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7" + "@babel/code-frame": "^7.21.4", + "@babel/parser": "^7.21.9", + "@babel/types": "^7.21.5" } }, "@babel/traverse": { - "version": "7.21.5", + "version": "7.22.4", "dev": true, "requires": { "@babel/code-frame": "^7.21.4", - "@babel/generator": "^7.21.5", - "@babel/helper-environment-visitor": "^7.21.5", + "@babel/generator": "^7.22.3", + "@babel/helper-environment-visitor": "^7.22.1", "@babel/helper-function-name": "^7.21.0", "@babel/helper-hoist-variables": "^7.18.6", "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.21.5", - "@babel/types": "^7.21.5", + "@babel/parser": "^7.22.4", + "@babel/types": "^7.22.4", "debug": "^4.1.0", "globals": "^11.1.0" } }, "@babel/types": { - "version": "7.21.5", + "version": "7.22.4", "requires": { "@babel/helper-string-parser": "^7.21.5", "@babel/helper-validator-identifier": "^7.19.1", @@ -18445,9 +18410,7 @@ } }, "@eslint/js": { - "version": "8.41.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.41.0.tgz", - "integrity": "sha512-LxcyMGxwmTh2lY9FwHPGWOHmYFCZvbrFCBZL4FzSSsxsRPuhrYUg/49/0KDfW8tnIEaEHtfmn6+NPN+1DqaNmA==" + "version": "8.41.0" }, "@floating-ui/core": { "version": "1.2.6" @@ -19133,8 +19096,6 @@ }, "@playwright/test": { "version": "1.34.3", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.34.3.tgz", - "integrity": "sha512-zPLef6w9P6T/iT6XDYG3mvGOqOyb6eHaV9XtkunYs0+OzxBtrPAAaHotc0X+PJ00WPPnLfFBTl7mf45Mn8DBmw==", "dev": true, "requires": { "@types/node": "*", @@ -19756,8 +19717,6 @@ }, "acorn-import-assertions": { "version": "1.9.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", - "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", "requires": {} }, "acorn-jsx": { @@ -20272,7 +20231,7 @@ "dev": true }, "bootstrap": { - "version": "5.2.3", + "version": "5.3.0", "requires": {} }, "brace-expansion": { @@ -20768,13 +20727,13 @@ "dev": true }, "css-loader": { - "version": "6.7.3", + "version": "6.8.1", "dev": true, "requires": { "icss-utils": "^5.1.0", - "postcss": "^8.4.19", + "postcss": "^8.4.21", "postcss-modules-extract-imports": "^3.0.0", - "postcss-modules-local-by-default": "^4.0.0", + "postcss-modules-local-by-default": "^4.0.3", "postcss-modules-scope": "^3.0.0", "postcss-modules-values": "^4.0.0", "postcss-value-parser": "^4.2.0", @@ -21414,8 +21373,6 @@ }, "eslint": { "version": "8.41.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.41.0.tgz", - "integrity": "sha512-WQDQpzGBOP5IrXPo4Hc0814r4/v2rrIsB0rhT7jtunIalgg6gYXWhRMOejVO8yH21T/FGaxjmFjBMNqcIlmH1Q==", "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.4.0", @@ -22195,8 +22152,6 @@ }, "fsevents": { "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "dev": true, "optional": true }, @@ -22277,8 +22232,6 @@ }, "glob": { "version": "10.2.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.2.6.tgz", - "integrity": "sha512-U/rnDpXJGF414QQQZv5uVsabTVxMSwzS5CH0p3DRCIV6ownl4f7PzGnkGmvlum2wB+9RlJWJZ6ACU1INnBqiPA==", "dev": true, "requires": { "foreground-child": "^3.1.0", @@ -22290,8 +22243,6 @@ "dependencies": { "brace-expansion": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, "requires": { "balanced-match": "^1.0.0" @@ -22299,8 +22250,6 @@ }, "minimatch": { "version": "9.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.1.tgz", - "integrity": "sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==", "dev": true, "requires": { "brace-expansion": "^2.0.1" @@ -22385,9 +22334,7 @@ "version": "4.2.10" }, "graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==" + "version": "1.4.0" }, "gzip-size": { "version": "6.0.0", @@ -22963,8 +22910,6 @@ }, "jest-canvas-mock": { "version": "2.5.1", - "resolved": "https://registry.npmjs.org/jest-canvas-mock/-/jest-canvas-mock-2.5.1.tgz", - "integrity": "sha512-IVnRiz+v4EYn3ydM/pBo8GW/J+nU/Hg5gHBQQOUQhdRyNfvHnabB8ReqARLO0p+kvQghqr4V0tA92CF3JcUSRg==", "dev": true, "requires": { "cssfontparser": "^1.2.1", @@ -24034,8 +23979,6 @@ }, "jiti": { "version": "1.18.2", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.18.2.tgz", - "integrity": "sha512-QAdOptna2NYiSSpv0O/BwoHBSmz4YhpzJHyi+fnMRTXFjp7B8i/YG5Z8IfusxB1ufjcD2Sre1F3R+nX3fvy7gg==", "dev": true }, "js-tokens": { @@ -24395,8 +24338,6 @@ }, "mini-css-extract-plugin": { "version": "2.7.6", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.7.6.tgz", - "integrity": "sha512-Qk7HcgaPkGG6eD77mLvZS1nmxlao3j+9PkrT9Uc7HAE1id3F41+DdBRYRYkbyfNRGzm8/YWtzhw7nVPmwhqTQw==", "dev": true, "requires": { "schema-utils": "^4.0.0" @@ -24734,29 +24675,21 @@ "dev": true }, "ol": { - "version": "7.3.0", + "version": "7.4.0", "requires": { "earcut": "^2.2.3", "geotiff": "^2.0.7", - "ol-mapbox-style": "^9.2.0", + "ol-mapbox-style": "^10.1.0", "pbf": "3.2.1", "rbush": "^3.0.1" - }, - "dependencies": { - "ol-mapbox-style": { - "version": "9.7.0", - "requires": { - "@mapbox/mapbox-gl-style-spec": "^13.23.1", - "mapbox-to-css-font": "^2.4.1" - } - } } }, "ol-mapbox-style": { - "version": "10.5.0", + "version": "10.6.0", "requires": { "@mapbox/mapbox-gl-style-spec": "^13.23.1", - "mapbox-to-css-font": "^2.4.1" + "mapbox-to-css-font": "^2.4.1", + "ol": "^7.3.0" } }, "on-finished": { @@ -25127,15 +25060,13 @@ }, "playwright-core": { "version": "1.34.3", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.34.3.tgz", - "integrity": "sha512-2pWd6G7OHKemc5x1r1rp8aQcpvDh7goMBZlJv6Co5vCNLVcQJdhxRL09SGaY6HcyHH9aT4tiynZabMofVasBYw==", "dev": true }, "popper.js": { "version": "1.16.1" }, "postcss": { - "version": "8.4.23", + "version": "8.4.24", "dev": true, "requires": { "nanoid": "^3.3.6", @@ -25191,8 +25122,6 @@ }, "postcss-loader": { "version": "7.3.2", - "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-7.3.2.tgz", - "integrity": "sha512-c7qDlXErX6n0VT+LUsW+nwefVtTu3ORtVvK8EXuUIDcxo+b/euYqpuHlJAvePb0Af5e8uMjR/13e0lTuYifaig==", "dev": true, "requires": { "cosmiconfig": "^8.1.3", @@ -25290,7 +25219,7 @@ "requires": {} }, "postcss-modules-local-by-default": { - "version": "4.0.0", + "version": "4.0.3", "dev": true, "requires": { "icss-utils": "^5.0.0", @@ -25659,8 +25588,6 @@ }, "react-image-crop": { "version": "10.1.4", - "resolved": "https://registry.npmjs.org/react-image-crop/-/react-image-crop-10.1.4.tgz", - "integrity": "sha512-bEc/SfJRPU06ApivtzuNmofEH3rqf1WsKgWNwloiZ4ttCB37DEETwR4KsQb+KkW87srvRtWpCbOhPs0a4TVAKw==", "requires": { "clsx": "^1.2.1" } @@ -25706,7 +25633,7 @@ "version": "1.0.4" }, "react-redux": { - "version": "8.0.5", + "version": "8.0.7", "requires": { "@babel/runtime": "^7.12.1", "@types/hoist-non-react-statics": "^3.3.1", @@ -25801,8 +25728,6 @@ }, "reactstrap": { "version": "9.1.10", - "resolved": "https://registry.npmjs.org/reactstrap/-/reactstrap-9.1.10.tgz", - "integrity": "sha512-VMDiQNV8hKug1GFOHEymYUYxDnueYl44F+wREABuYy2RgvzDq7OL7T/T8OpUz6JAA+f9LeeHohXxFbpb+a/VmA==", "requires": { "@babel/runtime": "^7.12.5", "@popperjs/core": "^2.6.0", @@ -26189,8 +26114,6 @@ }, "sass-loader": { "version": "13.3.1", - "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-13.3.1.tgz", - "integrity": "sha512-cBTxmgyVA1nXPvIK4brjJMXOMJ2v2YrQEuHqLw3LylGb3gsR6jAvdjHMcy/+JGTmmIF9SauTrLLR7bsWDMWqgg==", "dev": true, "requires": { "klona": "^2.0.6", @@ -26801,8 +26724,6 @@ }, "stylelint": { "version": "15.6.2", - "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-15.6.2.tgz", - "integrity": "sha512-fjQWwcdUye4DU+0oIxNGwawIPC5DvG5kdObY5Sg4rc87untze3gC/5g/ikePqVjrAsBUZjwMN+pZsAYbDO6ArQ==", "dev": true, "requires": { "@csstools/css-parser-algorithms": "^2.1.1", @@ -27013,8 +26934,6 @@ }, "tar": { "version": "6.1.15", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.15.tgz", - "integrity": "sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==", "dev": true, "requires": { "chownr": "^2.0.0", @@ -27047,8 +26966,6 @@ }, "terser-webpack-plugin": { "version": "5.3.9", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz", - "integrity": "sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==", "requires": { "@jridgewell/trace-mapping": "^0.3.17", "jest-worker": "^27.4.5", @@ -27432,9 +27349,7 @@ "dev": true }, "webpack": { - "version": "5.84.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.84.1.tgz", - "integrity": "sha512-ZP4qaZ7vVn/K8WN/p990SGATmrL1qg4heP/MrVneczYtpDGJWlrgZv55vxaV2ul885Kz+25MP2kSXkPe3LZfmg==", + "version": "5.85.0", "requires": { "@types/eslint-scope": "^3.7.3", "@types/estree": "^1.0.0", @@ -27464,22 +27379,18 @@ "dependencies": { "enhanced-resolve": { "version": "5.14.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.14.1.tgz", - "integrity": "sha512-Vklwq2vDKtl0y/vtwjSesgJ5MYS7Etuk5txS8VdKL4AOS1aUlD96zqIfsOSLQsdv3xgMRbtkWM8eG9XDfKUPow==", "requires": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" } }, "tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==" + "version": "2.2.1" } } }, "webpack-bundle-analyzer": { - "version": "4.8.0", + "version": "4.9.0", "dev": true, "requires": { "@discoveryjs/json-ext": "0.5.7", @@ -27535,8 +27446,6 @@ }, "webpack-cli": { "version": "5.1.1", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-5.1.1.tgz", - "integrity": "sha512-OLJwVMoXnXYH2ncNGU8gxVpUtm3ybvdioiTvHgUyBuyMLKiVvWy+QObzBsMtp5pH7qQoEuWgeEUQ/sU3ZJFzAw==", "dev": true, "requires": { "@discoveryjs/json-ext": "^0.5.0", @@ -27573,8 +27482,6 @@ }, "webpack-dev-middleware": { "version": "6.1.1", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-6.1.1.tgz", - "integrity": "sha512-y51HrHaFeeWir0YO4f0g+9GwZawuigzcAdRNon6jErXy/SqV/+O6eaVAzDqE6t3e3NpGeR5CS+cCDaTC+V3yEQ==", "dev": true, "requires": { "colorette": "^2.0.10", @@ -27874,8 +27781,6 @@ }, "xml2js": { "version": "0.6.0", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.0.tgz", - "integrity": "sha512-eLTh0kA8uHceqesPqSE+VvO1CDDJWMwlQfB6LuN6T8w6MaDJ8Txm8P7s5cHD0miF0V+GGTZrDQfxPZQVsur33w==", "dev": true, "requires": { "sax": ">=0.6.0", diff --git a/package.json b/package.json index 9aebd5c035..2d5443dd49 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "worldview", - "version": "4.6.0", + "version": "4.7.0", "description": "Interactive interface for browsing full-resolution, global satellite imagery", "keywords": [ "NASA", @@ -75,11 +75,11 @@ "upload": "node tasks/util/upload.js" }, "devDependencies": { - "@babel/core": "^7.21.8", + "@babel/core": "^7.22.1", "@babel/eslint-parser": "^7.21.8", "@babel/plugin-proposal-class-properties": "^7.18.6", "@babel/preset-env": "^7.21.5", - "@babel/preset-react": "^7.18.6", + "@babel/preset-react": "^7.22.3", "@playwright/test": "^1.34.3", "@pmmmwh/react-refresh-webpack-plugin": "^0.5.10", "@webpack-cli/serve": "^2.0.4", @@ -90,7 +90,7 @@ "cheerio": "^1.0.0-rc.12", "clean-webpack-plugin": "^4.0.0", "cross-env": "^7.0.3", - "css-loader": "^6.7.3", + "css-loader": "^6.8.1", "css-minimizer-webpack-plugin": "^5.0.0", "css-url-relative-plugin": "^1.1.0", "cssnano": "^6.0.1", @@ -120,7 +120,7 @@ "node-ssh": "^13.1.0", "npm-run-all": "^4.1.5", "patch-package": "^7.0.0", - "postcss": "^8.4.23", + "postcss": "^8.4.24", "postcss-loader": "^7.3.1", "react-refresh": "^0.14.0", "react-test-renderer": "^17.0.2", @@ -135,8 +135,8 @@ "stylelint-high-performance-animation": "^1.8.0", "tar": "^6.1.15", "terser-webpack-plugin": "^5.3.9", - "webpack": "^5.84.1", - "webpack-bundle-analyzer": "^4.8.0", + "webpack": "^5.85.0", + "webpack-bundle-analyzer": "^4.9.0", "webpack-cli": "^5.1.1", "webpack-dev-middleware": "^6.1.1", "webpack-dev-server": "^4.15.0", @@ -154,7 +154,7 @@ "@khanisak/temperature-converter": "^2.0.1", "@redux-devtools/extension": "^3.2.5", "bluebird": "3.7.2", - "bootstrap": "5.2.3", + "bootstrap": "^5.3.0", "cachai": "^1.0.2", "compression": "^1.7.4", "coordinate-parser": "^1.0.7", @@ -174,8 +174,8 @@ "moment": "^2.29.4", "moment-locales-webpack-plugin": "^1.2.0", "node-dir": "^0.1.17", - "ol": "7.3.0", - "ol-mapbox-style": "^10.4.0", + "ol": "^7.4.0", + "ol-mapbox-style": "^10.6.0", "p-queue": "^7.3.4", "proj4": "2.9.0", "prop-types": "^15.8.1", @@ -188,7 +188,7 @@ "react-infinite-scroller": "^1.2.6", "react-joyride": "^2.5.4", "react-mobile-datepicker": "^4.0.2", - "react-redux": "^8.0.5", + "react-redux": "^8.0.7", "react-resizable": "^3.0.5", "react-swipe-to-delete-component": "1.0.5", "react-visibility-sensor": "^5.1.1", diff --git a/web/index.html b/web/index.html index 11e3c3fbb0..aeff834470 100644 --- a/web/index.html +++ b/web/index.html @@ -20,7 +20,7 @@ }); var f = d.getElementsByTagName(s)[0], j = d.createElement(s), dl = l != 'dataLayer' ? '&l=' + l : ''; j.async = true; j.src = 'https://www.googletagmanager.com/gtm.js?id=' + i + dl; f.parentNode.insertBefore(j, f); - })(window,document,'script','dataLayer','GTM-TCCQ7MW'); + })(window,document,'script','dataLayer','GTM-WNP7MLF'); window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} diff --git a/web/js/components/kiosk/animation-tile-check/animation-tile-check.js b/web/js/components/kiosk/animation-tile-check/animation-tile-check.js index 7a4938cbdb..6448e91a40 100644 --- a/web/js/components/kiosk/animation-tile-check/animation-tile-check.js +++ b/web/js/components/kiosk/animation-tile-check/animation-tile-check.js @@ -14,28 +14,34 @@ function AnimationTileCheck(props) { isPlaying, } = props; - const { activeString } = useSelector((state) => ({ - activeString: state.compare.activeString, + const { + config, proj, zoom, activeLayers, + } = useSelector((state) => ({ + config: state.config, + proj: state.proj.selected, + zoom: Math.floor(state.map.ui.selected.getView().getZoom()), + activeLayers: getActiveLayers(state, state.compare.activeString).map((layer) => layer), })); - const activeLayers = useSelector((state) => getActiveLayers(state, activeString).map((layer) => layer)); const [frameDates, setFrameDates] = useState([]); + // This component is only renered when kioskMode is active & eic is subdaily or daily animation + // This means we can listen to the animation play trigger once the tileError check has completed useEffect(() => { if (isPlaying) getFrameDates(); }, [isPlaying]); - // get an array of each frame date for duration of animation + // Get an array of each frame date for duration of animation function determineFrameDates() { const getNextDate = (date) => util.dateAdd(date, interval, delta); const frameDatesArray = []; let frameDate = startDate; - // this puts an extra '.000Z' on the end of the date string - frameDatesArray.push(frameDate.toISOString()); + + frameDatesArray.push(frameDate); while (frameDate < endDate) { frameDate = getNextDate(frameDate); - frameDatesArray.push(frameDate.toISOString()); + frameDatesArray.push(frameDate); } return frameDatesArray; } @@ -46,7 +52,7 @@ function AnimationTileCheck(props) { } return ( - + ); } diff --git a/web/js/components/kiosk/animation-tile-check/date-range-tile-check.js b/web/js/components/kiosk/animation-tile-check/date-range-tile-check.js index f82f4287ef..3e297f89fb 100644 --- a/web/js/components/kiosk/animation-tile-check/date-range-tile-check.js +++ b/web/js/components/kiosk/animation-tile-check/date-range-tile-check.js @@ -1,92 +1,255 @@ -// import React, { useEffect, useState } from 'react'; -// import { useSelector, useDispatch } from 'react-redux'; -// import OlTileGridWMTS from 'ol/tilegrid/WMTS'; -// import OlSourceWMTS from 'ol/source/WMTS'; -// import OlLayerTile from 'ol/layer/Tile'; -// import TileState from 'ol/TileState'; -// import OlTileGridTileGrid from 'ol/tilegrid/TileGrid'; -// import PropTypes from 'prop-types'; +/* eslint-disable quote-props */ +import { useEffect } from 'react'; +import OlTileGridWMTS from 'ol/tilegrid/WMTS'; +import OlSourceWMTS from 'ol/source/WMTS'; +import PropTypes from 'prop-types'; +import { useDispatch } from 'react-redux'; +import { toggleCheckedAnimationAvailability as toggleCheckedAnimationAvailabilityAction } from '../../../modules/ui/actions'; +import util from '../../../util/util'; +import { + LEFT_WING_EXTENT, RIGHT_WING_EXTENT, LEFT_WING_ORIGIN, RIGHT_WING_ORIGIN, +} from '../../../modules/map/constants'; + +// Layers to be checked for tile availability need to have manually determined content-length thresholds. +// Any active layers that are not listed in this object will NOT be checked for tile availability. +// This represents a TOTAL content-length for all tiles for a single date for a single layer +// To find a good value for the total content-length: +// 1. Find a visibly verifiabled date range where the layer has full tiles for the entire range +// 2. Add the layer id to the contentLengthThresholds object below with a value of 1 +// 3. Place a console statement in getAvailability() for console.log(resolvedLayersAvailability) +// 4. Create a permalink with the kiosk parameter with kiosk=true && (eic='sa' || eic='da') +// 5. Use the permalink & open the console +// 6. Look through the conentLengthSum values for each layer/date to find a good value +// Currently can only be used for WMTS tiles. +const contentLengthThresholds = { + 'GOES-East_ABI_GeoColor': 160000, + 'GOES-West_ABI_GeoColor': 160000, + 'AMSRU2_Sea_Ice_Concentration_12km': 10000, +}; function DateRangeTileCheck(props) { - // const { - // frameDates, - // activeLayers, - // } = props; - - // useEffect(() => { - // if (frameDates.length){ - // // console.log('frameDates', frameDates, 'activeLayers', activeLayers) - // parentFunction(activeLayers) - // } - - // }, [frameDates]) - - // function checkTileAvailability(url) { - // return new Promise((resolve, reject) => { - // const img = new Image(); - // img.onload = () => { - // resolve(true); - // }; - // img.onerror = () => { - // resolve(false); - // }; - // img.src = url; - // }); - // } - - // const wmtsUrlFunction = (layer, date) => async function(tile, src) { - - // } - - // // #3 child function that accepts an array of frame dates and a layer and returns availability for the range - // async function checkTilesForDates(dates, layer) { - // const availability = { - // availableTiles: [], - // unavailableTiles: [], - // }; - - // for (const date of dates) { - // const tileUrl = wmtsUrlFunction(layer, date); // Replace with your tile URL generation logic - // const isAvailable = await checkTileAvailability(tileUrl); - - // if (isAvailable) { - // availability.availableTiles.push(date); - // } else { - // availability.unavailableTiles.push(date); - // } - // } - // return availability; - // } - - // // #2 child function that accepts one layer and returns results for that layer - // async function getAvailabilityForLayer(layer) { - // console.log(layer) - - // const availability = await checkTilesForDates(frameDates, layer); - - // const id = layer.id - - // const layerAvailability = { - // [id]: availability, - // }; - - - // return layerAvailability - // } - - // // parent function that accepts activeLayers and returns final results - // function parentFunction(activeLayers) { - - // const allLayersAvailability = activeLayers.map((layer) => { - // const layerAvailability = getAvailabilityForLayer(layer) - // return layerAvailability; - // }) - - // console.log(allLayersAvailability) - // } - + const { + frameDates, + activeLayers, + config, + proj, + zoom, + } = props; + + const dispatch = useDispatch(); + const toggleCheckedAnimationAvailability = (available) => { dispatch(toggleCheckedAnimationAvailabilityAction(available)); }; + + useEffect(() => { + if (frameDates.length) { + getAvailability(); + } + }, [frameDates]); + + const calcExtentsFromLimits = (matrixSet, matrixSetLimits, day) => { + let extent; + let origin; + + switch (day) { + case 1: + extent = LEFT_WING_EXTENT; + origin = LEFT_WING_ORIGIN; + break; + case -1: + extent = RIGHT_WING_EXTENT; + origin = RIGHT_WING_ORIGIN; + break; + default: + extent = proj.maxExtent; + origin = [extent[0], extent[3]]; + break; + } + + const resolutionLen = matrixSet.resolutions.length; + const setlimitsLen = matrixSetLimits && matrixSetLimits.length; + + if (!matrixSetLimits || setlimitsLen !== resolutionLen || day) { + return { origin, extent }; + } + + const limitIndex = resolutionLen - 1; + const resolution = matrixSet.resolutions[limitIndex]; + const tileWidth = matrixSet.tileSize[0] * resolution; + const tileHeight = matrixSet.tileSize[1] * resolution; + const { + minTileCol, + maxTileRow, + maxTileCol, + minTileRow, + } = matrixSetLimits[limitIndex]; + const minX = extent[0] + (minTileCol * tileWidth); + const minY = extent[3] - ((maxTileRow + 1) * tileHeight); + const maxX = extent[0] + ((maxTileCol + 1) * tileWidth); + const maxY = extent[3] - (minTileRow * tileHeight); + + return { + origin, + extent: [minX, minY, maxX, maxY], + }; + }; + + const requestTilesWMTS = async (def, date) => { + const { + id, format, matrixIds, matrixSetLimits, projections, style, type, + } = def; + + let contentLengthSum = 0; + + const isGranule = type === 'granule'; + const projectionsAttributes = projections[proj.id]; + const projSource = projectionsAttributes.source; + const configSource = config.sources[projSource]; + const urlParameters = `?TIME=${util.toISOStringSeconds(util.roundTimeOneMinute(date))}`; + const sourceURL = def.sourceOverride || configSource.url; + const configMatrixSet = configSource.matrixSets[projectionsAttributes.matrixSet]; + + const { tileMatrices, resolutions, tileSize } = configMatrixSet; + const { origin, extent } = calcExtentsFromLimits(configMatrixSet, matrixSetLimits, null); + const sizes = !tileMatrices ? [] : tileMatrices.map(({ matrixWidth, matrixHeight }) => [matrixWidth, matrixHeight]); + + const tileGridOptions = { + origin, + extent, + sizes, + resolutions, + matrixIds: matrixIds || resolutions.map((set, index) => index), + tileSize: tileSize[0], + }; + + const tileLoadFunction = function(tile, src) { + return new Promise((resolve) => { + fetch(src) + .then((response) => response.blob().then((data) => [response, data])) + .then(([response, data]) => { + const contentLength = response.headers.get('content-length'); + if (response.status === 200 && data !== undefined) { + contentLengthSum += parseInt(contentLength, 10); + } + resolve(); + }) + .catch((e) => { + console.error('Error loading tile', e); + resolve(); + }); + }); + }; + + + const wmtsSource = new OlSourceWMTS({ + url: sourceURL + urlParameters, + layer: id, + cacheSize: 4096, + crossOrigin: 'anonymous', + format, + transition: isGranule ? 350 : 0, + matrixSet: configMatrixSet.id, + tileGrid: new OlTileGridWMTS(tileGridOptions), + wrapX: false, + style: typeof style === 'undefined' ? 'default' : style, + tileLoadFunction, + }); + + const [matrixWidth, matrixHeight] = sizes[zoom]; + + const promises = []; + + for (let x = 0; x < matrixWidth; x += 1) { + for (let y = 0; y < matrixHeight; y += 1) { + const tileCoord = [zoom, x, y]; + const tileUrl = wmtsSource.tileUrlFunction(tileCoord, 1, proj); + if (tileUrl !== undefined) { + const promise = wmtsSource.getTileLoadFunction()(tileCoord, tileUrl); + promises.push(promise); + } + } + } + + await Promise.all(promises); + return { + date, + contentLengthSum, + }; + }; + + // Invoked from getAvailability, accepts one layer and returns results for that layer + // Each layer will have a nested array of each frameDate with a content-length value + async function getAvailabilityForLayer(layer) { + const layerName = layer.id.toString(); + + // Start all the tile requests concurrently + const tilePromises = frameDates.map((date) => requestTilesWMTS(layer, date)); + + // Wait for all the requests to finish and gather the results + const tiles = await Promise.all(tilePromises); + + const availability = { + layerName, + dates: tiles, + }; + + return availability; + } + + // Parent function called when frameDates are calculated + async function getAvailability() { + // An array of layers that are eligible to be checked + const layersToBeChecked = activeLayers.filter((layer) => contentLengthThresholds[layer.id]); + + // Map through each eligible layer and request availability + const layersAvailability = layersToBeChecked.map((layer) => { + const layerAvailability = getAvailabilityForLayer(layer); + return layerAvailability; + }); + + // Wait for all the requests to finish and gather the results with promise + const resolvedLayersAvailability = await Promise.all(layersAvailability); + + // Create a set of unique dates that are below the threshold + // The size of this set will determine how many frames are missing tiles + const uniqueDatesBelowThreshold = new Set(); + + resolvedLayersAvailability.forEach((layer) => { + const threshold = contentLengthThresholds[layer.layerName]; + + layer.dates.forEach((date) => { + if (date.contentLengthSum < threshold) { + const dateStr = date.date.toISOString(); // Convert date to string for use as an object key + uniqueDatesBelowThreshold.add(dateStr); // Add the date to the set. If it's already there, it won't be added again. + } + }); + }); + + const framesWithMissingTiles = uniqueDatesBelowThreshold.size; + + // Calculate how many frames are missing tiles as a percentage + const percentMissing = (framesWithMissingTiles / frameDates.length) * 100; + + // If there are less than 40% of frames with missing tiles we dispatch action to allow animation to play + // Else we do not do anything which means we display static imagery of the first frame + // The imagery at this date should already be satisfactory because the errorTile process has already been completed + // The percentMissing conditional value is completely arbitrary and can be changed + if (percentMissing < 40) { + console.log('Good Check:', percentMissing, '% ', 'of dates with missing frames'); + toggleCheckedAnimationAvailability(true); + } else { + // THIS ELSE BLOCK IS ONLY FOR TESTING + console.log('Bad Check: ', percentMissing, '% ', ' of dates with missing frames. Aborting animation.'); + } + } return null; } +DateRangeTileCheck.propTypes = { + proj: PropTypes.object, + config: PropTypes.object, + activeLayers: PropTypes.array, + frameDates: PropTypes.array, + zoom: PropTypes.number, +}; + export default DateRangeTileCheck; diff --git a/web/js/components/kiosk/util.js b/web/js/components/kiosk/util.js index 76734dcc41..074422298a 100644 --- a/web/js/components/kiosk/util.js +++ b/web/js/components/kiosk/util.js @@ -1,5 +1,5 @@ -/* eslint-disable import/prefer-default-export */ // formats date for kiosk mode and updates to EST +// eslint-disable-next-line import/prefer-default-export export function formatKioskDate(date, subdaily) { const options = { year: 'numeric', @@ -24,3 +24,5 @@ export function formatKioskDate(date, subdaily) { return formattedDate; } + + diff --git a/web/js/components/layer/product-picker/browse/browse-layers.js b/web/js/components/layer/product-picker/browse/browse-layers.js index 22d59be6d0..d41deab9c4 100644 --- a/web/js/components/layer/product-picker/browse/browse-layers.js +++ b/web/js/components/layer/product-picker/browse/browse-layers.js @@ -90,7 +90,7 @@ function BrowseLayers (props) { : (
-
+
@@ -206,7 +206,7 @@ function BrowseLayers (props) { { isCategoryDisplay ? ( -
+
) : renderContent() diff --git a/web/js/components/layer/product-picker/search/search-layers-list.js b/web/js/components/layer/product-picker/search/search-layers-list.js index 0fb0592f9d..8d975bbf97 100644 --- a/web/js/components/layer/product-picker/search/search-layers-list.js +++ b/web/js/components/layer/product-picker/search/search-layers-list.js @@ -152,7 +152,7 @@ class SearchLayerList extends React.Component { useWindow={false} getScrollParent={() => this.scrollParent} > -
+
{visibleItems.map((layer) => (isMobile && recentLayerMode ? ( { - testMode && ( + checkAnimationAvailability ? ( - ) + ) : isPlaying ? ( + + ) : null } - {isPlaying && !testMode && ( - - )} {isCollapsed ? ( - ) : isKioskModeActive && !testMode + ) : isKioskModeActive ? null - : ( { const hasFutureLayers = activeLayersForProj.filter((layer) => layer.futureTime).length > 0; const layerDateRange = getDateRange({}, activeLayersForProj); + const isAntarctic = proj.id === 'arctic'; + const minDate = new Date(config.startDate); let maxDate; if (layerDateRange && layerDateRange.end > appNow) { @@ -388,7 +387,10 @@ const mapStateToProps = (state) => { maxDate = appNow; } - const { isDistractionFreeModeActive, isKioskModeActive } = ui; + const { + isDistractionFreeModeActive, isKioskModeActive, animationAvailabilityChecked, eic, + } = ui; + const checkAnimationAvailability = (eic === 'sa' || eic === 'da') && !animationAvailabilityChecked && isKioskModeActive && isPlaying && !isAntarctic; const { isEmbedModeActive } = embed; const animationIsActive = isActive && lodashGet(map, 'ui.selected.frameState_') @@ -436,6 +438,7 @@ const mapStateToProps = (state) => { appNow, animationCustomModalOpen, autoplay, + checkAnimationAvailability, customSelected, startDate, endDate, @@ -522,6 +525,7 @@ AnimationWidget.propTypes = { animationCustomModalOpen: PropTypes.bool, autoplay: PropTypes.bool, breakpoints: PropTypes.object, + checkAnimationAvailability: PropTypes.bool, snappedCurrentDate: PropTypes.object, currentDate: PropTypes.object, delta: PropTypes.number, diff --git a/web/js/map/layerbuilder.js b/web/js/map/layerbuilder.js index 34e86984ff..c93d0edcf5 100644 --- a/web/js/map/layerbuilder.js +++ b/web/js/map/layerbuilder.js @@ -26,7 +26,6 @@ import { mergeBreakpointLayerAttributes, formatReduxDate, extractDateFromTileErrorURL, - formatSelectedDate, } from './util'; import { datesInDateRanges, prevDateInDateRange } from '../modules/layers/util'; import { updateLayerDateCollection, updateLayerCollection } from '../modules/layers/actions'; @@ -163,14 +162,12 @@ export default function mapLayerBuilder(config, cache, store) { */ const tileLoadFunction = (layer, layerDate) => async function(tile, src) { const state = store.getState(); - const { ui: { isKioskModeActive }, date: { selected } } = state; + const { ui: { isKioskModeActive } } = state; const date = layerDate.toISOString().split('T')[0]; const checkBlobTiles = (headers) => { - // recently changed from appNow date to selected date, was previously only checking current day - const formattedSelectedDate = formatSelectedDate(selected); - if (isKioskModeActive && kioskCheckForBlankTilesList.includes(layer.id) && formattedSelectedDate === date) { + if (isKioskModeActive && kioskCheckForBlankTilesList.includes(layer.id)) { errorTiles.kioskTileCount += 1; const contentLength = headers.get('content-length'); const contentType = headers.get('content-type'); @@ -289,6 +286,11 @@ export default function mapLayerBuilder(config, cache, store) { } } layer.setOpacity(opacity || 1.0); + if (breakPointLayer) { + layer.getLayersArray().forEach((l) => { + l.setOpacity(opacity || 1.0); + }); + } return layer; }; diff --git a/web/js/map/natural-events/util.js b/web/js/map/natural-events/util.js index 6d2d7a5b5b..315ea09c38 100644 --- a/web/js/map/natural-events/util.js +++ b/web/js/map/natural-events/util.js @@ -47,8 +47,13 @@ export const getTrackPoint = function(proj, clusterPoint, isSelected, callback) }; textEl.appendChild(content); textEl.appendChild(magnitudeContent); - textEl.className = 'track-marker-date'; - if (!isSelected) { + if (isSelected) { + textEl.className = 'track-marker-date track-marker-date-selected'; + setTimeout(() => { + textEl.className = 'track-marker-date'; + }, 5000); + } else { + textEl.className = 'track-marker-date'; textEl.style.top = hasMagnitude ? '-40px' : '-28px'; } circleEl.className = `track-marker track-marker-${date}`; diff --git a/web/js/mapUI/components/kiosk/kiosk-animations/kiosk-animations.js b/web/js/mapUI/components/kiosk/kiosk-animations/kiosk-animations.js index 8fcee0aa73..1ff0c10ab0 100644 --- a/web/js/mapUI/components/kiosk/kiosk-animations/kiosk-animations.js +++ b/web/js/mapUI/components/kiosk/kiosk-animations/kiosk-animations.js @@ -81,6 +81,7 @@ function KioskAnimations({ ui }) { return date.toString(); }; + // Invoked after tileError check is complete, this will trigger the animation availability check const handleAnimationSettings = () => { const start = updateStartTime(selectedDate); const end = selectedDate; diff --git a/web/js/mapUI/components/update-opacity/updateOpacity.js b/web/js/mapUI/components/update-opacity/updateOpacity.js index 4803cfafc0..0c7be066fd 100644 --- a/web/js/mapUI/components/update-opacity/updateOpacity.js +++ b/web/js/mapUI/components/update-opacity/updateOpacity.js @@ -69,8 +69,11 @@ function UpdateOpacity(props) { if (def.type === 'granule') { updateGranuleLayerOpacity(def, activeString, opacity, compare); } else { - const layer = findLayer(def, activeString); - layer.setOpacity(opacity); + const layerGroup = findLayer(def, activeString); + layerGroup.setOpacity(opacity); + layerGroup.getLayersArray().forEach((l) => { + l.setOpacity(opacity); + }); } updateLayerVisibilities(); }; diff --git a/web/js/mapUI/components/update-projection/updateProjection.js b/web/js/mapUI/components/update-projection/updateProjection.js index ec72e8db5b..1fb1b27ef9 100644 --- a/web/js/mapUI/components/update-projection/updateProjection.js +++ b/web/js/mapUI/components/update-projection/updateProjection.js @@ -280,7 +280,8 @@ function UpdateProjection(props) { * @returns {void} */ function showMap(map) { - document.getElementById(`${map.getTarget()}`).style.display = 'block'; + const el = document.getElementById(`${map.getTarget()}`); + if (el) el.style.display = 'block'; } /** @@ -294,7 +295,8 @@ function UpdateProjection(props) { * @returns {void} */ function hideMap(map) { - document.getElementById(`${map.getTarget()}`).style.display = 'none'; + const el = document.getElementById(`${map.getTarget()}`); + if (el) el.style.display = 'none'; } diff --git a/web/js/modules/layers/reducers.js b/web/js/modules/layers/reducers.js index 7e0bc83ac5..a956be58e4 100644 --- a/web/js/modules/layers/reducers.js +++ b/web/js/modules/layers/reducers.js @@ -159,12 +159,13 @@ export function layerReducer(state = initialState, action) { }; case TOGGLE_LAYER_VISIBILITY: + if (getLayerIndex() === -1) return state; return update(state, { [compareState]: { layers: { [getLayerIndex()]: { visible: { - $set: action.visible, + $set: action?.visible, }, }, }, diff --git a/web/js/modules/ui/actions.js b/web/js/modules/ui/actions.js index d440814440..2b207d702c 100644 --- a/web/js/modules/ui/actions.js +++ b/web/js/modules/ui/actions.js @@ -7,6 +7,7 @@ import { SET_ERROR_TILES, DISPLAY_STATIC_MAP, READY_FOR_KIOSK_ANIMATION, + CHECK_ANIMATION_AVAILABILITY, } from './constants'; import { CLOSE as CLOSE_MODAL } from '../modal/constants'; @@ -30,6 +31,8 @@ export default function toggleDistractionFreeMode() { }; } +// Keeping this action for testing purposes. +// Kiosk mode should always be activated through the permalink parameters. export function toggleKioskMode(isActive) { return { type: TOGGLE_KIOSK_MODE, @@ -37,6 +40,7 @@ export function toggleKioskMode(isActive) { }; } +// Layerbuilder tracks tile requests that return errors or blank tiles and dispatches this action for specific layers. export function setErrorTiles(errorTiles) { return { type: SET_ERROR_TILES, @@ -50,6 +54,8 @@ export function setErrorTiles(errorTiles) { }; } +// After each tile request we call this to clear the error tiles for the current date. +// We want to preserve the lastCheckedDate value from the previous dispatched setErrorTiles action. export function clearErrorTiles() { return (dispatch, getState) => { const { ui: { errorTiles: { lastCheckedDate } } } = getState(); @@ -74,6 +80,8 @@ export function clearErrorTiles() { }; } +// Dispatched when maximum date/time threshold is met when checking for error/blank tiles. +// Displays a static image map stored locally in repo. export function toggleStaticMap(isActive) { return { type: DISPLAY_STATIC_MAP, @@ -81,9 +89,21 @@ export function toggleStaticMap(isActive) { }; } +// When kiosk mode is active && (eic === 'sa' || eic === 'da') this action is dispatched once we step the date back to full imagery. +// This signals that the animation availability to ready to be checked. export function toggleReadyForKioskAnimation(toggleAnimation) { return { type: READY_FOR_KIOSK_ANIMATION, toggleAnimation, }; } + +// When kiosk mode is active && (eic === 'sa' || eic === 'da') this action is dispatched once the animation has been triggered. +// Once availability is measured and passes the threshold metric this action will dispatch. +// This signals that the animation is ready to be played. +export function toggleCheckedAnimationAvailability(toggleCheck) { + return { + type: CHECK_ANIMATION_AVAILABILITY, + toggleCheck, + }; +} diff --git a/web/js/modules/ui/constants.js b/web/js/modules/ui/constants.js index d6f2d71f14..8775e42db7 100644 --- a/web/js/modules/ui/constants.js +++ b/web/js/modules/ui/constants.js @@ -4,3 +4,4 @@ export const SET_ERROR_TILES = 'UI/SET_ERROR_TILES'; export const CLEAR_ERROR_TILES = 'UI/CLEAR_ERROR_TILES'; export const DISPLAY_STATIC_MAP = 'UI/DISPLAY_STATIC_MAP'; export const READY_FOR_KIOSK_ANIMATION = 'UI/READY_FOR_KIOSK_ANIMATION'; +export const CHECK_ANIMATION_AVAILABILITY = 'UI/CHECK_ANIMATION_AVAILABILITY'; diff --git a/web/js/modules/ui/reducers.js b/web/js/modules/ui/reducers.js index 1696a7dd24..5dcab1f082 100644 --- a/web/js/modules/ui/reducers.js +++ b/web/js/modules/ui/reducers.js @@ -5,13 +5,14 @@ import { DISPLAY_STATIC_MAP, CLEAR_ERROR_TILES, READY_FOR_KIOSK_ANIMATION, + CHECK_ANIMATION_AVAILABILITY, } from './constants'; export const uiState = { isDistractionFreeModeActive: false, isKioskModeActive: false, displayStaticMap: false, - eic: '', // sa == subdaily-animation, da == daily-animation, ss== subdaily-static, ds == daily-static + eic: '', // 'sa' == subdaily-animation, 'da' == daily-animation errorTiles: { dailyTiles: [], subdailyTiles: [], @@ -20,6 +21,7 @@ export const uiState = { lastCheckedDate: null, }, readyForKioskAnimation: false, + animationAvailabilityChecked: false, }; export default function uiReducers(state = uiState, action) { @@ -58,8 +60,12 @@ export default function uiReducers(state = uiState, action) { ...state, readyForKioskAnimation: action.toggleAnimation, }; + case CHECK_ANIMATION_AVAILABILITY: + return { + ...state, + animationAvailabilityChecked: action.toggleCheck, + }; default: return state; } } - diff --git a/web/scss/components/list.scss b/web/scss/components/list.scss index 48661329a0..eaa42237f6 100644 --- a/web/scss/components/list.scss +++ b/web/scss/components/list.scss @@ -2,6 +2,7 @@ background: #282828; color: #eee; text-align: left; + border: none; } .list-group-item.active { diff --git a/web/scss/features/events.scss b/web/scss/features/events.scss index 4887b86a2c..b01ab2c746 100644 --- a/web/scss/features/events.scss +++ b/web/scss/features/events.scss @@ -314,6 +314,12 @@ display: block; } +@media (any-hover: none) { + .track-marker-date-selected { + display: block; + } +} + .cluster-marker:hover ~ .cluster-track-marker-date { display: block; } diff --git a/web/scss/features/layers.scss b/web/scss/features/layers.scss index ccec9f8f82..3db40afd8d 100644 --- a/web/scss/features/layers.scss +++ b/web/scss/features/layers.scss @@ -431,7 +431,7 @@ flex-direction: column; } - & .product-outter-list-case { + & .product-outer-list-case { width: 100%; padding: 0 4px; } @@ -835,7 +835,7 @@ margin: 0; } - &.browse-search-width .product-outter-list-case { + &.browse-search-width .product-outer-list-case { width: 100%; } @@ -953,7 +953,7 @@ margin: 0; } - &.browse-search-width .product-outter-list-case { + &.browse-search-width .product-outer-list-case { width: 100%; } @@ -1052,3 +1052,9 @@ a[rel="noreferrer"]:hover { } } } + +.scrollable-layer-container { + overflow-y: scroll; + max-height: calc(100vh - 95px); + height: auto; +}