From c6908b568c666c9d6b6ce0e910e676f88c3b36b6 Mon Sep 17 00:00:00 2001 From: unclFedor <103448502+unclFedor@users.noreply.github.com> Date: Mon, 6 Nov 2023 10:14:58 +0100 Subject: [PATCH 01/40] feat: replace StaticMap By Maplibre (#308) * feat: replace StaticMap By Maplibre * fixed inspection's comments * fixed lint issues * fixed unit test issues * fixed unit test errors * fixed unit test per pull 310 * removed duplicated code in test --- package.json | 12 +- .../attributes-stats/attribute-stats.spec.tsx | 6 +- .../comparison-side/comparison-side.spec.tsx | 31 +- .../debug-panel/debug-panel.spec.tsx | 5 + .../deck-gl-wrapper/deck-gl-wrapper.spec.tsx | 48 +- .../deck-gl-wrapper/deck-gl-wrapper.tsx | 25 +- .../layers-panel/layers-panel.spec.tsx | 7 +- .../layers-panel/map-options-panel.spec.tsx | 5 + .../map-control-panel.spec.tsx | 6 + src/pages/dashboard/dashboard.tsx | 28 +- .../slices/attribute-stats-map-slice.spec.ts | 8 +- src/redux/slices/base-maps-slice.spec.ts | 6 + src/redux/slices/base-maps-slice.ts | 2 +- .../slices/colors-by-attribute-slice.spec.ts | 6 + src/redux/slices/debug-option-slice.spec.ts | 6 + src/redux/slices/drag-mode-slice.spec.ts | 6 + .../slices/flattened-sublayers-slice.spec.ts | 5 + .../slices/uv-debug-texture-slice.spec.ts | 5 + yarn.lock | 1325 +++++++++-------- 19 files changed, 858 insertions(+), 684 deletions(-) diff --git a/package.json b/package.json index 9b5b4db7..dc6adcf3 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,12 @@ "author": "", "license": "ISC", "dependencies": { + "@deck.gl/core": "^8.9.32", + "@deck.gl/extensions": "^8.9.32", + "@deck.gl/geo-layers": "^8.9.32", + "@deck.gl/layers": "^8.9.32", + "@deck.gl/mesh-layers": "^8.9.32", + "@deck.gl/react": "^8.9.32", "@fortawesome/fontawesome-svg-core": "^1.2.36", "@fortawesome/free-solid-svg-icons": "^5.15.4", "@fortawesome/react-fontawesome": "^0.1.17", @@ -29,18 +35,18 @@ "@loaders.gl/i3s": "^4.0.0-beta.2", "@loaders.gl/loader-utils": "^4.0.0-beta.2", "@loaders.gl/tiles": "^4.0.0-beta.2", - "@luma.gl/core": "^8.5.14", "@math.gl/proj4": "^3.6.3", "@probe.gl/stats": "^4.0.4", "@reduxjs/toolkit": "^1.9.5", - "deck.gl": "^8.8.3", + "apache-arrow": "^13.0.0", "html2canvas": "^1.4.1", + "maplibre-gl": "^3.5.2", "normalize.css": "^8.0.1", "prop-types": "^15.8.1", "react": "^17.0.2", "react-color": "^2.19.3", "react-dom": "^17.0.2", - "react-map-gl": "^5.0.0", + "react-map-gl": "^7.1.6", "react-redux": "^8.1.1", "react-responsive": "^9.0.0-beta.8", "react-router-dom": "^6.2.1", diff --git a/src/components/attributes-panel/attributes-stats/attribute-stats.spec.tsx b/src/components/attributes-panel/attributes-stats/attribute-stats.spec.tsx index 1d8507eb..887dc97d 100644 --- a/src/components/attributes-panel/attributes-stats/attribute-stats.spec.tsx +++ b/src/components/attributes-panel/attributes-stats/attribute-stats.spec.tsx @@ -9,7 +9,11 @@ import { setupStore } from "../../../redux/store"; import { setColorsByAttrubute } from "../../../redux/slices/colors-by-attribute-slice"; jest.mock("@loaders.gl/core"); - +jest.mock("@loaders.gl/i3s", () => { + return jest.fn().mockImplementation(() => { + return null; + }); +}); jest.mock("../histogram", () => ({ HistogramChart: jest.fn().mockImplementation(() =>
HistogramChart
), })); diff --git a/src/components/comparison/comparison-side/comparison-side.spec.tsx b/src/components/comparison/comparison-side/comparison-side.spec.tsx index 6a23f8b6..198cb217 100644 --- a/src/components/comparison/comparison-side/comparison-side.spec.tsx +++ b/src/components/comparison/comparison-side/comparison-side.spec.tsx @@ -18,7 +18,36 @@ import { MemoryUsagePanel } from "../../memory-usage-panel/memory-usage-panel"; import { setupStore } from "../../../redux/store"; import { setDragMode } from "../../../redux/slices/drag-mode-slice"; -jest.mock("@loaders.gl/core"); +jest.mock("react-map-gl/maplibre", () => { + return jest.fn().mockImplementation(() => { + return null; + }); +}); +jest.mock("@loaders.gl/core", () => { + return { + load: jest.fn(), + }; +}); +jest.mock("@loaders.gl/i3s", () => { + return jest.fn().mockImplementation(() => { + return null; + }); +}); +jest.mock("@loaders.gl/3d-tiles", () => { + return jest.fn().mockImplementation(() => { + return null; + }); +}); +jest.mock("@deck.gl/layers", () => { + return jest.fn().mockImplementation(() => { + return null; + }); +}); +jest.mock("@deck.gl/geo-layers", () => { + return jest.fn().mockImplementation(() => { + return null; + }); +}); jest.mock("../../deck-gl-wrapper/deck-gl-wrapper"); jest.mock("../../main-tools-panel/main-tools-panel"); jest.mock("../../layers-panel/layers-panel"); diff --git a/src/components/debug-panel/debug-panel.spec.tsx b/src/components/debug-panel/debug-panel.spec.tsx index 18b75124..6d449b15 100644 --- a/src/components/debug-panel/debug-panel.spec.tsx +++ b/src/components/debug-panel/debug-panel.spec.tsx @@ -16,6 +16,11 @@ import { selectBoundingVolumeType, } from "../../redux/slices/debug-options-slice"; +jest.mock("@loaders.gl/i3s", () => { + return jest.fn().mockImplementation(() => { + return null; + }); +}); jest.mock("../../utils/hooks/layout"); jest.mock("../close-button/close-button", () => ({ CloseButton: ({ onClick }) => { diff --git a/src/components/deck-gl-wrapper/deck-gl-wrapper.spec.tsx b/src/components/deck-gl-wrapper/deck-gl-wrapper.spec.tsx index c7fbf164..934b2994 100644 --- a/src/components/deck-gl-wrapper/deck-gl-wrapper.spec.tsx +++ b/src/components/deck-gl-wrapper/deck-gl-wrapper.spec.tsx @@ -11,6 +11,19 @@ import { // Mocks jest.mock("@loaders.gl/core"); +jest.mock("@loaders.gl/i3s", () => { + return { + COORDINATE_SYSTEM: { + METER_OFFSETS: 2, + LNGLAT_OFFSETS: 3, + }, + }; +}); +jest.mock("@loaders.gl/3d-tiles", () => { + return jest.fn().mockImplementation(() => { + return null; + }); +}); jest.mock("@loaders.gl/images"); jest.mock("@loaders.gl/tiles"); jest.mock("@deck.gl/react", () => { @@ -18,10 +31,25 @@ jest.mock("@deck.gl/react", () => { return null; }); }); +jest.mock("react-map-gl/maplibre", () => { + return { + Map: jest.fn().mockImplementation(() =>
), + }; +}); jest.mock("@deck.gl/core"); -jest.mock("@deck.gl/layers"); -jest.mock("@deck.gl/geo-layers"); -jest.mock("react-map-gl"); +jest.mock("@deck.gl/layers", () => { + return { + LineLayer: jest.fn(), + ScatterplotLayer: jest.fn(), + }; +}); + +jest.mock("@deck.gl/geo-layers", () => { + return { + Tile3DLayer: jest.fn(), + TerrainLayer: jest.fn(), + }; +}); jest.mock("../../utils/debug/build-minimap-data"); jest.mock("../../utils/debug/texture-selector-utils"); jest.mock("../../utils/debug/frustum-utils"); @@ -61,7 +89,7 @@ import { setupStore } from "../../redux/store"; import { setColorsByAttrubute } from "../../redux/slices/colors-by-attribute-slice"; import { setDragMode } from "../../redux/slices/drag-mode-slice"; import { setDebugOptions } from "../../redux/slices/debug-options-slice"; -import { addBaseMap } from "../../redux/slices/base-maps-slice" +import { addBaseMap } from "../../redux/slices/base-maps-slice"; const simpleCallbackMock = jest.fn().mockImplementation(() => { /* Do Nothing */ @@ -336,7 +364,11 @@ describe("Deck.gl I3S map component", () => { it("Should render pickable with auto highlighting", () => { const store = setupStore(); - callRender(renderWithProvider, { pickable: true, autoHighlight: true }, store); + callRender( + renderWithProvider, + { pickable: true, autoHighlight: true }, + store + ); const { pickable, autoHighlight } = Tile3DLayer.mock.lastCall[0]; expect(pickable).toBe(true); expect(autoHighlight).toBe(true); @@ -509,8 +541,7 @@ describe("Deck.gl I3S map component", () => { describe("Render TerrainLayer", () => { const store = setupStore(); - store.dispatch( - addBaseMap({ id: "Terrain", mapUrl: "", name: "Terrain" })); + store.dispatch(addBaseMap({ id: "Terrain", mapUrl: "", name: "Terrain" })); it("Should render terrain", () => { callRender(renderWithProvider, undefined, store); expect(TerrainLayer).toHaveBeenCalled(); @@ -519,7 +550,8 @@ describe("Deck.gl I3S map component", () => { it("Should call onTerrainTileLoad", () => { const store = setupStore(); store.dispatch( - addBaseMap({ id: "Terrain", mapUrl: "", name: "Terrain" })); + addBaseMap({ id: "Terrain", mapUrl: "", name: "Terrain" }) + ); const { rerender } = callRender(renderWithProvider, undefined, store); const { onTileLoad } = TerrainLayer.mock.lastCall[0]; const terrainTile = { diff --git a/src/components/deck-gl-wrapper/deck-gl-wrapper.tsx b/src/components/deck-gl-wrapper/deck-gl-wrapper.tsx index a938b42d..dffbbf78 100644 --- a/src/components/deck-gl-wrapper/deck-gl-wrapper.tsx +++ b/src/components/deck-gl-wrapper/deck-gl-wrapper.tsx @@ -1,3 +1,4 @@ +import { Map as MaplibreMap } from "react-map-gl/maplibre"; import DeckGL from "@deck.gl/react"; import { LineLayer, ScatterplotLayer } from "@deck.gl/layers"; import { TerrainLayer, Tile3DLayer } from "@deck.gl/geo-layers"; @@ -14,7 +15,6 @@ import { View, } from "@deck.gl/core"; import { useEffect, useMemo, useState, useRef } from "react"; -import { StaticMap } from "react-map-gl"; import { CONTRAST_MAP_STYLES } from "../../constants/map-styles"; import { NormalsDebugData, @@ -58,7 +58,10 @@ import { selectBoundingVolumeColorMode, selectBoundingVolumeType, } from "../../redux/slices/debug-options-slice"; -import { selectBaseMaps, selectSelectedBaseMapId } from "../../redux/slices/base-maps-slice"; +import { + selectBaseMaps, + selectSelectedBaseMapId, +} from "../../redux/slices/base-maps-slice"; const TRANSITION_DURAITON = 4000; const INITIAL_VIEW_STATE = { @@ -212,8 +215,8 @@ export const DeckGlWrapper = ({ const baseMaps = useAppSelector(selectBaseMaps); const selectedBaseMapId = useAppSelector(selectSelectedBaseMapId); const selectedBaseMap = baseMaps.find((map) => map.id === selectedBaseMapId); - const showTerrain=selectedBaseMap?.id === "Terrain"; - const mapStyle=selectedBaseMap?.mapUrl; + const showTerrain = selectedBaseMap?.id === "Terrain"; + const mapStyle = selectedBaseMap?.mapUrl; const VIEWS = useMemo( () => [ new MapView({ @@ -761,21 +764,11 @@ export const DeckGlWrapper = ({ currentViewport = viewport; }} {!showTerrain && ( - + )} {mapStyle && ( - + )} diff --git a/src/components/layers-panel/layers-panel.spec.tsx b/src/components/layers-panel/layers-panel.spec.tsx index 67d496ce..7d25e52a 100644 --- a/src/components/layers-panel/layers-panel.spec.tsx +++ b/src/components/layers-panel/layers-panel.spec.tsx @@ -12,14 +12,11 @@ import { LayerSettingsPanel } from "./layer-settings-panel"; import { load } from "@loaders.gl/core"; import { PageId } from "../../types"; import { setupStore } from "../../redux/store"; -import { - selectSelectedBaseMapId, -} from "../../redux/slices/base-maps-slice"; +import { selectSelectedBaseMapId } from "../../redux/slices/base-maps-slice"; jest.mock("@loaders.gl/core", () => ({ load: jest.fn(), })); - jest.mock("@loaders.gl/i3s", () => ({ ArcGisWebSceneLoader: jest.fn(), })); @@ -277,7 +274,7 @@ describe("Layers Panel", () => { }); const state = store.getState(); - const baseMapId = selectSelectedBaseMapId(state); + const baseMapId = selectSelectedBaseMapId(state); expect(baseMapId).toEqual("https://test-base-map.url"); }); diff --git a/src/components/layers-panel/map-options-panel.spec.tsx b/src/components/layers-panel/map-options-panel.spec.tsx index 6ee488ac..8f3130a1 100644 --- a/src/components/layers-panel/map-options-panel.spec.tsx +++ b/src/components/layers-panel/map-options-panel.spec.tsx @@ -14,6 +14,11 @@ import { selectSelectedBaseMapId, } from "../../redux/slices/base-maps-slice"; +jest.mock("@loaders.gl/i3s", () => { + return jest.fn().mockImplementation(() => { + return null; + }); +}); jest.mock("./base-map-list-item/base-map-list-item"); jest.mock("../plus-button/plus-button"); jest.mock("./delete-confirmation"); diff --git a/src/components/map-control-panel/map-control-panel.spec.tsx b/src/components/map-control-panel/map-control-panel.spec.tsx index 879182b6..724001a8 100644 --- a/src/components/map-control-panel/map-control-panel.spec.tsx +++ b/src/components/map-control-panel/map-control-panel.spec.tsx @@ -5,6 +5,12 @@ import { MapControllPanel } from "./map-control-panel"; import { setupStore } from "../../redux/store"; import { setDragMode } from "../../redux/slices/drag-mode-slice"; +jest.mock("@loaders.gl/i3s", () => { + return jest.fn().mockImplementation(() => { + return null; + }); +}); + describe("MapControllPanel", () => { let componentElement; let buttons; diff --git a/src/pages/dashboard/dashboard.tsx b/src/pages/dashboard/dashboard.tsx index f14c10de..5aff61b1 100644 --- a/src/pages/dashboard/dashboard.tsx +++ b/src/pages/dashboard/dashboard.tsx @@ -1,5 +1,5 @@ +import { Map as MaplibreMap } from "react-map-gl/maplibre"; import { useState, useCallback } from "react"; -import { StaticMap } from "react-map-gl"; import DeckGL from "@deck.gl/react"; import { Tile3DLayer } from "@deck.gl/geo-layers"; import { I3SLoader } from "@loaders.gl/i3s"; @@ -149,7 +149,7 @@ const Title = styled.div` desktop: "73px", tablet: "73px", mobile: "45px", - })}; + })}; `; const GreenText = styled.span` @@ -179,7 +179,7 @@ const IphoneImage = styled.img` left: 1670px; z-index: 4; width: 198px; - + @media (max-width: 1670px) { left: calc(100% - 184px); } @@ -310,7 +310,7 @@ export const Dashboard = () => { return ( - + Explore and Debug I3S Data with one <GreenText id="green-text"> Simple and Easy-to-Use Tool</GreenText> @@ -322,7 +322,7 @@ export const Dashboard = () => { layers={[tile3DLayer]} initialViewState={viewState} > - <StaticMap mapStyle={DEFAULT_MAP_STYLE} /> + <MaplibreMap mapStyle={DEFAULT_MAP_STYLE}></MaplibreMap> </DeckGL> </DeckWithTitleWrapper> <Wrapper id="tools-wrapper" layout={layout}> @@ -333,17 +333,13 @@ export const Dashboard = () => { src={AppShowcase} /> )} - {layout === Layout.Desktop && - ( - <> - <MacImage id="mac-image" src={Mac} /> - <IphoneImage id="iphone-image" src={Iphone} /> - </> - )} - <ToolsContainer - id="tools-description-container" - layout={layout} - > + {layout === Layout.Desktop && ( + <> + <MacImage id="mac-image" src={Mac} /> + <IphoneImage id="iphone-image" src={Iphone} /> + </> + )} + <ToolsContainer id="tools-description-container" layout={layout}> <ToolsItem id="tools-item-viewer" layout={layout}> <ViewerImage /> <ToolItemDescription layout={layout}> diff --git a/src/redux/slices/attribute-stats-map-slice.spec.ts b/src/redux/slices/attribute-stats-map-slice.spec.ts index f2f83d02..6f55d6d7 100644 --- a/src/redux/slices/attribute-stats-map-slice.spec.ts +++ b/src/redux/slices/attribute-stats-map-slice.spec.ts @@ -4,9 +4,13 @@ import { getAttributeStatsInfo, selectStatisitcsMap, } from "./attribute-stats-map-slice"; -import { StatsInfo } from "@loaders.gl/i3s"; jest.mock("@loaders.gl/core"); +jest.mock("@loaders.gl/i3s", () => { + return jest.fn().mockImplementation(() => { + return null; + }); +}); describe("slice: attribute-stats-map", () => { it("Selector should return the initial state", () => { @@ -54,7 +58,7 @@ describe("slice: attribute-stats-map", () => { }); }); -const stats: StatsInfo = { +const stats = { avg: 27.159085097827166, max: 1408.377901, min: 0, diff --git a/src/redux/slices/base-maps-slice.spec.ts b/src/redux/slices/base-maps-slice.spec.ts index 9d622eb2..f102075b 100644 --- a/src/redux/slices/base-maps-slice.spec.ts +++ b/src/redux/slices/base-maps-slice.spec.ts @@ -9,6 +9,12 @@ import reducer, { deleteBaseMaps, } from "./base-maps-slice"; +jest.mock("@loaders.gl/i3s", () => { + return jest.fn().mockImplementation(() => { + return null; + }); +}); + describe("slice: base-maps", () => { it("Reducer should return the initial state", () => { expect(reducer(undefined, { type: undefined })).toEqual({ diff --git a/src/redux/slices/base-maps-slice.ts b/src/redux/slices/base-maps-slice.ts index e1a10a84..356b5df3 100644 --- a/src/redux/slices/base-maps-slice.ts +++ b/src/redux/slices/base-maps-slice.ts @@ -4,7 +4,7 @@ import { BASE_MAPS } from "../../constants/map-styles"; import { RootState } from "../store"; // Define a type for the slice state -interface BaseMapsState { +export interface BaseMapsState { baseMap: BaseMap[]; selectedBaseMap: string; } diff --git a/src/redux/slices/colors-by-attribute-slice.spec.ts b/src/redux/slices/colors-by-attribute-slice.spec.ts index 62eae9c1..7969f4de 100644 --- a/src/redux/slices/colors-by-attribute-slice.spec.ts +++ b/src/redux/slices/colors-by-attribute-slice.spec.ts @@ -5,6 +5,12 @@ import reducer, { setColorsByAttrubute, } from "./colors-by-attribute-slice"; +jest.mock("@loaders.gl/i3s", () => { + return jest.fn().mockImplementation(() => { + return null; + }); +}); + describe("slice: colors-by-attribute", () => { it("Reducer should return the initial state", () => { expect(reducer(undefined, { type: undefined })).toEqual({ value: null }); diff --git a/src/redux/slices/debug-option-slice.spec.ts b/src/redux/slices/debug-option-slice.spec.ts index 277d5925..210e95fd 100644 --- a/src/redux/slices/debug-option-slice.spec.ts +++ b/src/redux/slices/debug-option-slice.spec.ts @@ -21,6 +21,12 @@ import reducer, { setDebugOptions, } from "./debug-options-slice"; +jest.mock("@loaders.gl/i3s", () => { + return jest.fn().mockImplementation(() => { + return null; + }); +}); + describe("slice: debug-options", () => { it("Reducer should return the initial state", () => { expect(reducer(undefined, { type: undefined })).toEqual({ diff --git a/src/redux/slices/drag-mode-slice.spec.ts b/src/redux/slices/drag-mode-slice.spec.ts index d6b1c67e..9308df16 100644 --- a/src/redux/slices/drag-mode-slice.spec.ts +++ b/src/redux/slices/drag-mode-slice.spec.ts @@ -6,6 +6,12 @@ import reducer, { setDragMode, } from "./drag-mode-slice"; +jest.mock("@loaders.gl/i3s", () => { + return jest.fn().mockImplementation(() => { + return null; + }); +}); + describe("slice: drag-mode", () => { it("Reducer should return the initial state", () => { expect(reducer(undefined, { type: undefined })).toEqual({ diff --git a/src/redux/slices/flattened-sublayers-slice.spec.ts b/src/redux/slices/flattened-sublayers-slice.spec.ts index ba9b89fc..1141f6e0 100644 --- a/src/redux/slices/flattened-sublayers-slice.spec.ts +++ b/src/redux/slices/flattened-sublayers-slice.spec.ts @@ -25,6 +25,11 @@ import { } from "./test-data/fluttened-sublayers-slice-test-data"; jest.mock("@loaders.gl/core"); +jest.mock("@loaders.gl/i3s", () => { + return jest.fn().mockImplementation(() => { + return null; + }); +}); const previousState: flattenedSublayersState = { single: { diff --git a/src/redux/slices/uv-debug-texture-slice.spec.ts b/src/redux/slices/uv-debug-texture-slice.spec.ts index c9684700..8d10424f 100644 --- a/src/redux/slices/uv-debug-texture-slice.spec.ts +++ b/src/redux/slices/uv-debug-texture-slice.spec.ts @@ -7,6 +7,11 @@ import { import { ImageLoader } from "@loaders.gl/images"; jest.mock("@loaders.gl/core"); +jest.mock("@loaders.gl/i3s", () => { + return jest.fn().mockImplementation(() => { + return null; + }); +}); const imageStubObject = { width: 1024, height: 1024, data: new ArrayBuffer(0) }; diff --git a/yarn.lock b/yarn.lock index 835a3442..0ff69e26 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,14 @@ # yarn lockfile v1 +"@75lb/deep-merge@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@75lb/deep-merge/-/deep-merge-1.1.1.tgz#3b06155b90d34f5f8cc2107d796f1853ba02fd6d" + integrity sha512-xvgv6pkMGBA6GwdyJbNAnDmfAIR/DfWhrj9jgWh3TY7gRm3KO46x/GPjRg6wJ0nOepwqrNxFfojebh0Df4h4Tw== + dependencies: + lodash.assignwith "^4.2.0" + typical "^7.1.1" + "@ampproject/remapping@^2.0.0": version "2.0.2" resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.0.2.tgz#f3d9760bf30588c51408dbe7c05ff2bb13069307" @@ -1658,131 +1666,90 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== -"@deck.gl/aggregation-layers@8.8.3": - version "8.8.3" - resolved "https://registry.yarnpkg.com/@deck.gl/aggregation-layers/-/aggregation-layers-8.8.3.tgz#589ca5eed9da588615318cdce36ce30f9d117ce5" - integrity sha512-Ioaw01bsueNWX1hA2ripTDt2OYIPe5EbPxcwRCqCs0W1u9brkj/2BFS2Xy5XVNYy1L6Zgt5RK5/m9HafoV8vXA== - dependencies: - "@luma.gl/constants" "^8.5.14" - "@luma.gl/shadertools" "^8.5.14" - "@math.gl/web-mercator" "^3.6.0" - d3-hexbin "^0.2.1" - -"@deck.gl/carto@8.8.3": - version "8.8.3" - resolved "https://registry.yarnpkg.com/@deck.gl/carto/-/carto-8.8.3.tgz#78b78670e7dd8bfa7d34fe860360b81551aba27d" - integrity sha512-3+rwwig7OLbWf3X0xYsmu5bAtj/mBb/OPH9eO5RTrxSUyLtYDoIjVjNrOXSyiwKlHMuDGs9a7Ax5g4Ppf7ECEw== - dependencies: - "@loaders.gl/gis" "^3.2.0" - "@loaders.gl/loader-utils" "^3.2.0" - "@loaders.gl/mvt" "^3.2.0" - "@loaders.gl/tiles" "^3.2.0" - "@luma.gl/constants" "^8.5.14" - "@math.gl/web-mercator" "^3.6.0" - cartocolor "^4.0.2" - d3-array "^2.8.0" - d3-color "^2.0.0" - d3-format "^2.0.0" - d3-scale "^3.2.3" - h3-js "^3.7.0" - moment-timezone "^0.5.33" - pbf "^3.2.1" - -"@deck.gl/core@8.8.3": - version "8.8.3" - resolved "https://registry.yarnpkg.com/@deck.gl/core/-/core-8.8.3.tgz#9e9b5db5bc172dee3fcd7c8bbca2b3af87bdbf41" - integrity sha512-n9GnCfVMYY/zwnEfpj9lKycPL0yItlmmVvU9fkWN90ztoyH3INK49LP8amPo0F3s8LaqKeYpt7ddCSbC8D7NOw== - dependencies: - "@loaders.gl/core" "^3.2.0" - "@loaders.gl/images" "^3.2.0" - "@luma.gl/constants" "^8.5.14" - "@luma.gl/core" "^8.5.14" - "@math.gl/core" "^3.6.0" - "@math.gl/sun" "^3.6.0" - "@math.gl/web-mercator" "^3.6.0" +"@deck.gl/core@^8.9.32": + version "8.9.32" + resolved "https://registry.yarnpkg.com/@deck.gl/core/-/core-8.9.32.tgz#45285a662068b08ebf04bf4509597c97adb923b4" + integrity sha512-LQA2wPYxuWqZyxrlFZMsLOr3tBHdOFXMMVz4wBNATCyObbc9THly8FgW2N48tHT6OY2fM2N5wmbw9uRLsCg1kw== + dependencies: + "@babel/runtime" "^7.0.0" + "@loaders.gl/core" "^3.4.13" + "@loaders.gl/images" "^3.4.13" + "@luma.gl/constants" "^8.5.21" + "@luma.gl/core" "^8.5.21" + "@luma.gl/webgl" "^8.5.21" + "@math.gl/core" "^3.6.2" + "@math.gl/sun" "^3.6.2" + "@math.gl/web-mercator" "^3.6.2" "@probe.gl/env" "^3.5.0" "@probe.gl/log" "^3.5.0" "@probe.gl/stats" "^3.5.0" gl-matrix "^3.0.0" - math.gl "^3.6.0" + math.gl "^3.6.2" mjolnir.js "^2.7.0" -"@deck.gl/extensions@8.8.3": - version "8.8.3" - resolved "https://registry.yarnpkg.com/@deck.gl/extensions/-/extensions-8.8.3.tgz#6566fcf14369062e292f122d4c3893bb7c92e979" - integrity sha512-cBN9HbzNfHjfqbnfSVZl2qJu53/2NrUsqHqtqISL+mj3lvHWNJomTa/NzPNKcvfRpumDnGjfSx1gFKph8a4XXA== - dependencies: - "@luma.gl/shadertools" "^8.5.14" - -"@deck.gl/geo-layers@8.8.3": - version "8.8.3" - resolved "https://registry.yarnpkg.com/@deck.gl/geo-layers/-/geo-layers-8.8.3.tgz#ae80a4bca46e5fc01ede379eb00c936ad141cf4b" - integrity sha512-bnxjGVoHLoNPogyMcXl9HVVKVrAZPemVQk8aAIpXkIK48bG4Tlh3PMfDWizxzE4dmRpGezBOkqiF5yXwZClrew== - dependencies: - "@loaders.gl/3d-tiles" "^3.2.0" - "@loaders.gl/gis" "^3.2.0" - "@loaders.gl/loader-utils" "^3.2.0" - "@loaders.gl/mvt" "^3.2.0" - "@loaders.gl/schema" "^3.2.0" - "@loaders.gl/terrain" "^3.2.0" - "@loaders.gl/tiles" "^3.2.0" - "@luma.gl/constants" "^8.5.14" - "@luma.gl/experimental" "^8.5.14" - "@math.gl/core" "^3.6.0" - "@math.gl/culling" "^3.6.0" - "@math.gl/web-mercator" "^3.6.0" +"@deck.gl/extensions@^8.9.32": + version "8.9.32" + resolved "https://registry.yarnpkg.com/@deck.gl/extensions/-/extensions-8.9.32.tgz#34d64cb4b7374e1ae1960be2c559c8aa7d7814d4" + integrity sha512-v2ALtHRnIj8F4MA6jwDq+rqZIl/1gU2d+kA9+MgLMiO2GW4o+IcR8IuCfL/wXe2e10Wjhmc7LlhpVc13ljOWlw== + dependencies: + "@babel/runtime" "^7.0.0" + "@luma.gl/shadertools" "^8.5.21" + +"@deck.gl/geo-layers@^8.9.32": + version "8.9.32" + resolved "https://registry.yarnpkg.com/@deck.gl/geo-layers/-/geo-layers-8.9.32.tgz#175863836c30d5b264ba9441dc2b19360553cc7d" + integrity sha512-yJe96Z47qhdvnkN0u2DkDIAS2SGBS9XxWWT06lQpRIJnJl8PXStcHK0rvcZgdfMBW8INtcAfF8LnkEhqzbWnAQ== + dependencies: + "@babel/runtime" "^7.0.0" + "@loaders.gl/3d-tiles" "^3.4.13" + "@loaders.gl/gis" "^3.4.13" + "@loaders.gl/loader-utils" "^3.4.13" + "@loaders.gl/mvt" "^3.4.13" + "@loaders.gl/schema" "^3.4.13" + "@loaders.gl/terrain" "^3.4.13" + "@loaders.gl/tiles" "^3.4.13" + "@loaders.gl/wms" "^3.4.13" + "@luma.gl/constants" "^8.5.21" + "@luma.gl/experimental" "^8.5.21" + "@math.gl/core" "^3.6.2" + "@math.gl/culling" "^3.6.2" + "@math.gl/web-mercator" "^3.6.2" "@types/geojson" "^7946.0.8" h3-js "^3.7.0" long "^3.2.0" -"@deck.gl/google-maps@8.8.3": - version "8.8.3" - resolved "https://registry.yarnpkg.com/@deck.gl/google-maps/-/google-maps-8.8.3.tgz#a93473bb091ee9eee1dd0ecb50b828ad4933fc37" - integrity sha512-e85ntVJf9yDShvOdrwnZYTn43LV6mxWCxNSN0oCEPMw0NjMcX6oNGXdORgj6NxC0KXK1a7awVNxggxXJ3+AgXA== - -"@deck.gl/json@8.8.3": - version "8.8.3" - resolved "https://registry.yarnpkg.com/@deck.gl/json/-/json-8.8.3.tgz#b3ae54e5ec1a0bf5917e03c73e4d8406582c39c0" - integrity sha512-DbovlgaCnv053AevDrRNVSSt3VP8Vj0DXNHK8ejRfYDlFp8pOltkTUAxA7wBl5yrKeIBFjoHbPDEZ8MAbNxing== - dependencies: - d3-dsv "^1.0.8" - expression-eval "^2.0.0" - -"@deck.gl/layers@8.8.3": - version "8.8.3" - resolved "https://registry.yarnpkg.com/@deck.gl/layers/-/layers-8.8.3.tgz#2484d48451241279480a711060b648cad73dae63" - integrity sha512-YWwTzuHmyD1lQ59H70xhx1gXJBLbXo2Bdq9TwEAxwS0IO9K18yhgRv6bFaarGB8pS8zv5g0WiY5kcNyqaA6Cvw== - dependencies: - "@loaders.gl/images" "^3.2.0" - "@loaders.gl/schema" "^3.2.0" - "@luma.gl/constants" "^8.5.14" - "@mapbox/tiny-sdf" "^1.1.0" - "@math.gl/core" "^3.6.0" - "@math.gl/polygon" "^3.6.0" - "@math.gl/web-mercator" "^3.6.0" - earcut "^2.0.6" - -"@deck.gl/mapbox@8.8.3": - version "8.8.3" - resolved "https://registry.yarnpkg.com/@deck.gl/mapbox/-/mapbox-8.8.3.tgz#a3aa9382d0f0119b0f367a278e09ada2f4379705" - integrity sha512-P68AhgYmgMENiWRvi039S4aj41ppDrwwfwZgp4MdiTQA8X3OxLPhWNX3Z8QvY4BkQRGCPXSigeRBxFSkKC4ZbQ== +"@deck.gl/layers@^8.9.32": + version "8.9.32" + resolved "https://registry.yarnpkg.com/@deck.gl/layers/-/layers-8.9.32.tgz#0c0b1909e7aba52ab156766c57f93c6d3d6af771" + integrity sha512-UuUBbRvBnL42pG70YY12YLspl6t/OacP4f/E3Ty0lliXe0m/5jJFW+moubsz3goBV0adMI+CQf57cdlqlfQ4AQ== dependencies: - "@types/mapbox-gl" "^2.6.3" - -"@deck.gl/mesh-layers@8.8.3": - version "8.8.3" - resolved "https://registry.yarnpkg.com/@deck.gl/mesh-layers/-/mesh-layers-8.8.3.tgz#a5924f959ff1b1327ea449c49d56322e8111d876" - integrity sha512-7TCZD9uECUmgHTDmWaHZRRS7B66f91AZ5Fn9h1PFlTn49wIxnd7uSX2ARCfDgZj1FA+9QRY2GKM16vQOhEyxjg== + "@babel/runtime" "^7.0.0" + "@loaders.gl/images" "^3.4.13" + "@loaders.gl/schema" "^3.4.13" + "@luma.gl/constants" "^8.5.21" + "@mapbox/tiny-sdf" "^2.0.5" + "@math.gl/core" "^3.6.2" + "@math.gl/polygon" "^3.6.2" + "@math.gl/web-mercator" "^3.6.2" + earcut "^2.2.4" + +"@deck.gl/mesh-layers@^8.9.32": + version "8.9.32" + resolved "https://registry.yarnpkg.com/@deck.gl/mesh-layers/-/mesh-layers-8.9.32.tgz#51fa85c469b61116c3cb64c6d39c999d6bba5e25" + integrity sha512-6bsy54PrBHjZriEe3Rf1iBVAI8Afy3L1qAXqKemxYaH56rc5EYlrmD0E/zKcACikIRFmE7bgQz/i6hlSt7dBHg== dependencies: - "@loaders.gl/gltf" "^3.2.0" - "@luma.gl/constants" "^8.5.14" - "@luma.gl/experimental" "^8.5.14" - "@luma.gl/shadertools" "^8.5.14" + "@babel/runtime" "^7.0.0" + "@loaders.gl/gltf" "^3.4.13" + "@luma.gl/constants" "^8.5.21" + "@luma.gl/experimental" "^8.5.21" + "@luma.gl/shadertools" "^8.5.21" -"@deck.gl/react@8.8.3": - version "8.8.3" - resolved "https://registry.yarnpkg.com/@deck.gl/react/-/react-8.8.3.tgz#e0e5ea77d6dd95bde2a0ef4490ff5aa3df809a0f" - integrity sha512-mFANO0HNze7iHFAtHA8njDELOWHsEC0D7dkijZugk86qPitJPCuY0aac9tLp5P0B9S3faMWgvYW+KbEA29YqlA== +"@deck.gl/react@^8.9.32": + version "8.9.32" + resolved "https://registry.yarnpkg.com/@deck.gl/react/-/react-8.9.32.tgz#9111801def2ad28c90292fbbbdea3de65288891a" + integrity sha512-FGBry/W8lCokSarKXhK7iWwdAG1cjJwEwlAv6nI/rmG28e7uElyVvOsMzzoIEFrQTovN4Xzs4RZrxliFk8CaWg== + dependencies: + "@babel/runtime" "^7.0.0" "@discoveryjs/json-ext@^0.5.0": version "0.5.6" @@ -2159,18 +2126,19 @@ "@jridgewell/resolve-uri" "^3.0.3" "@jridgewell/sourcemap-codec" "^1.4.10" -"@loaders.gl/3d-tiles@^3.2.0": - version "3.2.12" - resolved "https://registry.yarnpkg.com/@loaders.gl/3d-tiles/-/3d-tiles-3.2.12.tgz#a9e55526d15231f5365ff1b6960855147640ccb1" - integrity sha512-fhJAW4KiMZ14isp/TaZe7GVptAtB7eT0MqM1nDoqWR7SlsxOrtW4S/hC+g58isf1FQ10DutpL8zs0ORVhSaweQ== +"@loaders.gl/3d-tiles@^3.4.13": + version "3.4.14" + resolved "https://registry.yarnpkg.com/@loaders.gl/3d-tiles/-/3d-tiles-3.4.14.tgz#c04781acf377e13c16b41eeaa14e46dfc96c90ca" + integrity sha512-cxStTSLIJgRZnkTBYTcp9FPVBQWQlJMzW1LRlaKWiwAHkOKBElszzApIIEvRvZGSrs8k8TUi6BJ1Y41iiANF7w== dependencies: - "@loaders.gl/draco" "3.2.12" - "@loaders.gl/gltf" "3.2.12" - "@loaders.gl/loader-utils" "3.2.12" - "@loaders.gl/math" "3.2.12" - "@loaders.gl/tiles" "3.2.12" + "@loaders.gl/draco" "3.4.14" + "@loaders.gl/gltf" "3.4.14" + "@loaders.gl/loader-utils" "3.4.14" + "@loaders.gl/math" "3.4.14" + "@loaders.gl/tiles" "3.4.14" "@math.gl/core" "^3.5.1" "@math.gl/geospatial" "^3.5.1" + long "^5.2.1" "@loaders.gl/3d-tiles@^4.0.0-beta.2": version "4.0.0-beta.2" @@ -2207,16 +2175,15 @@ lz4js "^0.2.0" zstd-codec "^0.1" -"@loaders.gl/core@^3.2.0": - version "3.2.12" - resolved "https://registry.yarnpkg.com/@loaders.gl/core/-/core-3.2.12.tgz#55a58b71d1aa64aa404d0369d190392fd2d4faca" - integrity sha512-kRQZGZ2+bvd++spjfp00aq2e3RrawAlaCwFxVyyQT6kYyQIzexr/obKd3X+yxYcrr4kUsav2iGqhLVObINlStQ== +"@loaders.gl/core@^3.4.13": + version "3.4.14" + resolved "https://registry.yarnpkg.com/@loaders.gl/core/-/core-3.4.14.tgz#79e5c54112f5bfe398da1718dc4fb661ffa213fd" + integrity sha512-5PFcjv7xC8AYL17juDMrvo8n0Fcwg9s8F4BaM2YCNUsb9RCI2SmLuIFJMcx1GgHO5vL0WiTIKO+JT4n1FuNR6w== dependencies: "@babel/runtime" "^7.3.1" - "@loaders.gl/loader-utils" "3.2.12" - "@loaders.gl/worker-utils" "3.2.12" - "@probe.gl/log" "^3.5.0" - probe.gl "^3.4.0" + "@loaders.gl/loader-utils" "3.4.14" + "@loaders.gl/worker-utils" "3.4.14" + "@probe.gl/log" "^4.0.1" "@loaders.gl/core@^4.0.0-beta.2": version "4.0.0-beta.2" @@ -2228,16 +2195,16 @@ "@loaders.gl/worker-utils" "4.0.0-beta.2" "@probe.gl/log" "^4.0.2" -"@loaders.gl/draco@3.2.12": - version "3.2.12" - resolved "https://registry.yarnpkg.com/@loaders.gl/draco/-/draco-3.2.12.tgz#e561431a2c6b4971abcf39e7704aa1f36a1f5f30" - integrity sha512-QoDlnL3ouwW3OSMRbyE4DyY41oxqadtaQ7wU3K6us4CF0XgvOToZZTG6QnCfF8FauFZ8JMebn6NT1LtobTNVYQ== +"@loaders.gl/draco@3.4.14": + version "3.4.14" + resolved "https://registry.yarnpkg.com/@loaders.gl/draco/-/draco-3.4.14.tgz#8555d9179db334faaded00d2902c318478a93b07" + integrity sha512-HwNFFt+dKZqFtzI0uVGvRkudFEZXxybJ+ZRsNkBbzAWoMM5L1TpuLs6DPsqPQUIT9HXNHzov18cZI0gK5bTJpg== dependencies: "@babel/runtime" "^7.3.1" - "@loaders.gl/loader-utils" "3.2.12" - "@loaders.gl/schema" "3.2.12" - "@loaders.gl/worker-utils" "3.2.12" - draco3d "1.4.1" + "@loaders.gl/loader-utils" "3.4.14" + "@loaders.gl/schema" "3.4.14" + "@loaders.gl/worker-utils" "3.4.14" + draco3d "1.5.5" "@loaders.gl/draco@4.0.0-beta.2": version "4.0.0-beta.2" @@ -2250,26 +2217,27 @@ "@loaders.gl/worker-utils" "4.0.0-beta.2" draco3d "1.5.5" -"@loaders.gl/gis@3.2.12", "@loaders.gl/gis@^3.2.0": - version "3.2.12" - resolved "https://registry.yarnpkg.com/@loaders.gl/gis/-/gis-3.2.12.tgz#d47ae587a7e5bef796fc74ccbe0c699e5a54d0a2" - integrity sha512-mm7YtDY2bnf+gWTKHRYK2T0itWilidyvsmZ6AcP5IiIwWoSaKBvBGq+mpzVWTKhgPvul7dP8+u2u7iuromxTGQ== +"@loaders.gl/gis@3.4.14", "@loaders.gl/gis@^3.4.13": + version "3.4.14" + resolved "https://registry.yarnpkg.com/@loaders.gl/gis/-/gis-3.4.14.tgz#a9b3eed45e2a4465a754e3404061222c51b1334a" + integrity sha512-5cmhIwioPpSkfNzFRM3PbFDecjpYIhtEOFbryu3rE37npKHLTD2tF4ocQxUPB+QVED6GLwWBdzJIs64UWGrqjw== dependencies: - "@loaders.gl/loader-utils" "3.2.12" - "@loaders.gl/schema" "3.2.12" + "@loaders.gl/loader-utils" "3.4.14" + "@loaders.gl/schema" "3.4.14" "@mapbox/vector-tile" "^1.3.1" "@math.gl/polygon" "^3.5.1" pbf "^3.2.1" -"@loaders.gl/gltf@3.2.12", "@loaders.gl/gltf@^3.2.0": - version "3.2.12" - resolved "https://registry.yarnpkg.com/@loaders.gl/gltf/-/gltf-3.2.12.tgz#3b602986b2e215ffc48c2b110e4be381be0326f5" - integrity sha512-vdLdWruh4nqmDm/9T0HWX30fJ+UVtB35uQk9dhN/couvrXXtdpkvtb7aFdX0nlCLcrbRlcCYbuCfKctt1CF2mg== +"@loaders.gl/gltf@3.4.14", "@loaders.gl/gltf@^3.4.13": + version "3.4.14" + resolved "https://registry.yarnpkg.com/@loaders.gl/gltf/-/gltf-3.4.14.tgz#8677d6793cf0827dee52711e55fbdc445e9f9bb8" + integrity sha512-jv+B5S/taiwzXAOu5D9nk1jjU9+JCCr/6/nGguCE2Ya3IX7CI1Nlnp20eKKhW8ZCEokZavMNT0bNbiJ5ahEFjA== dependencies: - "@loaders.gl/draco" "3.2.12" - "@loaders.gl/images" "3.2.12" - "@loaders.gl/loader-utils" "3.2.12" - "@loaders.gl/textures" "3.2.12" + "@loaders.gl/draco" "3.4.14" + "@loaders.gl/images" "3.4.14" + "@loaders.gl/loader-utils" "3.4.14" + "@loaders.gl/textures" "3.4.14" + "@math.gl/core" "^3.5.1" "@loaders.gl/gltf@4.0.0-beta.2": version "4.0.0-beta.2" @@ -2300,12 +2268,12 @@ "@math.gl/geospatial" "^3.5.1" md5 "^2.3.0" -"@loaders.gl/images@3.2.12", "@loaders.gl/images@^3.2.0": - version "3.2.12" - resolved "https://registry.yarnpkg.com/@loaders.gl/images/-/images-3.2.12.tgz#9ab2bab72892f72ecb4450f1343f6d12fcc56ffd" - integrity sha512-acPKRg9EwgrPyItF97x8LM9p4b8GR03JY+wFJwzBlVdOZXx1dmz1t4rVynRDwgAUgybGKLoPfJtwTIKARnICYQ== +"@loaders.gl/images@3.4.14", "@loaders.gl/images@^3.4.13": + version "3.4.14" + resolved "https://registry.yarnpkg.com/@loaders.gl/images/-/images-3.4.14.tgz#d7a4950f11b48d028cf3719cf6498945f4a05c14" + integrity sha512-tL447hTWhOKBOB87SE4hvlC8OkbRT0mEaW1a/wIS9f4HnYDa/ycRLMV+nvdvYMZur4isNPam44oiRqi7GcILkg== dependencies: - "@loaders.gl/loader-utils" "3.2.12" + "@loaders.gl/loader-utils" "3.4.14" "@loaders.gl/images@4.0.0-beta.2": version "4.0.0-beta.2" @@ -2314,14 +2282,14 @@ dependencies: "@loaders.gl/loader-utils" "4.0.0-beta.2" -"@loaders.gl/loader-utils@3.2.12", "@loaders.gl/loader-utils@^3.2.0": - version "3.2.12" - resolved "https://registry.yarnpkg.com/@loaders.gl/loader-utils/-/loader-utils-3.2.12.tgz#dfa9093d52a806128ff758e06f4b90cfc46d46db" - integrity sha512-OXu7vqBvYj2HD0Tcle8RwRAktJ5BsBTZc6ADPNia7FOGI9sA2ZDECPa0g8gBtKpbhzluLZzPj5N4OPdL6hNiQg== +"@loaders.gl/loader-utils@3.4.14", "@loaders.gl/loader-utils@^3.4.13": + version "3.4.14" + resolved "https://registry.yarnpkg.com/@loaders.gl/loader-utils/-/loader-utils-3.4.14.tgz#d94decc279fd2304b8762c87d8d9626058d91f21" + integrity sha512-HCTY2/F83RLbZWcTvWLVJ1vke3dl6Bye20HU1AqkA37J2vzHwOZ8kj6eee8eeSkIkf7VIFwjyhVJxe0flQE/Bw== dependencies: "@babel/runtime" "^7.3.1" - "@loaders.gl/worker-utils" "3.2.12" - "@probe.gl/stats" "^3.5.0" + "@loaders.gl/worker-utils" "3.4.14" + "@probe.gl/stats" "^4.0.1" "@loaders.gl/loader-utils@4.0.0-beta.2", "@loaders.gl/loader-utils@^4.0.0-beta.2": version "4.0.0-beta.2" @@ -2332,13 +2300,13 @@ "@loaders.gl/worker-utils" "4.0.0-beta.2" "@probe.gl/stats" "^4.0.2" -"@loaders.gl/math@3.2.12": - version "3.2.12" - resolved "https://registry.yarnpkg.com/@loaders.gl/math/-/math-3.2.12.tgz#148853e5708ed9c59b2f7c093bc3e1309579a92e" - integrity sha512-+34kJ6v//33xJq7mFd5ndNe0BU5bgy4afQ5ciy4VVhQns/Keml9hl/i8eOY2lFt/SUs1T2CSe1+X5065L0CWCA== +"@loaders.gl/math@3.4.14": + version "3.4.14" + resolved "https://registry.yarnpkg.com/@loaders.gl/math/-/math-3.4.14.tgz#c27993f0dbe5a88f3ffa07e5240ce27ea5e92392" + integrity sha512-OBEVX6Q5pMipbCAiZyX2+q1zRd0nw8M2dclpny05on8700OaKMwfs47wEUnbfCU3iyHad3sgsAxN3EIh+kuo9Q== dependencies: - "@loaders.gl/images" "3.2.12" - "@loaders.gl/loader-utils" "3.2.12" + "@loaders.gl/images" "3.4.14" + "@loaders.gl/loader-utils" "3.4.14" "@math.gl/core" "^3.5.1" "@loaders.gl/math@4.0.0-beta.2": @@ -2350,24 +2318,23 @@ "@loaders.gl/loader-utils" "4.0.0-beta.2" "@math.gl/core" "^3.5.1" -"@loaders.gl/mvt@^3.2.0": - version "3.2.12" - resolved "https://registry.yarnpkg.com/@loaders.gl/mvt/-/mvt-3.2.12.tgz#ff399c252738597a608687d801eb47a1f4be5f5a" - integrity sha512-gr81UErVuZ2JMGwnrz/Bg4SGe3i6T3VQ9Z8bjGU50pwpFMgn+fKmQe5CyoC+XvYQ8nDML76QCgo5sLX+9ePhHA== +"@loaders.gl/mvt@^3.4.13": + version "3.4.14" + resolved "https://registry.yarnpkg.com/@loaders.gl/mvt/-/mvt-3.4.14.tgz#fee16db321301e94b329c6be9db9420db0be17c8" + integrity sha512-tozGmWvsJacjaLavjX4S/5yNDV9S4wJb7+vPG/nXWX2gTtgZ1mxcFQAtAJjokqpy37d1ZhLt+TXh0HrLoTmRgw== dependencies: - "@loaders.gl/gis" "3.2.12" - "@loaders.gl/loader-utils" "3.2.12" - "@loaders.gl/schema" "3.2.12" + "@loaders.gl/gis" "3.4.14" + "@loaders.gl/loader-utils" "3.4.14" + "@loaders.gl/schema" "3.4.14" "@math.gl/polygon" "^3.5.1" pbf "^3.2.1" -"@loaders.gl/schema@3.2.12", "@loaders.gl/schema@^3.2.0": - version "3.2.12" - resolved "https://registry.yarnpkg.com/@loaders.gl/schema/-/schema-3.2.12.tgz#312911131d7fc90e05b771e95696dfddacb7c738" - integrity sha512-IP/fniG3PsMvhU+kkryULAoszgNEUSmfCvKZujDtU65xgIHScNQP87+wgqfZFScftEX0iBSahr7QYdQCEsv83w== +"@loaders.gl/schema@3.4.14", "@loaders.gl/schema@^3.4.13": + version "3.4.14" + resolved "https://registry.yarnpkg.com/@loaders.gl/schema/-/schema-3.4.14.tgz#6f145065a2abaf402aa419cfa25ec7f1fdeed487" + integrity sha512-r6BEDfUvbvzgUnh/MtkR5RzrkIwo1x1jtPFRTSJVsIZO7arXXlu3blffuv5ppEkKpNZ1Xzd9WtHp/JIkuctsmw== dependencies: "@types/geojson" "^7946.0.7" - apache-arrow "^4.0.0" "@loaders.gl/schema@4.0.0-beta.2": version "4.0.0-beta.2" @@ -2376,25 +2343,26 @@ dependencies: "@types/geojson" "^7946.0.7" -"@loaders.gl/terrain@^3.2.0": - version "3.2.12" - resolved "https://registry.yarnpkg.com/@loaders.gl/terrain/-/terrain-3.2.12.tgz#742916b7091b1a076420ae9e5186899d211b7b8c" - integrity sha512-Vluf7PrVl/0eId4Qqbjrla97XnNuVpmrE4sZHyY3gjdpxn/liMwYmIzts8ZWkB7pXrH5CmN+fUBOyPbNh9vuLw== +"@loaders.gl/terrain@^3.4.13": + version "3.4.14" + resolved "https://registry.yarnpkg.com/@loaders.gl/terrain/-/terrain-3.4.14.tgz#8cd469b356b94c0d31ffc987c9166ccd33fe1d86" + integrity sha512-vhchEVkPaWXnqd2ofujG2AEnBsk4hEw6LWSaFY7E3VMzNhI9l2EHvyU3+Hs03jYbXM4oLlQPGqd/T7x+5IMtig== dependencies: "@babel/runtime" "^7.3.1" - "@loaders.gl/loader-utils" "3.2.12" - "@loaders.gl/schema" "3.2.12" + "@loaders.gl/images" "3.4.14" + "@loaders.gl/loader-utils" "3.4.14" + "@loaders.gl/schema" "3.4.14" "@mapbox/martini" "^0.2.0" -"@loaders.gl/textures@3.2.12": - version "3.2.12" - resolved "https://registry.yarnpkg.com/@loaders.gl/textures/-/textures-3.2.12.tgz#75cda15b13761ba48f56e5751e2f7eb219105b83" - integrity sha512-xludkKPnzdQAHC19J0depqEvUH8x61cjsMId9Q1Et/emwI5TyEiDK78vl7tsIzuOh/IvrPHykRxfXp4uayW+Nw== +"@loaders.gl/textures@3.4.14": + version "3.4.14" + resolved "https://registry.yarnpkg.com/@loaders.gl/textures/-/textures-3.4.14.tgz#a229ff70592b7a90af96fdd361cda48b9c95bec9" + integrity sha512-iKDHL2ZlOUud4/e3g0p0SyvkukznopYy6La3O6I9vDfKp8peuKMRRcTfFfd/zH0OqQC0hIhCXNz46vRLu7h6ng== dependencies: - "@loaders.gl/images" "3.2.12" - "@loaders.gl/loader-utils" "3.2.12" - "@loaders.gl/schema" "3.2.12" - "@loaders.gl/worker-utils" "3.2.12" + "@loaders.gl/images" "3.4.14" + "@loaders.gl/loader-utils" "3.4.14" + "@loaders.gl/schema" "3.4.14" + "@loaders.gl/worker-utils" "3.4.14" ktx-parse "^0.0.4" texture-compressor "^1.0.2" @@ -2410,7 +2378,7 @@ ktx-parse "^0.0.4" texture-compressor "^1.0.2" -"@loaders.gl/tiles@3.2.12", "@loaders.gl/tiles@4.0.0-beta.2", "@loaders.gl/tiles@^3.2.0", "@loaders.gl/tiles@^4.0.0-beta.2": +"@loaders.gl/tiles@3.4.14", "@loaders.gl/tiles@4.0.0-beta.2", "@loaders.gl/tiles@^3.4.13", "@loaders.gl/tiles@^4.0.0-beta.2": version "4.0.0-beta.2" resolved "https://registry.yarnpkg.com/@loaders.gl/tiles/-/tiles-4.0.0-beta.2.tgz#fbad0b87b75dd7bdb26ae586cfbd194ea0675c91" integrity sha512-EdwwYDqfzSA/aKpDxRv2hbHduMSTWauRmKC4j2E9oDGkl1lsIxgytR0ifjmqxHoZ4T3m91i/fcymI0CbS8k+aA== @@ -2423,10 +2391,24 @@ "@math.gl/web-mercator" "^3.5.1" "@probe.gl/stats" "^4.0.2" -"@loaders.gl/worker-utils@3.2.12": - version "3.2.12" - resolved "https://registry.yarnpkg.com/@loaders.gl/worker-utils/-/worker-utils-3.2.12.tgz#c47a6ddc2eae2845f7e9be14cf33f672da164fb0" - integrity sha512-MRgk8ln4Ur2RAnalD6OWstSuIAlf0l/26KTHtJiVD+HtmLJDoxSoQOHsnrEsdE18m+8NpAQgTD+rDzZtEpsnlw== +"@loaders.gl/wms@^3.4.13": + version "3.4.14" + resolved "https://registry.yarnpkg.com/@loaders.gl/wms/-/wms-3.4.14.tgz#1bfde56078409fb41a749c1ef9e22a870fa59e3e" + integrity sha512-D1pObPSUj885zGPyHIb7GtcwpHQNk0T8nK/4EHb0SHLe0y1b4qwqSOswdS9geXT9Q61hyhl/L0zqyTgwjiMStg== + dependencies: + "@babel/runtime" "^7.3.1" + "@loaders.gl/images" "3.4.14" + "@loaders.gl/loader-utils" "3.4.14" + "@loaders.gl/schema" "3.4.14" + "@loaders.gl/xml" "3.4.14" + "@turf/rewind" "^5.1.5" + deep-strict-equal "^0.2.0" + lerc "^4.0.1" + +"@loaders.gl/worker-utils@3.4.14": + version "3.4.14" + resolved "https://registry.yarnpkg.com/@loaders.gl/worker-utils/-/worker-utils-3.4.14.tgz#5391a416a3d60e03b9edcedb285af44312d40d2e" + integrity sha512-PUSwxoAYbskisXd0KfYEQ902b0igBA2UAWdP6PzPvY+tJmobfh74dTNwrrBQ1rGXQxxmGx6zc6/ksX6mlIzIrg== dependencies: "@babel/runtime" "^7.3.1" @@ -2437,6 +2419,16 @@ dependencies: "@babel/runtime" "^7.3.1" +"@loaders.gl/xml@3.4.14": + version "3.4.14" + resolved "https://registry.yarnpkg.com/@loaders.gl/xml/-/xml-3.4.14.tgz#8bfdbed0440cabdc891f152c80b05128cb019d24" + integrity sha512-SNMGOHz4p8Cw+M6kxXhFEjXdNddJPOZY1rzNmRq7NYdGQlQYYeJdqV5HWzHx9BkoQYyrDXkrweGN0mY9QxCfeA== + dependencies: + "@babel/runtime" "^7.3.1" + "@loaders.gl/loader-utils" "3.4.14" + "@loaders.gl/schema" "3.4.14" + fast-xml-parser "^4.2.5" + "@loaders.gl/zip@4.0.0-beta.2": version "4.0.0-beta.2" resolved "https://registry.yarnpkg.com/@loaders.gl/zip/-/zip-4.0.0-beta.2.tgz#0c641d49e1068e13d2f37bc90529cc791ed123dd" @@ -2447,100 +2439,95 @@ jszip "^3.1.5" md5 "^2.3.0" -"@luma.gl/constants@8.5.18", "@luma.gl/constants@^8.5.14", "@luma.gl/constants@^8.5.4": +"@luma.gl/constants@8.5.21", "@luma.gl/constants@^8.5.21": + version "8.5.21" + resolved "https://registry.yarnpkg.com/@luma.gl/constants/-/constants-8.5.21.tgz#81825e9bd9bdf4a9449bcface8b504389f65f634" + integrity sha512-aJxayGxTT+IRd1vfpcgD/cKSCiVJjBNiuiChS96VulrmCvkzUOLvYXr42y5qKB4RyR7vOIda5uQprNzoHrhQAA== + +"@luma.gl/constants@^8.5.4": version "8.5.18" resolved "https://registry.yarnpkg.com/@luma.gl/constants/-/constants-8.5.18.tgz#f18886dfb1407225cd18cb792e490219f91eb3d2" integrity sha512-lQLGAlroQaeJkAUwrb1fRiHlMBP9/ukyjnZ1QlYgXYyeC7/9XhLx4rqBlOzQ2sxcTHHwi73nHD0P2XmVuAccBg== -"@luma.gl/core@^8.5.14": - version "8.5.18" - resolved "https://registry.yarnpkg.com/@luma.gl/core/-/core-8.5.18.tgz#622a71746df23ed262e52dca613de07146e68513" - integrity sha512-XvxE2WE9jFEweJftczQ4QPd8FD23H8mWJoQej7llnyta0Xqb18Cx2VOzuyQ4uN7Uab42YkwXTu25uAq0SdAehA== +"@luma.gl/core@^8.5.21": + version "8.5.21" + resolved "https://registry.yarnpkg.com/@luma.gl/core/-/core-8.5.21.tgz#dc630f1ea18900287ac8da60724d0d8f783b31b1" + integrity sha512-11jQJQEMoR/IN2oIsd4zFxiQJk6FE+xgVIMUcsCTBuzafTtQZ8Po9df8mt+MVewpDyBlTVs6g8nxHRH4np1ukA== dependencies: "@babel/runtime" "^7.0.0" - "@luma.gl/constants" "8.5.18" - "@luma.gl/engine" "8.5.18" - "@luma.gl/gltools" "8.5.18" - "@luma.gl/shadertools" "8.5.18" - "@luma.gl/webgl" "8.5.18" + "@luma.gl/constants" "8.5.21" + "@luma.gl/engine" "8.5.21" + "@luma.gl/gltools" "8.5.21" + "@luma.gl/shadertools" "8.5.21" + "@luma.gl/webgl" "8.5.21" -"@luma.gl/engine@8.5.18": - version "8.5.18" - resolved "https://registry.yarnpkg.com/@luma.gl/engine/-/engine-8.5.18.tgz#78fda10cbd4a576ea04160888e0b4b5003471b18" - integrity sha512-hLdtEPk3yt8ikL3g9qVc5FuMPMdhnj1ykPgmG6Mh4lRlCProgGSlwqWuAkzPYwYqIBqKlPNMv8DavRfsKAKc3g== +"@luma.gl/engine@8.5.21": + version "8.5.21" + resolved "https://registry.yarnpkg.com/@luma.gl/engine/-/engine-8.5.21.tgz#bc8e55371fb95e33fec195c08abf35598c55da42" + integrity sha512-IG3WQSKXFNUEs8QG7ZjHtGiOtsakUu+BAxtJ6997A6/F06yynZ44tPe5NU70jG9Yfu3kV0LykPZg7hO3vXZDiA== dependencies: "@babel/runtime" "^7.0.0" - "@luma.gl/constants" "8.5.18" - "@luma.gl/gltools" "8.5.18" - "@luma.gl/shadertools" "8.5.18" - "@luma.gl/webgl" "8.5.18" + "@luma.gl/constants" "8.5.21" + "@luma.gl/gltools" "8.5.21" + "@luma.gl/shadertools" "8.5.21" + "@luma.gl/webgl" "8.5.21" "@math.gl/core" "^3.5.0" "@probe.gl/env" "^3.5.0" "@probe.gl/stats" "^3.5.0" "@types/offscreencanvas" "^2019.7.0" -"@luma.gl/experimental@^8.5.14": - version "8.5.18" - resolved "https://registry.yarnpkg.com/@luma.gl/experimental/-/experimental-8.5.18.tgz#6162bac53e3b96f9f2662ee5f17683d36f1ff60a" - integrity sha512-Bw8mwO3NVYGwzYr1Edl4LVbT7JORIpymdXpmmoqP9SpWAh5HJmNSS8wt1FDaQGVCgSA/5QpmmZb1NjIKX4B40g== +"@luma.gl/experimental@^8.5.21": + version "8.5.21" + resolved "https://registry.yarnpkg.com/@luma.gl/experimental/-/experimental-8.5.21.tgz#1ab5ad084202ae3c05e16b7e4b430c791f86a50d" + integrity sha512-uFKPChGofyihOKxtqJy78QCQCDFnuMTK4QHrUX/qiTnvFSO8BgtTUevKvWGN9lBvq+uDD0lSieeF9yBzhQfAzw== dependencies: - "@luma.gl/constants" "8.5.18" + "@luma.gl/constants" "8.5.21" "@math.gl/core" "^3.5.0" earcut "^2.0.6" -"@luma.gl/gltools@8.5.18": - version "8.5.18" - resolved "https://registry.yarnpkg.com/@luma.gl/gltools/-/gltools-8.5.18.tgz#df8501c01ad6c3b114a5e5d2e6526546df009d40" - integrity sha512-AnZ8fxsJz/wRdUJazsFvTXbh8ypYX9rATPJj8YlDv08DGGFTQiq8MurzbEjXaEYshAu5w9rXd22nQXkQziUhmQ== +"@luma.gl/gltools@8.5.21": + version "8.5.21" + resolved "https://registry.yarnpkg.com/@luma.gl/gltools/-/gltools-8.5.21.tgz#1077305a30712f20cd904c2e4cbe5b9263b7d138" + integrity sha512-6qZ0LaT2Mxa4AJT5F44TFoaziokYiHUwO45vnM/NYUOIu9xevcmS6VtToawytMEACGL6PDeDyVqP3Y80SDzq5g== dependencies: "@babel/runtime" "^7.0.0" - "@luma.gl/constants" "8.5.18" + "@luma.gl/constants" "8.5.21" "@probe.gl/env" "^3.5.0" "@probe.gl/log" "^3.5.0" "@types/offscreencanvas" "^2019.7.0" -"@luma.gl/shadertools@8.5.18", "@luma.gl/shadertools@^8.5.14": - version "8.5.18" - resolved "https://registry.yarnpkg.com/@luma.gl/shadertools/-/shadertools-8.5.18.tgz#2007c7173b95c552910fdf722876e25d8f2385a3" - integrity sha512-orkdnlVLB8AO4yf9jXXZqEG/UuwVg/v3Gmo4/F2vdrwkUMN+wUZFUdhssDGEGWvuauZWK9Mbz8XrxC0gmLbWzw== +"@luma.gl/shadertools@8.5.21", "@luma.gl/shadertools@^8.5.21": + version "8.5.21" + resolved "https://registry.yarnpkg.com/@luma.gl/shadertools/-/shadertools-8.5.21.tgz#9a8e087e39e34f055f9fdda9fac527c04f637b4e" + integrity sha512-WQah7yFDJ8cNCLPYpIm3r0wSlXLvjoA279fcknmATvvkW3/i8PcCJ/nYEBJO3hHEwwMQxD16+YZu/uwGiifLMg== dependencies: "@babel/runtime" "^7.0.0" "@math.gl/core" "^3.5.0" -"@luma.gl/webgl@8.5.18": - version "8.5.18" - resolved "https://registry.yarnpkg.com/@luma.gl/webgl/-/webgl-8.5.18.tgz#fe6c06fcc77e6559ff2532e47e589918ec939b3c" - integrity sha512-8pRMq4olLzEv7ToDtCagGDklkIu1iFFBEXT4Rh11ohrfUiDAPfGz5hJrr3m0XtsVfS1CQ5QPWN2tQclmXOL+cQ== +"@luma.gl/webgl@8.5.21", "@luma.gl/webgl@^8.5.21": + version "8.5.21" + resolved "https://registry.yarnpkg.com/@luma.gl/webgl/-/webgl-8.5.21.tgz#fe67bf19a41231840ca677ae702969c7a9a5d7a0" + integrity sha512-ZVLO4W5UuaOlzZIwmFWhnmZ1gYoU97a+heMqxLrSSmCUAsSu3ZETUex9gOmzdM1WWxcdWaa3M68rvKCNEgwz0Q== dependencies: "@babel/runtime" "^7.0.0" - "@luma.gl/constants" "8.5.18" - "@luma.gl/gltools" "8.5.18" + "@luma.gl/constants" "8.5.21" + "@luma.gl/gltools" "8.5.21" "@probe.gl/env" "^3.5.0" "@probe.gl/stats" "^3.5.0" -"@mapbox/geojson-rewind@^0.5.0": - version "0.5.1" - resolved "https://registry.yarnpkg.com/@mapbox/geojson-rewind/-/geojson-rewind-0.5.1.tgz#adbe16dc683eb40e90934c51a5e28c7bbf44f4e1" - integrity sha512-eL7fMmfTBKjrb+VFHXCGv9Ot0zc3C0U+CwXo1IrP+EPwDczLoXv34Tgq3y+2mPSFNVUXgU42ILWJTC7145KPTA== +"@mapbox/geojson-rewind@^0.5.2": + version "0.5.2" + resolved "https://registry.yarnpkg.com/@mapbox/geojson-rewind/-/geojson-rewind-0.5.2.tgz#591a5d71a9cd1da1a0bf3420b3bea31b0fc7946a" + integrity sha512-tJaT+RbYGJYStt7wI3cq4Nl4SXxG8W7JDG5DMJu97V25RnbNg3QtQtf+KD+VLjNpWKYsRvXDNmNrBgEETr1ifA== dependencies: get-stream "^6.0.1" - minimist "^1.2.5" - -"@mapbox/geojson-types@^1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@mapbox/geojson-types/-/geojson-types-1.0.2.tgz#9aecf642cb00eab1080a57c4f949a65b4a5846d6" - integrity sha512-e9EBqHHv3EORHrSfbR9DqecPNn+AmuAoQxV6aL8Xu30bJMJR1o8PZLZzpk1Wq7/NfCbuhmakHTPYRhoqLsXRnw== + minimist "^1.2.6" -"@mapbox/jsonlint-lines-primitives@^2.0.2": +"@mapbox/jsonlint-lines-primitives@^2.0.2", "@mapbox/jsonlint-lines-primitives@~2.0.2": version "2.0.2" resolved "https://registry.yarnpkg.com/@mapbox/jsonlint-lines-primitives/-/jsonlint-lines-primitives-2.0.2.tgz#ce56e539f83552b58d10d672ea4d6fc9adc7b234" integrity sha1-zlblOfg1UrWNENZy6k1vya3HsjQ= -"@mapbox/mapbox-gl-supported@^1.5.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@mapbox/mapbox-gl-supported/-/mapbox-gl-supported-1.5.0.tgz#f60b6a55a5d8e5ee908347d2ce4250b15103dc8e" - integrity sha512-/PT1P6DNf7vjEEiPkVIRJkvibbqWtqnyGaBz3nfRdcxclNSnSdaLU5tfAgcD7I8Yt5i+L19s406YLl1koLnLbg== - "@mapbox/martini@^0.2.0": version "0.2.0" resolved "https://registry.yarnpkg.com/@mapbox/martini/-/martini-0.2.0.tgz#1af70211fbe994abf26e37f1388ca69c02cd43b4" @@ -2551,15 +2538,15 @@ resolved "https://registry.yarnpkg.com/@mapbox/point-geometry/-/point-geometry-0.1.0.tgz#8a83f9335c7860effa2eeeca254332aa0aeed8f2" integrity sha1-ioP5M1x4YO/6Lu7KJUMyqgru2PI= -"@mapbox/tiny-sdf@^1.1.0", "@mapbox/tiny-sdf@^1.1.1": - version "1.2.5" - resolved "https://registry.yarnpkg.com/@mapbox/tiny-sdf/-/tiny-sdf-1.2.5.tgz#424c620a96442b20402552be70a7f62a8407cc59" - integrity sha512-cD8A/zJlm6fdJOk6DqPUV8mcpyJkRz2x2R+/fYcWDYG3oWbG7/L7Yl/WqQ1VZCjnL9OTIMAn6c+BC5Eru4sQEw== +"@mapbox/tiny-sdf@^2.0.5", "@mapbox/tiny-sdf@^2.0.6": + version "2.0.6" + resolved "https://registry.yarnpkg.com/@mapbox/tiny-sdf/-/tiny-sdf-2.0.6.tgz#9a1d33e5018093e88f6a4df2343e886056287282" + integrity sha512-qMqa27TLw+ZQz5Jk+RcwZGH7BQf5G/TrutJhspsca/3SHwmgKQ1iq+d3Jxz5oysPVYTGP6aXxCo5Lk9Er6YBAA== -"@mapbox/unitbezier@^0.0.0": - version "0.0.0" - resolved "https://registry.yarnpkg.com/@mapbox/unitbezier/-/unitbezier-0.0.0.tgz#15651bd553a67b8581fb398810c98ad86a34524e" - integrity sha1-FWUb1VOme4WB+zmIEMmK2Go0Uk4= +"@mapbox/unitbezier@^0.0.1": + version "0.0.1" + resolved "https://registry.yarnpkg.com/@mapbox/unitbezier/-/unitbezier-0.0.1.tgz#d32deb66c7177e9e9dfc3bbd697083e2e657ff01" + integrity sha512-nMkuDXFv60aBr9soUG5q+GvZYL+2KZHVvsqFCzqnkGEf46U2fvmytHaEVc1/YZbiLn8X+eR3QzX1+dwDO1lxlw== "@mapbox/vector-tile@^1.3.1": version "1.3.1" @@ -2573,6 +2560,18 @@ resolved "https://registry.yarnpkg.com/@mapbox/whoots-js/-/whoots-js-3.1.0.tgz#497c67a1cef50d1a2459ba60f315e448d2ad87fe" integrity sha512-Es6WcD0nO5l+2BOQS4uLfNPYQaNDfbot3X1XUoloz+x0mPDS3eeORZJl06HXjwBG1fOGwCRnzK88LMdxKRrd6Q== +"@maplibre/maplibre-gl-style-spec@^19.2.1", "@maplibre/maplibre-gl-style-spec@^19.3.3": + version "19.3.3" + resolved "https://registry.yarnpkg.com/@maplibre/maplibre-gl-style-spec/-/maplibre-gl-style-spec-19.3.3.tgz#a106248bd2e25e77c963a362aeaf630e00f924e9" + integrity sha512-cOZZOVhDSulgK0meTsTkmNXb1ahVvmTmWmfx9gRBwc6hq98wS9JP35ESIoNq3xqEan+UN+gn8187Z6E4NKhLsw== + dependencies: + "@mapbox/jsonlint-lines-primitives" "~2.0.2" + "@mapbox/unitbezier" "^0.0.1" + json-stringify-pretty-compact "^3.0.0" + minimist "^1.2.8" + rw "^1.3.3" + sort-object "^3.0.3" + "@math.gl/core@3.5.7", "@math.gl/core@^3.5.0", "@math.gl/core@^3.5.1": version "3.5.7" resolved "https://registry.yarnpkg.com/@math.gl/core/-/core-3.5.7.tgz#41145f214c36f20a6bf32e4c25551e97c6828e99" @@ -2581,16 +2580,7 @@ "@babel/runtime" "^7.12.0" gl-matrix "~3.3.0" -"@math.gl/core@3.6.1", "@math.gl/core@^3.6.0": - version "3.6.1" - resolved "https://registry.yarnpkg.com/@math.gl/core/-/core-3.6.1.tgz#1472ba744b91db1ef8fc59e79aef446a70fef22d" - integrity sha512-arWJyTIdg9EG2xPze0T569wcWsmMHswh5a194zAO86JmDxhPKe/JUU41s0D9OTipq3obuLz/OVayZJEpDB4qcw== - dependencies: - "@babel/runtime" "^7.12.0" - "@math.gl/types" "3.6.1" - gl-matrix "^3.4.0" - -"@math.gl/core@3.6.3": +"@math.gl/core@3.6.3", "@math.gl/core@^3.6.2": version "3.6.3" resolved "https://registry.yarnpkg.com/@math.gl/core/-/core-3.6.3.tgz#a6bf796ed421093099749d609de8d99a3ac20a53" integrity sha512-jBABmDkj5uuuE0dTDmwwss7Cup5ZwQ6Qb7h1pgvtkEutTrhkcv8SuItQNXmF45494yIHeoGue08NlyeY6wxq2A== @@ -2608,13 +2598,13 @@ "@math.gl/core" "3.5.7" gl-matrix "~3.3.0" -"@math.gl/culling@^3.6.0": - version "3.6.1" - resolved "https://registry.yarnpkg.com/@math.gl/culling/-/culling-3.6.1.tgz#e50b082b9d8532a8920641a11a0d338812dbc1e1" - integrity sha512-Goqf5QvDUQd6o3Hwf9GRV8KjcpEZedODxPFZf1I1asB5f62ksPL2ArlyrNmHLoeGVL+KBumuoiIe4j8CYeafsQ== +"@math.gl/culling@^3.6.2": + version "3.6.3" + resolved "https://registry.yarnpkg.com/@math.gl/culling/-/culling-3.6.3.tgz#91cdfa496748e8873a2e6261415a27a27b6af5f2" + integrity sha512-3UERXHbaPlM6pnTk2MI7LeQ5CoelDZzDzghTTcv+HdQCZsT/EOEuEdYimETHtSxiyiOmsX2Un65UBLYT/rbKZg== dependencies: "@babel/runtime" "^7.12.0" - "@math.gl/core" "3.6.1" + "@math.gl/core" "3.6.3" gl-matrix "^3.4.0" "@math.gl/geospatial@^3.5.1": @@ -2626,19 +2616,12 @@ "@math.gl/core" "3.5.7" gl-matrix "~3.3.0" -"@math.gl/polygon@^3.5.1": - version "3.5.7" - resolved "https://registry.yarnpkg.com/@math.gl/polygon/-/polygon-3.5.7.tgz#6ddab215552919a2f784e8ea746fe582475c1e33" - integrity sha512-fTi9Vfs7+LQ5Cn5ABSp0i+rfRec2fFuPhUE+Xpvg3dELQP+YMSw7FeR5SvUBgt3UY86qLmrkmxz3WwffcJA/eg== - dependencies: - "@math.gl/core" "3.5.7" - -"@math.gl/polygon@^3.6.0": - version "3.6.1" - resolved "https://registry.yarnpkg.com/@math.gl/polygon/-/polygon-3.6.1.tgz#d09c3231856c237e271e4d3ac5f6394b500a57b6" - integrity sha512-DS8Xxo+cadPl1YBWURFWIYGC+baiwezz4zzqAZtEn5li2dnVDbt73uiECdTBdmjXhJUiMxz1VzkF7r7Hcz10TA== +"@math.gl/polygon@^3.5.1", "@math.gl/polygon@^3.6.2": + version "3.6.3" + resolved "https://registry.yarnpkg.com/@math.gl/polygon/-/polygon-3.6.3.tgz#0c19c0b059cedde1cd760cc3796e9180f75bcbde" + integrity sha512-FivQ1ZnYcAss1wVifOkHP/ZnlfQy1IL/769uzNtiHxwUbW0kZG3yyOZ9I7fwyzR5Hvqt3ErJKHjSYZr0uVlz5g== dependencies: - "@math.gl/core" "3.6.1" + "@math.gl/core" "3.6.3" "@math.gl/proj4@^3.6.3": version "3.6.3" @@ -2650,24 +2633,19 @@ "@types/proj4" "^2.5.0" proj4 "2.6.2" -"@math.gl/sun@^3.6.0": - version "3.6.1" - resolved "https://registry.yarnpkg.com/@math.gl/sun/-/sun-3.6.1.tgz#d49a8cfc02e5414af87c3b69686869a954169462" - integrity sha512-IWeiUPIsr4ZmZxKUA5uE/PA3i/lZByzWHCGxFBXRJjVxCrHJsWZOxnVtwbPOT7nypSb01O3j6AXVq9RhUMMfzw== +"@math.gl/sun@^3.6.2": + version "3.6.3" + resolved "https://registry.yarnpkg.com/@math.gl/sun/-/sun-3.6.3.tgz#30c15612313b56349c568f21f39c0e0f0e77b2df" + integrity sha512-mrx6CGYYeTNSQttvcw0KVUy+35YDmnjMqpO/o0t06Vcghrt0HNruB/ScRgUSbJrgkbOg1Vcqm23HBd++clzQzw== dependencies: "@babel/runtime" "^7.12.0" -"@math.gl/types@3.6.1": - version "3.6.1" - resolved "https://registry.yarnpkg.com/@math.gl/types/-/types-3.6.1.tgz#d4f8f0ca31473866ab71dee10cfa919a9ac827c2" - integrity sha512-G2KegmrstjUsLLtm+zj6lfxEB42s6JVDmIY3kU08HOyWHJTgvbZ2Z1MsB6z8TeKfX1QH8M/2WlemRwUS+3cj8w== - "@math.gl/types@3.6.3": version "3.6.3" resolved "https://registry.yarnpkg.com/@math.gl/types/-/types-3.6.3.tgz#9fa9866feabcbb76de107d78ff3a89c0243ac374" integrity sha512-3uWLVXHY3jQxsXCr/UCNPSc2BG0hNUljhmOBt9l+lNFDp7zHgm0cK2Tw4kj2XfkJy4TgwZTBGwRDQgWEbLbdTA== -"@math.gl/web-mercator@^3.5.1", "@math.gl/web-mercator@^3.5.5": +"@math.gl/web-mercator@^3.5.1": version "3.5.7" resolved "https://registry.yarnpkg.com/@math.gl/web-mercator/-/web-mercator-3.5.7.tgz#180a1057ea622bd857c6931f67268c2e98f174c6" integrity sha512-i0w6AcV2b5+yeUQOA/KdnnzTYMUZvEKzHbbxI+ZyCuFs3p9S/IUt/EWVw4KGGOjVbf3UrGFlWSM70Th+0KyrsA== @@ -2675,10 +2653,10 @@ "@babel/runtime" "^7.12.0" gl-matrix "~3.3.0" -"@math.gl/web-mercator@^3.6.0": - version "3.6.1" - resolved "https://registry.yarnpkg.com/@math.gl/web-mercator/-/web-mercator-3.6.1.tgz#f6a62bb92167a7b0ae9017d5a2ba5eb866cd3850" - integrity sha512-nB/sJYAZpjWOpdQ9IMWXcAITM57huILBdEWzfumqgZ0ay49I4Y0yaFgkjgd/52gfwpY8TDoaR8eRxIQ7c1tx7Q== +"@math.gl/web-mercator@^3.6.2": + version "3.6.3" + resolved "https://registry.yarnpkg.com/@math.gl/web-mercator/-/web-mercator-3.6.3.tgz#ef91168e030eecffc788618d686e8a6c1d7a0bf8" + integrity sha512-UVrkSOs02YLehKaehrxhAejYMurehIHPfFQvPFZmdJHglHOU4V2cCUApTVEwOksvCp161ypEqVp+9H6mGhTTcw== dependencies: "@babel/runtime" "^7.12.0" gl-matrix "^3.4.0" @@ -2718,7 +2696,7 @@ dependencies: "@babel/runtime" "^7.0.0" -"@probe.gl/log@3.5.0", "@probe.gl/log@^3.5.0": +"@probe.gl/log@^3.5.0": version "3.5.0" resolved "https://registry.yarnpkg.com/@probe.gl/log/-/log-3.5.0.tgz#6589822ab771eadf77787ffc6ecf73e59d181c64" integrity sha512-nW/qz2X1xY08WU/TsmJP6/6IPNcaY5fS/vLjpC4ahJuE2Mezga4hGM/R2X5JWE/nkPc+BsC5GnAnD13rwAxS7g== @@ -2726,7 +2704,7 @@ "@babel/runtime" "^7.0.0" "@probe.gl/env" "3.5.0" -"@probe.gl/log@^4.0.2", "@probe.gl/log@^4.0.4": +"@probe.gl/log@^4.0.1", "@probe.gl/log@^4.0.2", "@probe.gl/log@^4.0.4": version "4.0.4" resolved "https://registry.yarnpkg.com/@probe.gl/log/-/log-4.0.4.tgz#e42d1d0e22981c4010521c350cad2305bce02976" integrity sha512-WpmXl6njlBMwrm8HBh/b4kSp/xnY1VVmeT4PWUKF+RkVbFuKQbsU11dA1IxoMd7gSY+5DGIwxGfAv1H5OMzA4A== @@ -2734,14 +2712,14 @@ "@babel/runtime" "^7.0.0" "@probe.gl/env" "4.0.4" -"@probe.gl/stats@3.5.0", "@probe.gl/stats@^3.5.0": +"@probe.gl/stats@^3.5.0": version "3.5.0" resolved "https://registry.yarnpkg.com/@probe.gl/stats/-/stats-3.5.0.tgz#774495772f06e898aae28c1d315c9edac07f3425" integrity sha512-IH2M+F3c8HR1DTroBARePUFG7wIewumtKA0UFqx51Z7S4hKrD60wFbpMmg0AcF4FvHAXMBoC+kYi1UKW9XbAOw== dependencies: "@babel/runtime" "^7.0.0" -"@probe.gl/stats@^4.0.2", "@probe.gl/stats@^4.0.4": +"@probe.gl/stats@^4.0.1", "@probe.gl/stats@^4.0.2", "@probe.gl/stats@^4.0.4": version "4.0.4" resolved "https://registry.yarnpkg.com/@probe.gl/stats/-/stats-4.0.4.tgz#b33a47bf192951d0789dfd2044b295c3709386bd" integrity sha512-SDuSY/D4yDL6LQDa69l/GCcnZLRiGYdyvYkxWb0CgnzTPdPrcdrzGkzkvpC3zsA4fEFw2smlDje370QGHwlisg== @@ -2970,6 +2948,51 @@ resolved "https://registry.yarnpkg.com/@trysound/sax/-/sax-0.2.0.tgz#cccaab758af56761eb7bf37af6f03f326dd798ad" integrity sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA== +"@turf/boolean-clockwise@^5.1.5": + version "5.1.5" + resolved "https://registry.yarnpkg.com/@turf/boolean-clockwise/-/boolean-clockwise-5.1.5.tgz#3302b7dac62c5e291a0789e29af7283387fa9deb" + integrity sha512-FqbmEEOJ4rU4/2t7FKx0HUWmjFEVqR+NJrFP7ymGSjja2SQ7Q91nnBihGuT+yuHHl6ElMjQ3ttsB/eTmyCycxA== + dependencies: + "@turf/helpers" "^5.1.5" + "@turf/invariant" "^5.1.5" + +"@turf/clone@^5.1.5": + version "5.1.5" + resolved "https://registry.yarnpkg.com/@turf/clone/-/clone-5.1.5.tgz#253e8d35477181976e33adfab50a0f02a7f0e367" + integrity sha512-//pITsQ8xUdcQ9pVb4JqXiSqG4dos5Q9N4sYFoWghX21tfOV2dhc5TGqYOhnHrQS7RiKQL1vQ48kIK34gQ5oRg== + dependencies: + "@turf/helpers" "^5.1.5" + +"@turf/helpers@^5.1.5": + version "5.1.5" + resolved "https://registry.yarnpkg.com/@turf/helpers/-/helpers-5.1.5.tgz#153405227ab933d004a5bb9641a9ed999fcbe0cf" + integrity sha512-/lF+JR+qNDHZ8bF9d+Cp58nxtZWJ3sqFe6n3u3Vpj+/0cqkjk4nXKYBSY0azm+GIYB5mWKxUXvuP/m0ZnKj1bw== + +"@turf/invariant@^5.1.5": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@turf/invariant/-/invariant-5.2.0.tgz#f0150ff7290b38577b73d088b7932c1ee0aa90a7" + integrity sha512-28RCBGvCYsajVkw2EydpzLdcYyhSA77LovuOvgCJplJWaNVyJYH6BOR3HR9w50MEkPqb/Vc/jdo6I6ermlRtQA== + dependencies: + "@turf/helpers" "^5.1.5" + +"@turf/meta@^5.1.5": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@turf/meta/-/meta-5.2.0.tgz#3b1ad485ee0c3b0b1775132a32c384d53e4ba53d" + integrity sha512-ZjQ3Ii62X9FjnK4hhdsbT+64AYRpaI8XMBMcyftEOGSmPMUVnkbvuv3C9geuElAXfQU7Zk1oWGOcrGOD9zr78Q== + dependencies: + "@turf/helpers" "^5.1.5" + +"@turf/rewind@^5.1.5": + version "5.1.5" + resolved "https://registry.yarnpkg.com/@turf/rewind/-/rewind-5.1.5.tgz#9ea3db4a68b73c1fd1dd11f57631b143cfefa1c9" + integrity sha512-Gdem7JXNu+G4hMllQHXRFRihJl3+pNl7qY+l4qhQFxq+hiU1cQoVFnyoleIqWKIrdK/i2YubaSwc3SCM7N5mMw== + dependencies: + "@turf/boolean-clockwise" "^5.1.5" + "@turf/clone" "^5.1.5" + "@turf/helpers" "^5.1.5" + "@turf/invariant" "^5.1.5" + "@turf/meta" "^5.1.5" + "@types/aria-query@^4.2.0": version "4.2.2" resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-4.2.2.tgz#ed4e0ad92306a704f9fb132a0cfcf77486dbe2bc" @@ -3030,6 +3053,16 @@ dependencies: "@types/node" "*" +"@types/command-line-args@5.2.0": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@types/command-line-args/-/command-line-args-5.2.0.tgz#adbb77980a1cc376bb208e3f4142e907410430f6" + integrity sha512-UuKzKpJJ/Ief6ufIaIzr3A/0XnluX7RvFgwkV89Yzvm77wCh1kFaFmqN8XEnGcN62EuHdedQjEMb8mYxFLGPyA== + +"@types/command-line-usage@5.0.2": + version "5.0.2" + resolved "https://registry.yarnpkg.com/@types/command-line-usage/-/command-line-usage-5.0.2.tgz#ba5e3f6ae5a2009d466679cc431b50635bf1a064" + integrity sha512-n7RlEEJ+4x4TS7ZQddTmNSxP+zziEG0TNsMfiRIxcIVXt71ENJ9ojeXmGO3wPoTdn7pJcU2xc3CJYMktNT6DPg== + "@types/connect-history-api-fallback@^1.3.5": version "1.3.5" resolved "https://registry.yarnpkg.com/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.3.5.tgz#d1f7a8a09d0ed5a57aee5ae9c18ab9b803205dae" @@ -3097,16 +3130,16 @@ "@types/qs" "*" "@types/serve-static" "*" -"@types/flatbuffers@^1.10.0": - version "1.10.0" - resolved "https://registry.yarnpkg.com/@types/flatbuffers/-/flatbuffers-1.10.0.tgz#aa74e30ffdc86445f2f060e1808fc9d56b5603ba" - integrity sha512-7btbphLrKvo5yl/5CC2OCxUSMx1wV1wvGT1qDXkSt7yi00/YW7E8k6qzXqJHsp+WU0eoG7r6MTQQXI9lIvd0qA== - -"@types/geojson@*", "@types/geojson@^7946.0.7", "@types/geojson@^7946.0.8": +"@types/geojson@*", "@types/geojson@^7946.0.7": version "7946.0.8" resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-7946.0.8.tgz#30744afdb385e2945e22f3b033f897f76b1f12ca" integrity sha512-1rkryxURpr6aWP7R786/UQOkJ3PcpQiWkAXBmdWc7ryFWqN6a4xfK7BtjXvFBKO9LjQ+MWQSWxYeZX1OApnArA== +"@types/geojson@^7946.0.12", "@types/geojson@^7946.0.8": + version "7946.0.12" + resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-7946.0.12.tgz#0307536218d32e6b970bccd1d148b9c4e5b6f10d" + integrity sha512-uK2z1ZHJyC0nQRbuovXFt4mzXDwf27vQeUWNhfKGwRcWW429GOhP8HxUHlM6TLH4bzmlv/HlEjpvJh3JfmGsAA== + "@types/graceful-fs@^4.1.2": version "4.1.5" resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.5.tgz#21ffba0d98da4350db64891f92a9e5db3cdb4e15" @@ -3115,9 +3148,9 @@ "@types/node" "*" "@types/hammerjs@^2.0.41": - version "2.0.41" - resolved "https://registry.yarnpkg.com/@types/hammerjs/-/hammerjs-2.0.41.tgz#f6ecf57d1b12d2befcce00e928a6a097c22980aa" - integrity sha512-ewXv/ceBaJprikMcxCmWU1FKyMAQ2X7a9Gtmzw8fcg2kIePI1crERDM818W+XYrxqdBBOdlf2rm137bU+BltCA== + version "2.0.43" + resolved "https://registry.yarnpkg.com/@types/hammerjs/-/hammerjs-2.0.43.tgz#8660dd1e0e5fd979395e2f999e670cdb9484d1e9" + integrity sha512-wqxfwHk83RS7+6OpytGdo5wqkqtvx+bGaIs1Rwm5NrtQHUfL4OgWs/5p0OipmjmT+fexePh37Ek+mqIpdNjQKA== "@types/hoist-non-react-statics@*", "@types/hoist-non-react-statics@^3.3.1": version "3.3.1" @@ -3179,19 +3212,26 @@ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d" integrity sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ== -"@types/mapbox-gl@^2.0.3": - version "2.6.0" - resolved "https://registry.yarnpkg.com/@types/mapbox-gl/-/mapbox-gl-2.6.0.tgz#f9e8e963d5a11eba9d914d95ef8a00d015ca8732" - integrity sha512-lHdITzC0IVn9+Pq6WFkkK0N6rUKIqxsdrNeixiQdvROFn2Aeu3TDvhpuag1IdengL5WGGRuEhK6m6HB916ReLw== +"@types/mapbox-gl@>=1.0.0": + version "2.7.17" + resolved "https://registry.yarnpkg.com/@types/mapbox-gl/-/mapbox-gl-2.7.17.tgz#cba3559ccd041b32d492d14d06c1f1fedba0a2cb" + integrity sha512-5lDO2W6glPCqiRuqKh0a7MPOwnVt1/KWcYnxsL3z5rmjuOcFdHEa+KzUwCzqsAlbAegIIhgQiREZzJ9o1ze1gQ== dependencies: "@types/geojson" "*" -"@types/mapbox-gl@^2.6.3": - version "2.7.1" - resolved "https://registry.yarnpkg.com/@types/mapbox-gl/-/mapbox-gl-2.7.1.tgz#d848793a3a350bdec48043b9fcf68c1b87733348" - integrity sha512-qr2cWQIJ12TMQg6cYc/FELgwXgcuLlDxcFyQH2EMdr3R8Mg5PFQUNZP5M4ZUanRVwJdQ10pMEVRTAjW9HqLdzg== +"@types/mapbox__point-geometry@*", "@types/mapbox__point-geometry@^0.1.3": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@types/mapbox__point-geometry/-/mapbox__point-geometry-0.1.3.tgz#3050f58fcdcc9da96998655268d477ea266dbe76" + integrity sha512-2W46IOXlu7vC8m3+M5rDqSnuY22GFxxx3xhkoyqyPWrD+eP2iAwNst0A1+umLYjCTJMJTSpiofphn9h9k+Kw+w== + +"@types/mapbox__vector-tile@^1.3.3": + version "1.3.3" + resolved "https://registry.yarnpkg.com/@types/mapbox__vector-tile/-/mapbox__vector-tile-1.3.3.tgz#f8bf33d91f9951c6090dbd454d4e33626f5107cc" + integrity sha512-d263B3KCQtXKVZMHpMJrEW5EeLBsQ8jvAS9nhpUKC5hHIlQaACG9PWkW8qxEeNuceo9120AwPjeS91uNa4ltqA== dependencies: "@types/geojson" "*" + "@types/mapbox__point-geometry" "*" + "@types/pbf" "*" "@types/mime@^1": version "1.3.2" @@ -3203,16 +3243,21 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.18.tgz#3b4fed5cfb58010e3a2be4b6e74615e4847f1074" integrity sha512-eKj4f/BsN/qcculZiRSujogjvp5O/k4lOW5m35NopjZM/QwLOR075a8pJW5hD+Rtdm2DaCVPENS6KtSQnUD6BA== -"@types/node@^14.14.37": - version "14.18.12" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.12.tgz#0d4557fd3b94497d793efd4e7d92df2f83b4ef24" - integrity sha512-q4jlIR71hUpWTnGhXWcakgkZeHa3CCjcQcnuzU8M891BAWA2jHiziiWEPEkdS5pFsz7H9HJiy8BrK7tBRNrY7A== +"@types/node@20.3.0": + version "20.3.0" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.3.0.tgz#719498898d5defab83c3560f45d8498f58d11938" + integrity sha512-cumHmIAf6On83X7yP+LrsEyUOf/YlociZelmpRYaGFydoaPdxdt80MAbu6vWerQT2COCp2nPvHdsbD7tHn/YlQ== "@types/offscreencanvas@^2019.7.0": version "2019.7.0" resolved "https://registry.yarnpkg.com/@types/offscreencanvas/-/offscreencanvas-2019.7.0.tgz#e4a932069db47bb3eabeb0b305502d01586fa90d" integrity sha512-PGcyveRIpL1XIqK8eBsmRBt76eFgtzuPiSTyKHZxnGemp2yzGzWpjYKAfK3wIMiU7eH+851yEpiuP8JZerTmWg== +"@types/pad-left@2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@types/pad-left/-/pad-left-2.1.1.tgz#17d906fc75804e1cc722da73623f1d978f16a137" + integrity sha512-Xd22WCRBydkGSApl5Bw0PhAOHKSVjNL3E3AwzKaps96IMraPqy5BvZIsBVK6JLwdybUzjHnuWVwpDd0JjTfHXA== + "@types/pako@^1.0.1": version "1.0.4" resolved "https://registry.yarnpkg.com/@types/pako/-/pako-1.0.4.tgz#b4262aef92680a9331fcdb8420c69cf3dd98d3f3" @@ -3223,6 +3268,11 @@ resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== +"@types/pbf@*", "@types/pbf@^3.0.4": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@types/pbf/-/pbf-3.0.4.tgz#32f8cd8bb2fb53e5870a5d751210d1dcdce23f85" + integrity sha512-SOFlLGZkLbEXJRwcWCqeP/Koyaf/uAqLXHUsdo/nMfjLsNd8kqauwHe9GBOljSmpcHp/LC6kOjo3SidGjNirVA== + "@types/prettier@^2.1.5": version "2.4.4" resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.4.4.tgz#5d9b63132df54d8909fce1c3f8ca260fdd693e17" @@ -3340,6 +3390,13 @@ "@types/react" "*" csstype "^3.0.2" +"@types/supercluster@^7.1.2": + version "7.1.2" + resolved "https://registry.yarnpkg.com/@types/supercluster/-/supercluster-7.1.2.tgz#2391a1b22ef108e37d51d4c8bdea7dc04ebf4bcf" + integrity sha512-qMhofL945Z4njQUuntadexAgPtpiBC014WvVqU70Prj42LC77Xgmz04us7hSMmwjs7KbgAwGBmje+FSOvDbP0Q== + dependencies: + "@types/geojson" "*" + "@types/testing-library__jest-dom@^5.9.1": version "5.14.3" resolved "https://registry.yarnpkg.com/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.3.tgz#ee6c7ffe9f8595882ee7bda8af33ae7b8789ef17" @@ -3347,11 +3404,6 @@ dependencies: "@types/jest" "*" -"@types/text-encoding-utf-8@^1.0.1": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@types/text-encoding-utf-8/-/text-encoding-utf-8-1.0.2.tgz#896e94ce99b653e886a9b925e9dc12c92af7b1ae" - integrity sha512-AQ6zewa0ucLJvtUi5HsErbOFKAcQfRLt9zFLlUOvcXBy2G36a+ZDpCHSGdzJVUD8aNURtIjh9aSjCStNMRCcRQ== - "@types/use-sync-external-store@^0.0.3": version "0.0.3" resolved "https://registry.yarnpkg.com/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz#b6725d5f4af24ace33b36fafd295136e75509f43" @@ -3772,21 +3824,21 @@ anymatch@^3.0.3, anymatch@~3.1.2: normalize-path "^3.0.0" picomatch "^2.0.4" -apache-arrow@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/apache-arrow/-/apache-arrow-4.0.1.tgz#62e58caa46a6a41966478a19c492380c9efb1d66" - integrity sha512-DyF7GXCbSjsw4P5C8b+qW7OnJKa6w9mJI0mhV0+EfZbVZCmhfiF6ffqcnrI/kzBrRqn9hH/Ft9n5+m4DTbBJpg== - dependencies: - "@types/flatbuffers" "^1.10.0" - "@types/node" "^14.14.37" - "@types/text-encoding-utf-8" "^1.0.1" - command-line-args "5.1.1" - command-line-usage "6.1.1" - flatbuffers "1.12.0" +apache-arrow@^13.0.0: + version "13.0.0" + resolved "https://registry.yarnpkg.com/apache-arrow/-/apache-arrow-13.0.0.tgz#8c8c69ca8ec53b804b4e10fe6b57483bda46dfbd" + integrity sha512-3gvCX0GDawWz6KFNC28p65U+zGh/LZ6ZNKWNu74N6CQlKzxeoWHpi4CgEQsgRSEMuyrIIXi1Ea2syja7dwcHvw== + dependencies: + "@types/command-line-args" "5.2.0" + "@types/command-line-usage" "5.0.2" + "@types/node" "20.3.0" + "@types/pad-left" "2.1.1" + command-line-args "5.2.1" + command-line-usage "7.0.1" + flatbuffers "23.5.26" json-bignum "^0.0.3" pad-left "^2.1.0" - text-encoding-utf-8 "^1.0.2" - tslib "^2.2.0" + tslib "^2.5.3" arch@^2.1.1: version "2.2.0" @@ -3820,15 +3872,15 @@ arr-union@^3.1.0: resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= -array-back@^3.0.1: +array-back@^3.0.1, array-back@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/array-back/-/array-back-3.1.0.tgz#b8859d7a508871c9a7b2cf42f99428f65e96bfb0" integrity sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q== -array-back@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/array-back/-/array-back-4.0.2.tgz#8004e999a6274586beeb27342168652fdb89fa1e" - integrity sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg== +array-back@^6.2.2: + version "6.2.2" + resolved "https://registry.yarnpkg.com/array-back/-/array-back-6.2.2.tgz#f567d99e9af88a6d3d2f9dfcc21db6f9ba9fd157" + integrity sha512-gUAZ7HPyb4SJczXAMUXMGAvI976JoK3qEx9v1FTmeYuJj0IBiaKttG1ydtGKdkfqWkIkouke7nG8ufGy77+Cvw== array-flatten@1.1.1: version "1.1.1" @@ -3845,6 +3897,11 @@ array-union@^2.1.0: resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== +assign-symbols@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" + integrity sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw== + async@^2.6.2: version "2.6.3" resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff" @@ -4145,6 +4202,11 @@ bser@2.1.1: dependencies: node-int64 "^0.4.0" +buf-compare@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/buf-compare/-/buf-compare-1.0.1.tgz#fef28da8b8113a0a0db4430b0b6467b69730b34a" + integrity sha512-Bvx4xH00qweepGc43xFvMs5BKASXTbHaHm6+kDYIK9p/4iFwjATQkmPKHQSgJZzKbAymhztRbXUf1Nqhzl73/Q== + buffer-crc32@~0.2.3: version "0.2.13" resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" @@ -4178,6 +4240,21 @@ bytes@3.1.1: resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.1.tgz#3f018291cb4cbad9accb6e6970bca9c8889e879a" integrity sha512-dWe4nWO/ruEOY7HkUJ5gFt1DCFV9zPRoJr8pV0/ASQermOZjtq8jMjOprC0Kd10GLN+l7xaUPvxzJFWtxGu8Fg== +bytewise-core@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/bytewise-core/-/bytewise-core-1.2.3.tgz#3fb410c7e91558eb1ab22a82834577aa6bd61d42" + integrity sha512-nZD//kc78OOxeYtRlVk8/zXqTB4gf/nlguL1ggWA8FuchMyOxcyHR4QPQZMUmA7czC+YnaBrPUCubqAWe50DaA== + dependencies: + typewise-core "^1.2" + +bytewise@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/bytewise/-/bytewise-1.1.0.tgz#1d13cbff717ae7158094aa881b35d081b387253e" + integrity sha512-rHuuseJ9iQ0na6UDhnrRVDh8YnWVlU6xM3VH6q/+yHDeUH2zIhUzP+2/h3LIrhLDBtTqzWpE3p3tP/boefskKQ== + dependencies: + bytewise-core "^1.2.2" + typewise "^1.0.3" + call-bind@^1.0.0, call-bind@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" @@ -4219,12 +4296,12 @@ caniuse-lite@^1.0.30001286, caniuse-lite@^1.0.30001349: resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001509.tgz" integrity sha512-2uDDk+TRiTX5hMcUYT/7CSyzMZxjfGu0vAUjS2g0LSD8UoXOv0LtpH4LxGMemsiPq6LCVIUjNwVM0erkOkGCDA== -cartocolor@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/cartocolor/-/cartocolor-4.0.2.tgz#ef1aa12860f6eeedc8d2420e2b9d7337937c4993" - integrity sha512-+Gh9mb6lFxsDOLQlBLPxAHCnWXlg2W8q3AcVwqRcy95TdBbcOU89Wrb6h2Hd/6Ww1Kc1pzXmUdpnWD+xeCG0dg== +chalk-template@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/chalk-template/-/chalk-template-0.4.0.tgz#692c034d0ed62436b9062c1707fadcd0f753204b" + integrity sha512-/ghrgmhfY8RaSdeo43hNXxpoHAtxdbskUHjPpfqUWGttFgycUhYPGx3YZBCnUCvOa7Doivn1IZec3DEGFoMgLg== dependencies: - colorbrewer "1.0.0" + chalk "^4.1.2" chalk@2.4.1: version "2.4.1" @@ -4235,7 +4312,7 @@ chalk@2.4.1: escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chalk@^2.0.0, chalk@^2.4.2: +chalk@^2.0.0: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -4399,11 +4476,6 @@ color-name@~1.1.4: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== -colorbrewer@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/colorbrewer/-/colorbrewer-1.0.0.tgz#4f97333b969ba7612382be4bc3394b341fb4c8a2" - integrity sha1-T5czO5abp2Ejgr5LwzlLNB+0yKI= - colorette@^2.0.10, colorette@^2.0.14: version "2.0.16" resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.16.tgz#713b9af84fdb000139f04546bd4a93f62a5085da" @@ -4416,27 +4488,27 @@ combined-stream@^1.0.8: dependencies: delayed-stream "~1.0.0" -command-line-args@5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/command-line-args/-/command-line-args-5.1.1.tgz#88e793e5bb3ceb30754a86863f0401ac92fd369a" - integrity sha512-hL/eG8lrll1Qy1ezvkant+trihbGnaKaeEjj6Scyr3DN+RC7iQ5Rz84IeLERfAWDGo0HBSNAakczwgCilDXnWg== +command-line-args@5.2.1, command-line-args@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/command-line-args/-/command-line-args-5.2.1.tgz#c44c32e437a57d7c51157696893c5909e9cec42e" + integrity sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg== dependencies: - array-back "^3.0.1" + array-back "^3.1.0" find-replace "^3.0.0" lodash.camelcase "^4.3.0" typical "^4.0.0" -command-line-usage@6.1.1: - version "6.1.1" - resolved "https://registry.yarnpkg.com/command-line-usage/-/command-line-usage-6.1.1.tgz#c908e28686108917758a49f45efb4f02f76bc03f" - integrity sha512-F59pEuAR9o1SF/bD0dQBDluhpT4jJQNWUHEuVBqpDmCUo6gPjCi+m9fCWnWZVR/oG6cMTUms4h+3NPl74wGXvA== +command-line-usage@7.0.1, command-line-usage@^7.0.0: + version "7.0.1" + resolved "https://registry.yarnpkg.com/command-line-usage/-/command-line-usage-7.0.1.tgz#e540afef4a4f3bc501b124ffde33956309100655" + integrity sha512-NCyznE//MuTjwi3y84QVUGEOT+P5oto1e1Pk/jFPVdPPfsG03qpTIl3yw6etR+v73d0lXsoojRpvbru2sqePxQ== dependencies: - array-back "^4.0.1" - chalk "^2.4.2" - table-layout "^1.0.1" - typical "^5.2.0" + array-back "^6.2.2" + chalk-template "^0.4.0" + table-layout "^3.0.0" + typical "^7.1.1" -commander@2, commander@^2.20.0: +commander@^2.20.0: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== @@ -4538,6 +4610,14 @@ cookie@0.4.1: resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.1.tgz#afd713fe26ebd21ba95ceb61f9a8116e50a537d1" integrity sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA== +core-assert@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/core-assert/-/core-assert-0.2.1.tgz#f85e2cf9bfed28f773cc8b3fa5c5b69bdc02fe3f" + integrity sha512-IG97qShIP+nrJCXMCgkNZgH7jZQ4n8RpPyPeXX++T6avR/KhLhgLiHKoEn5Rc1KjfycSfA9DMa6m+4C4eguHhw== + dependencies: + buf-compare "^1.0.0" + is-error "^2.2.0" + core-js-compat@^3.20.2, core-js-compat@^3.21.0: version "3.21.0" resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.21.0.tgz#bcc86aa5a589cee358e7a7fa0a4979d5a76c3885" @@ -4690,11 +4770,6 @@ css@^3.0.0: source-map "^0.6.1" source-map-resolve "^0.6.0" -csscolorparser@~1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/csscolorparser/-/csscolorparser-1.0.3.tgz#b34f391eea4da8f3e98231e2ccd8df9c041f171b" - integrity sha1-s085HupNqPPpgjHizNjfnAQfFxs= - cssesc@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" @@ -4737,13 +4812,6 @@ cwd@^0.10.0: find-pkg "^0.1.2" fs-exists-sync "^0.1.0" -d3-array@2, d3-array@^2.3.0, d3-array@^2.8.0: - version "2.12.1" - resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-2.12.1.tgz#e20b41aafcdffdf5d50928004ececf815a465e81" - integrity sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ== - dependencies: - internmap "^1.0.0" - "d3-array@2 - 3", "d3-array@2.10.0 - 3": version "3.2.0" resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-3.2.0.tgz#15bf96cd9b7333e02eb8de8053d78962eafcff14" @@ -4751,47 +4819,16 @@ d3-array@2, d3-array@^2.3.0, d3-array@^2.8.0: dependencies: internmap "1 - 2" -"d3-color@1 - 2", d3-color@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/d3-color/-/d3-color-2.0.0.tgz#8d625cab42ed9b8f601a1760a389f7ea9189d62e" - integrity sha512-SPXi0TSKPD4g9tw0NMZFnR95XVgUZiBH+uUTqQuDu1OsE2zomHU7ho0FISciaPvosimixwHFl3WHLGabv6dDgQ== - "d3-color@1 - 3": version "3.1.0" resolved "https://registry.yarnpkg.com/d3-color/-/d3-color-3.1.0.tgz#395b2833dfac71507f12ac2f7af23bf819de24e2" integrity sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA== -d3-dsv@^1.0.8: - version "1.2.0" - resolved "https://registry.yarnpkg.com/d3-dsv/-/d3-dsv-1.2.0.tgz#9d5f75c3a5f8abd611f74d3f5847b0d4338b885c" - integrity sha512-9yVlqvZcSOMhCYzniHE7EVUws7Fa1zgw+/EAV2BxJoG3ME19V6BQFBwI855XQDsxyOuG7NibqRMTtiF/Qup46g== - dependencies: - commander "2" - iconv-lite "0.4" - rw "1" - -"d3-format@1 - 2", d3-format@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/d3-format/-/d3-format-2.0.0.tgz#a10bcc0f986c372b729ba447382413aabf5b0767" - integrity sha512-Ab3S6XuE/Q+flY96HXT0jOXcM4EAClYFnRGY5zsjRGNy6qCYrQsMffs7cV5Q9xejb35zxW5hf/guKw34kvIKsA== - "d3-format@1 - 3": version "3.1.0" resolved "https://registry.yarnpkg.com/d3-format/-/d3-format-3.1.0.tgz#9260e23a28ea5cb109e93b21a06e24e2ebd55641" integrity sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA== -d3-hexbin@^0.2.1: - version "0.2.2" - resolved "https://registry.yarnpkg.com/d3-hexbin/-/d3-hexbin-0.2.2.tgz#9c5837dacfd471ab05337a9e91ef10bfc4f98831" - integrity sha1-nFg32s/UcasFM3qeke8Qv8T5iDE= - -"d3-interpolate@1.2.0 - 2": - version "2.0.1" - resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-2.0.1.tgz#98be499cfb8a3b94d4ff616900501a64abc91163" - integrity sha512-c5UhwwTs/yybcmTpAVqwSFl6vrQ8JZJoT5F7xNFK9pymv5C0Ymcc9/LIJHtYIggg/yS9YHw8i8O8tgb9pupjeQ== - dependencies: - d3-color "1 - 2" - "d3-interpolate@1.2.0 - 3", d3-interpolate@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-3.0.1.tgz#3c47aa5b32c5b3dfb56ef3fd4342078a632b400d" @@ -4804,17 +4841,6 @@ d3-hexbin@^0.2.1: resolved "https://registry.yarnpkg.com/d3-path/-/d3-path-3.0.1.tgz#f09dec0aaffd770b7995f1a399152bf93052321e" integrity sha512-gq6gZom9AFZby0YLduxT1qmrp4xpBA1YZr19OI717WIdKE2OM5ETq5qrHLb301IgxhLwcuxvGZVLeeWc/k1I6w== -d3-scale@^3.2.3: - version "3.3.0" - resolved "https://registry.yarnpkg.com/d3-scale/-/d3-scale-3.3.0.tgz#28c600b29f47e5b9cd2df9749c206727966203f3" - integrity sha512-1JGp44NQCt5d1g+Yy+GeOnZP7xHo0ii8zsQp6PGzd+C1/dl0KGsp9A7Mxwp+1D1o4unbTTxVdU/ZOIEBoeZPbQ== - dependencies: - d3-array "^2.3.0" - d3-format "1 - 2" - d3-interpolate "1.2.0 - 2" - d3-time "^2.1.1" - d3-time-format "2 - 3" - d3-scale@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/d3-scale/-/d3-scale-4.0.2.tgz#82b38e8e8ff7080764f8dcec77bd4be393689396" @@ -4833,13 +4859,6 @@ d3-shape@^3.1.0: dependencies: d3-path "1 - 3" -"d3-time-format@2 - 3": - version "3.0.0" - resolved "https://registry.yarnpkg.com/d3-time-format/-/d3-time-format-3.0.0.tgz#df8056c83659e01f20ac5da5fdeae7c08d5f1bb6" - integrity sha512-UXJh6EKsHBTjopVqZBhFysQcoXSv/5yLONZvkQ5Kk3qbwiUYkdX17Xa1PT6U1ZWXGGfB1ey5L8dKMlFq2DO0Ag== - dependencies: - d3-time "1 - 2" - "d3-time-format@2 - 4": version "4.1.0" resolved "https://registry.yarnpkg.com/d3-time-format/-/d3-time-format-4.1.0.tgz#7ab5257a5041d11ecb4fe70a5c7d16a195bb408a" @@ -4847,13 +4866,6 @@ d3-shape@^3.1.0: dependencies: d3-time "1 - 3" -"d3-time@1 - 2", d3-time@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/d3-time/-/d3-time-2.1.1.tgz#e9d8a8a88691f4548e68ca085e5ff956724a6682" - integrity sha512-/eIQe/eR4kCQwq7yxi7z4c6qEXf2IYGcjoWB5OOQy4Tq9Uv39/947qlDcN2TLkiTzQWzvnsuYPB9TrWaNfipKQ== - dependencies: - d3-array "2" - "d3-time@1 - 3", "d3-time@2.1.1 - 3": version "3.0.0" resolved "https://registry.yarnpkg.com/d3-time/-/d3-time-3.0.0.tgz#65972cb98ae2d4954ef5c932e8704061335d4975" @@ -4901,23 +4913,6 @@ decimal.js@^10.2.1: resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.3.1.tgz#d8c3a444a9c6774ba60ca6ad7261c3a94fd5e783" integrity sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ== -deck.gl@^8.8.3: - version "8.8.3" - resolved "https://registry.yarnpkg.com/deck.gl/-/deck.gl-8.8.3.tgz#392f3f2312e60f3852fbbbed4dec1f22297c97b3" - integrity sha512-uVfa+DkHCZ+7BbkHyRVPLsuiDqMI8+C9XLOK7RRDtHhT9JfGArQ81SuFdBMEZC3Q1PHErhZ+pHbd9QqWkozaVg== - dependencies: - "@deck.gl/aggregation-layers" "8.8.3" - "@deck.gl/carto" "8.8.3" - "@deck.gl/core" "8.8.3" - "@deck.gl/extensions" "8.8.3" - "@deck.gl/geo-layers" "8.8.3" - "@deck.gl/google-maps" "8.8.3" - "@deck.gl/json" "8.8.3" - "@deck.gl/layers" "8.8.3" - "@deck.gl/mapbox" "8.8.3" - "@deck.gl/mesh-layers" "8.8.3" - "@deck.gl/react" "8.8.3" - decode-uri-component@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" @@ -4940,7 +4935,7 @@ deep-equal@^1.0.1: object-keys "^1.1.1" regexp.prototype.flags "^1.2.0" -deep-extend@^0.6.0, deep-extend@~0.6.0: +deep-extend@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== @@ -4950,6 +4945,13 @@ deep-is@^0.1.3, deep-is@~0.1.3: resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== +deep-strict-equal@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/deep-strict-equal/-/deep-strict-equal-0.2.0.tgz#4a078147a8ab57f6a0d4f5547243cd22f44eb4e4" + integrity sha512-3daSWyvZ/zwJvuMGlzG1O+Ow0YSadGfb3jsh9xoCutv2tWyB9dA4YvR9L9/fSdDZa2dByYQe+TqapSGUrjnkoA== + dependencies: + core-assert "^0.2.0" + deepmerge@^4.2.2: version "4.2.2" resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" @@ -5121,20 +5123,15 @@ dot-case@^3.0.4: no-case "^3.0.4" tslib "^2.0.3" -draco3d@1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/draco3d/-/draco3d-1.4.1.tgz#2abdcf7b59caaac50f7e189aec454176c57146b2" - integrity sha512-9Rxonc70xiovBC+Bq1h57SNZIHzWTibU1VfIGp5z3Xx8dPtv4yT5uGhiH7P5uvJRR2jkrvHafRxR7bTANkvfpg== - draco3d@1.5.5: version "1.5.5" resolved "https://registry.yarnpkg.com/draco3d/-/draco3d-1.5.5.tgz#6bf4bbdd65950e6153e991cb0dcb8a10323f610e" integrity sha512-JVuNV0EJzD3LBYhGyIXJLeBID/EVtmFO1ZNhAYflTgiMiAJlbhXQmRRda/azjc8MRVMHh0gqGhiqHUo5dIXM8Q== -earcut@^2.0.6, earcut@^2.2.2: - version "2.2.3" - resolved "https://registry.yarnpkg.com/earcut/-/earcut-2.2.3.tgz#d44ced2ff5a18859568e327dd9c7d46b16f55cf4" - integrity sha512-iRDI1QeCQIhMCZk48DRDMVgQSSBDmbzzNhnxIo+pwx3swkfjMh6vh0nWLq1NdvGHLKH6wIrAM3vQWeTj6qeoug== +earcut@^2.0.6, earcut@^2.2.4: + version "2.2.4" + resolved "https://registry.yarnpkg.com/earcut/-/earcut-2.2.4.tgz#6d02fd4d68160c114825d06890a92ecaae60343a" + integrity sha512-/pjZsA1b4RPHbeWZQn66SWS8nZZWLQQ23oE3Eam7aroEFGEvwKAsJfZ9ytiEMycfzXWpca4FA9QIOehf7PocBQ== ee-first@1.1.1: version "1.1.1" @@ -5473,12 +5470,20 @@ express@^4.17.1: utils-merge "1.0.1" vary "~1.1.2" -expression-eval@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/expression-eval/-/expression-eval-2.1.0.tgz#422915caa46140a7c5b5f248650dea8bf8236e62" - integrity sha512-FUJO/Akvl/JOWkvlqZaqbkhsEWlCJWDeZG4tzX96UH68D9FeRgYgtb55C2qtqbORC0Q6x5419EDjWu4IT9kQfg== +extend-shallow@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" + integrity sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug== + dependencies: + is-extendable "^0.1.0" + +extend-shallow@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" + integrity sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q== dependencies: - jsep "^0.3.0" + assign-symbols "^1.0.0" + is-extendable "^1.0.1" extract-zip@2.0.1: version "2.0.1" @@ -5529,6 +5534,13 @@ fast-url-parser@1.1.3: dependencies: punycode "^1.3.2" +fast-xml-parser@^4.2.5: + version "4.3.2" + resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-4.3.2.tgz#761e641260706d6e13251c4ef8e3f5694d4b0d79" + integrity sha512-rmrXUXwbJedoXkStenj1kkljNF7ugn5ZjR9FJcwmCfcCbtOMDghPajbc+Tck6vE6F5XsDmx+Pr2le9fw8+pXBg== + dependencies: + strnum "^1.0.5" + fastest-levenshtein@^1.0.12: version "1.0.12" resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz#9990f7d3a88cc5a9ffd1f1745745251700d497e2" @@ -5663,10 +5675,10 @@ flat-cache@^3.0.4: flatted "^3.1.0" rimraf "^3.0.2" -flatbuffers@1.12.0: - version "1.12.0" - resolved "https://registry.yarnpkg.com/flatbuffers/-/flatbuffers-1.12.0.tgz#72e87d1726cb1b216e839ef02658aa87dcef68aa" - integrity sha512-c7CZADjRcl6j0PlvFy0ZqXQ67qSEZfrVPynmnL+2zPc+NtMvrF8Y0QceMo7QqnSPc7+uWjUIAbvCQ5WIKlMVdQ== +flatbuffers@23.5.26: + version "23.5.26" + resolved "https://registry.yarnpkg.com/flatbuffers/-/flatbuffers-23.5.26.tgz#01358e272a61239f0faf3bfbe4e014f3ace9d746" + integrity sha512-vE+SI9vrJDwi1oETtTIFldC/o9GsVKRM+s6EL0nQgxXlYV1Vc4Tk30hj4xGICftInKQKj1F3up2n8UbIVobISQ== flatted@^3.1.0: version "3.2.5" @@ -5802,7 +5814,12 @@ get-stream@^6.0.0, get-stream@^6.0.1: resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== -gl-matrix@^3.0.0, gl-matrix@^3.2.1, gl-matrix@^3.4.0: +get-value@^2.0.2, get-value@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" + integrity sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA== + +gl-matrix@^3.0.0, gl-matrix@^3.4.0, gl-matrix@^3.4.3: version "3.4.3" resolved "https://registry.yarnpkg.com/gl-matrix/-/gl-matrix-3.4.3.tgz#fc1191e8320009fd4d20e9339595c6041ddc22c9" integrity sha512-wcCp8vu8FT22BnvKVPjXa/ICBWRq/zjFfdofZy1WSpQZpphblv12/bOQLBC1rMM7SGOFS9ltVmKOHil5+Ml7gA== @@ -5861,6 +5878,15 @@ global-prefix@^0.1.4: is-windows "^0.2.0" which "^1.2.12" +global-prefix@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-3.0.0.tgz#fc85f73064df69f50421f47f883fe5b913ba9b97" + integrity sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg== + dependencies: + ini "^1.3.5" + kind-of "^6.0.2" + which "^1.3.1" + globals@^11.1.0: version "11.12.0" resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" @@ -5890,11 +5916,6 @@ graceful-fs@^4.1.2, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9: resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96" integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ== -grid-index@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/grid-index/-/grid-index-1.1.0.tgz#97f8221edec1026c8377b86446a7c71e79522ea7" - integrity sha512-HZRwumpOGUrHyxO5bqKZL0B0GlUpwtCAzZ42sgxUPniu33R1LSFH5yrIcBCHjkctCAh3mtWKcKd9J4vDDdeVHA== - h3-js@^3.7.0: version "3.7.2" resolved "https://registry.yarnpkg.com/h3-js/-/h3-js-3.7.2.tgz#61d4feb7bb42868ca9cdb2d5cf9d9dda94f9e5a3" @@ -6112,7 +6133,7 @@ hyphenate-style-name@^1.0.0: resolved "https://registry.yarnpkg.com/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz#691879af8e220aea5750e8827db4ef62a54e361d" integrity sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ== -iconv-lite@0.4, iconv-lite@0.4.24: +iconv-lite@0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== @@ -6198,7 +6219,7 @@ inherits@2.0.3: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= -ini@^1.3.4, ini@~1.3.0: +ini@^1.3.4, ini@^1.3.5, ini@~1.3.0: version "1.3.8" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== @@ -6208,11 +6229,6 @@ ini@^1.3.4, ini@~1.3.0: resolved "https://registry.yarnpkg.com/internmap/-/internmap-2.0.3.tgz#6685f23755e43c524e251d29cbc97248e3061009" integrity sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg== -internmap@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/internmap/-/internmap-1.0.1.tgz#0017cc8a3b99605f0302f2b198d272e015e5df95" - integrity sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw== - interpret@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/interpret/-/interpret-2.2.0.tgz#1a78a0b5965c40a5416d007ad6f50ad27c417df9" @@ -6277,11 +6293,23 @@ is-docker@^2.0.0, is-docker@^2.1.1: resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== -is-extendable@^0.1.1: +is-error@^2.2.0: + version "2.2.2" + resolved "https://registry.yarnpkg.com/is-error/-/is-error-2.2.2.tgz#c10ade187b3c93510c5470a5567833ee25649843" + integrity sha512-IOQqts/aHWbiisY5DuPJQ0gcbvaLFCa7fBa9xoLfxBZvQ+ZI/Zh9xoI7Gk+G64N0FdK4AbibytHht2tWgpJWLg== + +is-extendable@^0.1.0, is-extendable@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= +is-extendable@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" + integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== + dependencies: + is-plain-object "^2.0.4" + is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" @@ -6324,7 +6352,7 @@ is-plain-obj@^3.0.0: resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-3.0.0.tgz#af6f2ea14ac5a646183a5bbdb5baabbc156ad9d7" integrity sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA== -is-plain-object@^2.0.1, is-plain-object@^2.0.4: +is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== @@ -6938,11 +6966,6 @@ jsdom@^16.6.0: ws "^7.4.6" xml-name-validator "^3.0.0" -jsep@^0.3.0: - version "0.3.5" - resolved "https://registry.yarnpkg.com/jsep/-/jsep-0.3.5.tgz#3fd79ebd92f6f434e4857d5272aaeef7d948264d" - integrity sha512-AoRLBDc6JNnKjNcmonituEABS5bcfqDhQAWWXNTFrqu6nVXBpBAGfcoTGZMFlIrh9FjmE1CQyX9CTNwZrXMMDA== - jsesc@^2.5.1: version "2.5.2" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" @@ -6956,7 +6979,7 @@ jsesc@~0.5.0: json-bignum@^0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/json-bignum/-/json-bignum-0.0.3.tgz#41163b50436c773d82424dbc20ed70db7604b8d7" - integrity sha1-QRY7UENsdz2CQk28IO1w23YEuNc= + integrity sha512-2WHyXj3OfHSgNyuzDbSxI1w2jgw5gkWSWhS7Qg4bWXx1nLk3jnbwfUeS0PSba3IzpTUWdHxBieELUzXRjQB2zg== json-parse-better-errors@^1.0.2: version "1.0.2" @@ -6983,6 +7006,11 @@ json-stable-stringify-without-jsonify@^1.0.1: resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= +json-stringify-pretty-compact@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/json-stringify-pretty-compact/-/json-stringify-pretty-compact-3.0.0.tgz#f71ef9d82ef16483a407869556588e91b681d9ab" + integrity sha512-Rc2suX5meI0S3bfdZuA7JMFBGkJ875ApfVyq2WHELjBiiG22My/l7/8zPpH/CfFVQHuVLd8NLR0nv6vi0BYYKA== + json5@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" @@ -7022,10 +7050,10 @@ just-curry-it@^5.2.1: resolved "https://registry.yarnpkg.com/just-curry-it/-/just-curry-it-5.2.1.tgz#93f17967b933e5dd6769ec86eea0eda8f32fce43" integrity sha512-M8qhhO9WVNc3yZgf3qfiNxMIsQlHqFHJ3vMI8N/rkp852h1utOB/N3ebS8jeXGAwYSbkdd0K6zP9eZneUtjHwA== -kdbush@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/kdbush/-/kdbush-3.0.0.tgz#f8484794d47004cc2d85ed3a79353dbe0abc2bf0" - integrity sha512-hRkd6/XW4HTsA9vjVpY9tuXJYLSlelnkTmVFu4M9/7MIYQtFcHpbugAU7UbOfjOiVSVYl2fqgBuJ32JUmRo5Ew== +kdbush@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/kdbush/-/kdbush-4.0.2.tgz#2f7b7246328b4657dd122b6c7f025fbc2c868e39" + integrity sha512-WbCVYJ27Sz8zi9Q7Q0xHC+05iwkm3Znipc2XTlrnJbsHMYktW4hPhXUE8Ys1engBrvffoSCqbil1JQAa7clRpA== kind-of@^2.0.1: version "2.0.1" @@ -7066,6 +7094,11 @@ lazy-cache@^1.0.3: resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e" integrity sha1-odePw6UEdMuAhF07O24dpJpEbo4= +lerc@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/lerc/-/lerc-4.0.2.tgz#db1232d791ef6bf769c4a55ada9dd46f58458622" + integrity sha512-9V1IUp1LJmzFYBm3ABYTawtZY0PzCVqXWuT2ZimVU4NOyGOo4C0P8+XmurVWmT5c8y4ZioJzwQI3k+t/3s8j+Q== + leven@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" @@ -7134,10 +7167,15 @@ lodash-es@^4.17.15: resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee" integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw== +lodash.assignwith@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.assignwith/-/lodash.assignwith-4.2.0.tgz#127a97f02adc41751a954d24b0de17e100e038eb" + integrity sha512-ZznplvbvtjK2gMvnQ1BR/zqPFZmS6jbK4p+6Up4xcRYA7yMIwxHCfbTcrYxXKzzqLsQ05eJPVznEW3tuwV7k1g== + lodash.camelcase@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" - integrity sha1-soqmKIorn8ZRA1x3EfZathkDMaY= + integrity sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA== lodash.debounce@^4.0.8: version "4.0.8" @@ -7157,7 +7195,7 @@ lodash@^4.0.1, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.1 long@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/long/-/long-3.2.0.tgz#d821b7138ca1cb581c172990ef14db200b5c474b" - integrity sha1-2CG3E4yhy1gcFymQ7xTbIAtcR0s= + integrity sha512-ZYvPPOMqUwPoDsbJaR10iQJYnMuZhRTvHYl62ErLIEX7RgFlziSBUUvrt3OVfc47QlHHpzPZYP17g3Fv7oeJkg== long@^5.2.1: version "5.2.3" @@ -7214,34 +7252,36 @@ makeerror@1.0.12: dependencies: tmpl "1.0.5" -mapbox-gl@^1.0.0: - version "1.13.2" - resolved "https://registry.yarnpkg.com/mapbox-gl/-/mapbox-gl-1.13.2.tgz#76639c44f141f8dff71b7d8f1504f2aed11f7517" - integrity sha512-CPjtWygL+f7naL+sGHoC2JQR0DG7u+9ik6WdkjjVmz2uy0kBC2l+aKfdi3ZzUR7VKSQJ6Mc/CeCN+6iVNah+ww== +maplibre-gl@^3.5.2: + version "3.5.2" + resolved "https://registry.yarnpkg.com/maplibre-gl/-/maplibre-gl-3.5.2.tgz#84a352f1845c6ccf6fe5d86aaa0d0e8b0f18923c" + integrity sha512-deqYA/RiEyXMGroZMDbOWNQTLnFsxREC+mDkQnuyCUNdBWm1KHafsXJYZP7rlLa5RLQNq05IAUAizY9aHTpIUw== dependencies: - "@mapbox/geojson-rewind" "^0.5.0" - "@mapbox/geojson-types" "^1.0.2" + "@mapbox/geojson-rewind" "^0.5.2" "@mapbox/jsonlint-lines-primitives" "^2.0.2" - "@mapbox/mapbox-gl-supported" "^1.5.0" "@mapbox/point-geometry" "^0.1.0" - "@mapbox/tiny-sdf" "^1.1.1" - "@mapbox/unitbezier" "^0.0.0" + "@mapbox/tiny-sdf" "^2.0.6" + "@mapbox/unitbezier" "^0.0.1" "@mapbox/vector-tile" "^1.3.1" "@mapbox/whoots-js" "^3.1.0" - csscolorparser "~1.0.3" - earcut "^2.2.2" + "@maplibre/maplibre-gl-style-spec" "^19.3.3" + "@types/geojson" "^7946.0.12" + "@types/mapbox__point-geometry" "^0.1.3" + "@types/mapbox__vector-tile" "^1.3.3" + "@types/pbf" "^3.0.4" + "@types/supercluster" "^7.1.2" + earcut "^2.2.4" geojson-vt "^3.2.1" - gl-matrix "^3.2.1" - grid-index "^1.1.0" - minimist "^1.2.5" + gl-matrix "^3.4.3" + global-prefix "^3.0.0" + kdbush "^4.0.2" murmurhash-js "^1.0.0" pbf "^3.2.1" - potpack "^1.0.1" + potpack "^2.0.0" quickselect "^2.0.0" - rw "^1.3.3" - supercluster "^7.1.0" + supercluster "^8.0.1" tinyqueue "^2.0.3" - vt-pbf "^3.1.1" + vt-pbf "^3.1.3" matchmediaquery@^0.3.0: version "0.3.1" @@ -7255,12 +7295,12 @@ material-colors@^1.2.1: resolved "https://registry.yarnpkg.com/material-colors/-/material-colors-1.2.6.tgz#6d1958871126992ceecc72f4bcc4d8f010865f46" integrity sha512-6qE4B9deFBIa9YSpOc9O0Sgc43zTeVYbgDT5veRKSlB2+ZuHNoVVxA1L/ckMUayV9Ay9y7Z/SZCLcGteW9i7bg== -math.gl@^3.6.0: - version "3.6.1" - resolved "https://registry.yarnpkg.com/math.gl/-/math.gl-3.6.1.tgz#14eb614b70ee152ef93a9b84115fccde5aea9359" - integrity sha512-dIAc4VPZ0zsJBJpP8W+Eha2/HQMZSOfEZXuNF4fFVE/8FshTyj0NkzNPtegteRmZGf/sROpzH2d5G3m+PRFrbw== +math.gl@^3.6.2: + version "3.6.3" + resolved "https://registry.yarnpkg.com/math.gl/-/math.gl-3.6.3.tgz#f87e0d24cb33c1a215185ae3a4e16839f1ce6db2" + integrity sha512-Yq9CyECvSDox9+5ETi2+x1bGTY5WvGUGL3rJfC4KPoCZAM51MGfrCm6rIn4yOJUVfMPs2a5RwMD+yGS/n1g3gg== dependencies: - "@math.gl/core" "3.6.1" + "@math.gl/core" "3.6.3" md5@^2.3.0: version "2.3.0" @@ -7393,6 +7433,11 @@ minimist@^1.2.0, minimist@^1.2.5: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== +minimist@^1.2.6, minimist@^1.2.8: + version "1.2.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== + mixin-object@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/mixin-object/-/mixin-object-2.0.1.tgz#4fb949441dab182540f1fe035ba60e1947a5e57e" @@ -7401,18 +7446,10 @@ mixin-object@^2.0.1: for-in "^0.1.3" is-extendable "^0.1.1" -mjolnir.js@^2.5.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/mjolnir.js/-/mjolnir.js-2.6.0.tgz#0a199f71434b5f183248e1a9bb06a3b4e5533ecb" - integrity sha512-rGA7+BJKvXI0ypxQD/+rQE/sW26kmc8UIZWhmQrjhwCf/zvhbcBlsu2vPB6w0Kv/rVnVFEONTSQqC0vFEpQvIA== - dependencies: - "@babel/runtime" "^7.0.0" - hammerjs "^2.0.8" - mjolnir.js@^2.7.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/mjolnir.js/-/mjolnir.js-2.7.0.tgz#8aeec755644d8e9de4f247a5fd0718e39795fe6e" - integrity sha512-XlK5OZ7d09eAIdYr+5VKOArYtkWB/f306s34yVij4pBk5wnaKxSrD7fVfP8/BL27nKVylNweqP1pxqh8h+hWKw== + version "2.7.1" + resolved "https://registry.yarnpkg.com/mjolnir.js/-/mjolnir.js-2.7.1.tgz#4e12590fe168b377c9c669b9c31aa5a62f8b8460" + integrity sha512-72BeUWgTv2cj5aZQKpwL8caNUFhXZ9bDm1hxpNj70XJQ62IBnTZmtv/WPxJvtaVNhzNo+D2U8O6ryNI0zImYcw== dependencies: "@types/hammerjs" "^2.0.41" hammerjs "^2.0.8" @@ -7429,18 +7466,6 @@ mkdirp@^0.5.5: dependencies: minimist "^1.2.5" -moment-timezone@^0.5.33: - version "0.5.34" - resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.34.tgz#a75938f7476b88f155d3504a9343f7519d9a405c" - integrity sha512-3zAEHh2hKUs3EXLESx/wsgw6IQdusOT8Bxm3D9UrHPQR7zlMmzwybC8zHEM1tQ4LJwP7fcxrWr8tuBg05fFCbg== - dependencies: - moment ">= 2.9.0" - -"moment@>= 2.9.0": - version "2.29.1" - resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.1.tgz#b2be769fa31940be9eeea6469c075e35006fa3d3" - integrity sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ== - moo@^0.5.1: version "0.5.2" resolved "https://registry.yarnpkg.com/moo/-/moo-0.5.2.tgz#f9fe82473bc7c184b0d32e2215d3f6e67278733c" @@ -7714,7 +7739,7 @@ p-try@^2.0.0: pad-left@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/pad-left/-/pad-left-2.1.0.tgz#16e6a3b2d44a8e138cb0838cc7cb403a4fc9e994" - integrity sha1-FuajstRKjhOMsIOMx8tAOk/J6ZQ= + integrity sha512-HJxs9K9AztdIQIAIa/OIazRAUW/L6B9hbQDxO4X07roW3eo9XqZc2ur9bn1StH9CnbbI9EgvejHQX7CBpCF1QA== dependencies: repeat-string "^1.5.4" @@ -7915,10 +7940,10 @@ postcss@^8.4.7: picocolors "^1.0.0" source-map-js "^1.0.2" -potpack@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/potpack/-/potpack-1.0.2.tgz#23b99e64eb74f5741ffe7656b5b5c4ddce8dfc14" - integrity sha512-choctRBIV9EMT9WGAZHn3V7t0Z2pMQyl0EZE6pFc/6ml3ssw7Dlf/oAOvFwjm1HVsqfQN8GfeFyJ+d8tRzqueQ== +potpack@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/potpack/-/potpack-2.0.0.tgz#61f4dd2dc4b3d5e996e3698c0ec9426d0e169104" + integrity sha512-Q+/tYsFU9r7xoOJ+y/ZTtdVQwTWfzjbiXBDMM/JKUux3+QPP02iUuIoeBQ+Ot6oEDlC+/PGjB/5A3K7KKb7hcw== prelude-ls@^1.2.1: version "1.2.1" @@ -7947,16 +7972,6 @@ pretty-format@^27.0.0, pretty-format@^27.0.2, pretty-format@^27.5.1: ansi-styles "^5.0.0" react-is "^17.0.1" -probe.gl@^3.4.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/probe.gl/-/probe.gl-3.5.0.tgz#084c0ef3a233e1c055cd8a88efb67abb11eba483" - integrity sha512-KWj8u0PNytr/rVwcQFcN7O8SK7n/ITOsUZ91l4fSX95oHhKvVCI7eadrzFUzFRlXkFfBWpMWZXFHITsHHHUctw== - dependencies: - "@babel/runtime" "^7.0.0" - "@probe.gl/env" "3.5.0" - "@probe.gl/log" "3.5.0" - "@probe.gl/stats" "3.5.0" - process-nextick-args@~2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" @@ -7983,7 +7998,7 @@ prompts@^2.0.1, prompts@^2.4.2: kleur "^3.0.3" sisteransi "^1.0.5" -prop-types@^15.5.10, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1: +prop-types@^15.5.10, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.8.1: version "15.8.1" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== @@ -8157,19 +8172,13 @@ react-lifecycles-compat@^3.0.4: resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA== -react-map-gl@^5.0.0: - version "5.3.19" - resolved "https://registry.yarnpkg.com/react-map-gl/-/react-map-gl-5.3.19.tgz#8c012eb7328c64dc2a4bb65eeceacd4a66734f72" - integrity sha512-Ia8OlbFJIjC9x7XMaUCNtm179NKiD/bjQOt1R/SbBcaz35pSFPUyI0SwOnIUQ98/mR4xopL6phgIfs0B3yZhtQ== +react-map-gl@^7.1.6: + version "7.1.6" + resolved "https://registry.yarnpkg.com/react-map-gl/-/react-map-gl-7.1.6.tgz#4ea239cd49493cfc9ed15aa52436b024c757c0a9" + integrity sha512-9XbrvpFF67Fyi+e6vRLJFnGpo3UF6ZHifIa8cS/wUYSsnv9sVyzGsN++FJy57zkz3Jh3kmf0xKZemR8K0FZLVw== dependencies: - "@babel/runtime" "^7.0.0" - "@types/geojson" "^7946.0.7" - "@types/mapbox-gl" "^2.0.3" - mapbox-gl "^1.0.0" - mjolnir.js "^2.5.0" - prop-types "^15.7.2" - resize-observer-polyfill "^1.5.1" - viewport-mercator-project "^7.0.4" + "@maplibre/maplibre-gl-style-spec" "^19.2.1" + "@types/mapbox-gl" ">=1.0.0" react-redux@^8.1.1: version "8.1.1" @@ -8342,11 +8351,6 @@ reduce-css-calc@^2.1.8: css-unit-converter "^1.1.1" postcss-value-parser "^3.3.0" -reduce-flatten@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/reduce-flatten/-/reduce-flatten-2.0.0.tgz#734fd84e65f375d7ca4465c69798c25c9d10ae27" - integrity sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w== - redux-thunk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.4.2.tgz#b9d05d11994b99f7a91ea223e8b04cf0afa5ef3b" @@ -8476,7 +8480,7 @@ renderkid@^3.0.0: repeat-string@^1.5.4: version "1.6.1" resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" - integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= + integrity sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w== require-directory@^2.1.1: version "2.1.1" @@ -8498,11 +8502,6 @@ reselect@^4.1.8: resolved "https://registry.yarnpkg.com/reselect/-/reselect-4.1.8.tgz#3f5dc671ea168dccdeb3e141236f69f02eaec524" integrity sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ== -resize-observer-polyfill@^1.5.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz#0e9020dd3d21024458d4ebd27e23e40269810464" - integrity sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg== - resolve-cwd@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" @@ -8573,7 +8572,7 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" -rw@1, rw@^1.3.3: +rw@^1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/rw/-/rw-1.3.3.tgz#3f862dfa91ab766b14885ef4d01124bfda074fb4" integrity sha1-P4Yt+pGrdmsUiF700BEkv9oHT7Q= @@ -8755,6 +8754,16 @@ serve@^13.0.2: serve-handler "6.1.3" update-check "1.5.2" +set-value@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" + integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw== + dependencies: + extend-shallow "^2.0.1" + is-extendable "^0.1.1" + is-plain-object "^2.0.3" + split-string "^3.0.1" + setimmediate@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" @@ -8850,6 +8859,28 @@ sockjs@^0.3.21: uuid "^8.3.2" websocket-driver "^0.7.4" +sort-asc@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/sort-asc/-/sort-asc-0.2.0.tgz#00a49e947bc25d510bfde2cbb8dffda9f50eb2fc" + integrity sha512-umMGhjPeHAI6YjABoSTrFp2zaBtXBej1a0yKkuMUyjjqu6FJsTF+JYwCswWDg+zJfk/5npWUUbd33HH/WLzpaA== + +sort-desc@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/sort-desc/-/sort-desc-0.2.0.tgz#280c1bdafc6577887cedbad1ed2e41c037976646" + integrity sha512-NqZqyvL4VPW+RAxxXnB8gvE1kyikh8+pR+T+CXLksVRN9eiQqkQlPwqWYU0mF9Jm7UnctShlxLyAt1CaBOTL1w== + +sort-object@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/sort-object/-/sort-object-3.0.3.tgz#945727165f244af9dc596ad4c7605a8dee80c269" + integrity sha512-nK7WOY8jik6zaG9CRwZTaD5O7ETWDLZYMM12pqY8htll+7dYeqGfEUPcUBHOpSJg2vJOrvFIY2Dl5cX2ih1hAQ== + dependencies: + bytewise "^1.1.0" + get-value "^2.0.2" + is-extendable "^0.1.1" + sort-asc "^0.2.0" + sort-desc "^0.2.0" + union-value "^1.0.1" + source-map-js@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" @@ -8923,6 +8954,13 @@ spdy@^4.0.2: select-hose "^2.0.0" spdy-transport "^3.0.0" +split-string@^3.0.1: + version "3.1.0" + resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" + integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== + dependencies: + extend-shallow "^3.0.0" + sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" @@ -8945,6 +8983,11 @@ stack-utils@^2.0.3: resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= +stream-read-all@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/stream-read-all/-/stream-read-all-3.0.1.tgz#60762ae45e61d93ba0978cda7f3913790052ad96" + integrity sha512-EWZT9XOceBPlVJRrYcykW8jyRSZYbkb/0ZK36uLEmoWVO5gxBOnntNTseNzfREsqxqdfEGQrD8SXQ3QWbBmq8A== + string-length@^4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" @@ -9022,6 +9065,11 @@ strip-json-comments@~2.0.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= +strnum@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/strnum/-/strnum-1.0.5.tgz#5c4e829fe15ad4ff0d20c3db5ac97b73c9b072db" + integrity sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA== + style-loader@^3.3.1: version "3.3.1" resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-3.3.1.tgz#057dfa6b3d4d7c7064462830f9113ed417d38575" @@ -9043,12 +9091,12 @@ styled-components@^5.3.3: shallowequal "^1.1.0" supports-color "^5.5.0" -supercluster@^7.1.0: - version "7.1.4" - resolved "https://registry.yarnpkg.com/supercluster/-/supercluster-7.1.4.tgz#6762aabfd985d3390b49f13b815567d5116a828a" - integrity sha512-GhKkRM1jMR6WUwGPw05fs66pOFWhf59lXq+Q3J3SxPvhNcmgOtLRV6aVQPMRsmXdpaeFJGivt+t7QXUPL3ff4g== +supercluster@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/supercluster/-/supercluster-8.0.1.tgz#9946ba123538e9e9ab15de472531f604e7372df5" + integrity sha512-IiOea5kJ9iqzD2t7QJq/cREyLHTtSmUT6gQsweojg9WH2sYJqZK9SswTu6jrscO6D1G5v5vYZ9ru/eq85lXeZQ== dependencies: - kdbush "^3.0.0" + kdbush "^4.0.2" supports-color@^5.3.0, supports-color@^5.5.0: version "5.5.0" @@ -9107,15 +9155,18 @@ symbol-tree@^3.2.4: resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== -table-layout@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/table-layout/-/table-layout-1.0.2.tgz#c4038a1853b0136d63365a734b6931cf4fad4a04" - integrity sha512-qd/R7n5rQTRFi+Zf2sk5XVVd9UQl6ZkduPFC3S7WEGJAmetDTjY3qPN50eSKzwuzEyQKy5TN2TiZdkIjos2L6A== +table-layout@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/table-layout/-/table-layout-3.0.2.tgz#69c2be44388a5139b48c59cf21e73b488021769a" + integrity sha512-rpyNZYRw+/C+dYkcQ3Pr+rLxW4CfHpXjPDnG7lYhdRoUcZTUt+KEsX+94RGp/aVp/MQU35JCITv2T/beY4m+hw== dependencies: - array-back "^4.0.1" - deep-extend "~0.6.0" - typical "^5.2.0" - wordwrapjs "^4.0.0" + "@75lb/deep-merge" "^1.1.1" + array-back "^6.2.2" + command-line-args "^5.2.1" + command-line-usage "^7.0.0" + stream-read-all "^3.0.1" + typical "^7.1.1" + wordwrapjs "^5.1.0" tapable@^2.0.0, tapable@^2.1.1, tapable@^2.2.0: version "2.2.1" @@ -9180,11 +9231,6 @@ test-exclude@^6.0.0: glob "^7.1.4" minimatch "^3.0.4" -text-encoding-utf-8@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/text-encoding-utf-8/-/text-encoding-utf-8-1.0.2.tgz#585b62197b0ae437e3c7b5d0af27ac1021e10d13" - integrity sha512-8bw4MY9WjdsD2aMtO0OzOCY3pXGYNx2d2FfHRVUKkiCPDWjKuOlhLVASS+pD7VkLTVjW268LYJHwsnPFlBpbAg== - text-segmentation@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/text-segmentation/-/text-segmentation-1.0.3.tgz#52a388159efffe746b24a63ba311b6ac9f2d7943" @@ -9293,11 +9339,16 @@ tslib@^1.8.1: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2.0.3, tslib@^2.1.0, tslib@^2.2.0: +tslib@^2.0.3, tslib@^2.1.0: version "2.3.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01" integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== +tslib@^2.5.3: + version "2.6.2" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" + integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== + tsutils@^3.21.0: version "3.21.0" resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" @@ -9354,15 +9405,27 @@ typescript@^4.5.5: resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.5.5.tgz#d8c953832d28924a9e3d37c73d729c846c5896f3" integrity sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA== +typewise-core@^1.2, typewise-core@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/typewise-core/-/typewise-core-1.2.0.tgz#97eb91805c7f55d2f941748fa50d315d991ef195" + integrity sha512-2SCC/WLzj2SbUwzFOzqMCkz5amXLlxtJqDKTICqg30x+2DZxcfZN2MvQZmGfXWKNWaKK9pBPsvkcwv8bF/gxKg== + +typewise@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/typewise/-/typewise-1.0.3.tgz#1067936540af97937cc5dcf9922486e9fa284651" + integrity sha512-aXofE06xGhaQSPzt8hlTY+/YWQhm9P0jYUp1f2XtmW/3Bk0qzXcyFWAtPoo2uTGQj1ZwbDuSyuxicq+aDo8lCQ== + dependencies: + typewise-core "^1.2.0" + typical@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/typical/-/typical-4.0.0.tgz#cbeaff3b9d7ae1e2bbfaf5a4e6f11eccfde94fc4" integrity sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw== -typical@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/typical/-/typical-5.2.0.tgz#4daaac4f2b5315460804f0acf6cb69c52bb93066" - integrity sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg== +typical@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/typical/-/typical-7.1.1.tgz#ba177ab7ab103b78534463ffa4c0c9754523ac1f" + integrity sha512-T+tKVNs6Wu7IWiAce5BgMd7OZfNYUndHwc5MknN+UHOudi7sGZzuHdCadllRuqJ3fPtgFtIH9+lt9qRv6lmpfA== unbzip2-stream@1.4.3: version "1.4.3" @@ -9395,6 +9458,16 @@ unicode-property-aliases-ecmascript@^2.0.0: resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz#0a36cb9a585c4f6abd51ad1deddb285c165297c8" integrity sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ== +union-value@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" + integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg== + dependencies: + arr-union "^3.1.0" + get-value "^2.0.6" + is-extendable "^0.1.1" + set-value "^2.0.1" + universalify@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" @@ -9476,14 +9549,7 @@ vary@~1.1.2: resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= -viewport-mercator-project@^7.0.4: - version "7.0.4" - resolved "https://registry.yarnpkg.com/viewport-mercator-project/-/viewport-mercator-project-7.0.4.tgz#67feec04135484bf424dd4890d630e82116b31e6" - integrity sha512-0jzpL6pIMocCKWg1C3mqi/N4UPgZC3FzwghEm1H+XsUo8hNZAyJc3QR7YqC816ibOR8aWT5pCsV+gCu8/BMJgg== - dependencies: - "@math.gl/web-mercator" "^3.5.5" - -vt-pbf@^3.1.1: +vt-pbf@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/vt-pbf/-/vt-pbf-3.1.3.tgz#68fd150756465e2edae1cc5c048e063916dcfaac" integrity sha512-2LzDFzt0mZKZ9IpVF2r69G9bXaP2Q2sArJCmcCgvfTdCCZzSyz4aCLoQyUilu37Ll56tCblIZrXFIjNUpGIlmA== @@ -9705,7 +9771,7 @@ whatwg-url@^8.0.0, whatwg-url@^8.5.0: tr46 "^2.1.0" webidl-conversions "^6.1.0" -which@^1.2.12, which@^1.2.9: +which@^1.2.12, which@^1.2.9, which@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== @@ -9741,13 +9807,10 @@ word-wrap@^1.2.3, word-wrap@~1.2.3: resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== -wordwrapjs@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/wordwrapjs/-/wordwrapjs-4.0.1.tgz#d9790bccfb110a0fc7836b5ebce0937b37a8b98f" - integrity sha512-kKlNACbvHrkpIw6oPeYDSmdCTu2hdMHoyXLTcUKala++lx5Y+wjJ/e474Jqv5abnVmwxw08DiTuHmw69lJGksA== - dependencies: - reduce-flatten "^2.0.0" - typical "^5.2.0" +wordwrapjs@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/wordwrapjs/-/wordwrapjs-5.1.0.tgz#4c4d20446dcc670b14fa115ef4f8fd9947af2b3a" + integrity sha512-JNjcULU2e4KJwUNv6CHgI46UvDGitb6dGryHajXTDiLgg1/RiGoPSDw4kZfYnwGtEXf2ZMeIewDQgFGzkCB2Sg== wrap-ansi@^7.0.0: version "7.0.0" From baf4f8dc1584130541ce0d1cc7fa00805a883ddc Mon Sep 17 00:00:00 2001 From: unclFedor <103448502+unclFedor@users.noreply.github.com> Date: Thu, 9 Nov 2023 13:54:14 +0100 Subject: [PATCH 02/40] feat: add arcgis map to viewer app (#311) * added arcgis map to viewer app * fixed unit test * fixed unit test --- package.json | 3 + .../arcgis-wrapper/arcgis-wrapper.spec.tsx | 20 ++ .../arcgis-wrapper/arcgis-wrapper.tsx | 42 ++++ .../layers-panel/map-options-panel.spec.tsx | 1 + src/constants/map-styles.ts | 5 + src/pages/viewer-app/viewer-app.tsx | 56 ++--- src/redux/slices/base-maps-slice.spec.ts | 54 +---- src/utils/testing-utils/e2e-layers-panel.tsx | 4 +- yarn.lock | 204 +++++++++++++++++- 9 files changed, 313 insertions(+), 76 deletions(-) create mode 100644 src/components/arcgis-wrapper/arcgis-wrapper.spec.tsx create mode 100644 src/components/arcgis-wrapper/arcgis-wrapper.tsx diff --git a/package.json b/package.json index dc6adcf3..6176355e 100644 --- a/package.json +++ b/package.json @@ -20,12 +20,15 @@ "author": "", "license": "ISC", "dependencies": { + "@arcgis/core": "^4.28.7", + "@deck.gl/arcgis": "^8.9.32", "@deck.gl/core": "^8.9.32", "@deck.gl/extensions": "^8.9.32", "@deck.gl/geo-layers": "^8.9.32", "@deck.gl/layers": "^8.9.32", "@deck.gl/mesh-layers": "^8.9.32", "@deck.gl/react": "^8.9.32", + "@esri/react-arcgis": "^5.2.0", "@fortawesome/fontawesome-svg-core": "^1.2.36", "@fortawesome/free-solid-svg-icons": "^5.15.4", "@fortawesome/react-fontawesome": "^0.1.17", diff --git a/src/components/arcgis-wrapper/arcgis-wrapper.spec.tsx b/src/components/arcgis-wrapper/arcgis-wrapper.spec.tsx new file mode 100644 index 00000000..8ebb244f --- /dev/null +++ b/src/components/arcgis-wrapper/arcgis-wrapper.spec.tsx @@ -0,0 +1,20 @@ +import { renderWithTheme } from "../../utils/testing-utils/render-with-theme"; +import { Map } from "@esri/react-arcgis"; + +jest.mock("@esri/react-arcgis", () => { + return { + Map: jest.fn().mockImplementation(() => <div></div>), + }; +}); + +const callRender = (renderFunc) => { + return renderFunc(<Map />); +}; + +describe("ArcGis Wrapper", () => { + it("Should be able to call ArcGis map", async () => { + callRender(renderWithTheme); + + expect(Map).toBeCalledTimes(1); + }); +}); diff --git a/src/components/arcgis-wrapper/arcgis-wrapper.tsx b/src/components/arcgis-wrapper/arcgis-wrapper.tsx new file mode 100644 index 00000000..db7a9317 --- /dev/null +++ b/src/components/arcgis-wrapper/arcgis-wrapper.tsx @@ -0,0 +1,42 @@ +import { Map as ArcGisMap } from "@esri/react-arcgis"; +import { loadArcGISModules } from "@deck.gl/arcgis"; +import { useEffect, useState } from "react"; + +function DeckGLLayer(props) { + const [layer, setLayer] = useState(null); + + useEffect(() => { + let deckLayer; + loadArcGISModules().then(({ DeckLayer }) => { + deckLayer = new DeckLayer({}); + setLayer(deckLayer); + props.map.add(deckLayer); + }); + return () => deckLayer && props.map.remove(deckLayer); + }, []); + + if (layer) { + // @ts-expect-error @deck.gl/arcgis has no types + layer.deck.set(props); + } + + return null; +} + +export function ArcgisWrapper() { + const layers = []; + + return ( + <ArcGisMap + mapProperties={{ basemap: "dark-gray-vector" }} + viewProperties={{ + center: [-122.44, 37.75], + zoom: 12, + }} + > + <DeckGLLayer layers={layers} /> + </ArcGisMap> + ); +} + +export default ArcgisWrapper; diff --git a/src/components/layers-panel/map-options-panel.spec.tsx b/src/components/layers-panel/map-options-panel.spec.tsx index 8f3130a1..afd1cbfc 100644 --- a/src/components/layers-panel/map-options-panel.spec.tsx +++ b/src/components/layers-panel/map-options-panel.spec.tsx @@ -180,6 +180,7 @@ describe("Map Options Panel", () => { name: "Light", }, { id: "Terrain", mapUrl: "", name: "Terrain" }, + { id: "ArcGis", name: "ArcGis", mapUrl: "" }, { id: "first", mapUrl: "https://first-url.com", name: "first name" }, ]); diff --git a/src/constants/map-styles.ts b/src/constants/map-styles.ts index 0bbcaf67..fbc40d07 100644 --- a/src/constants/map-styles.ts +++ b/src/constants/map-styles.ts @@ -14,6 +14,11 @@ export const BASE_MAPS: BaseMap[] = [ "https://basemaps.cartocdn.com/gl/positron-nolabels-gl-style/style.json", }, { id: "Terrain", name: "Terrain", mapUrl: "" }, + { + id: "ArcGis", + name: "ArcGis", + mapUrl: "", + }, ]; export const CONTRAST_MAP_STYLES = { diff --git a/src/pages/viewer-app/viewer-app.tsx b/src/pages/viewer-app/viewer-app.tsx index 0a95046f..cfdd2ae7 100644 --- a/src/pages/viewer-app/viewer-app.tsx +++ b/src/pages/viewer-app/viewer-app.tsx @@ -66,9 +66,9 @@ import { import { useAppDispatch, useAppSelector } from "../../redux/hooks"; import { setDragMode } from "../../redux/slices/drag-mode-slice"; import { setColorsByAttrubute } from "../../redux/slices/colors-by-attribute-slice"; -import { - setInitialBaseMaps, -} from "../../redux/slices/base-maps-slice"; +import { setInitialBaseMaps } from "../../redux/slices/base-maps-slice"; +import { selectSelectedBaseMapId } from "../../redux/slices/base-maps-slice"; +import { ArcgisWrapper } from "../../components/arcgis-wrapper/arcgis-wrapper"; const INITIAL_VIEW_STATE = { main: { @@ -100,6 +100,7 @@ export const ViewerApp = () => { const [isAttributesLoading, setAttributesLoading] = useState(false); const flattenedSublayers = useAppSelector(selectLayers); const bslSublayers = useAppSelector(selectSublayers); + const selectedBaseMapId = useAppSelector(selectSelectedBaseMapId); const [tilesetsStats, setTilesetsStats] = useState(initStats()); const [memoryStats, setMemoryStats] = useState<Stats | null>(null); const [updateStatsNumber, setUpdateStatsNumber] = useState<number>(0); @@ -538,29 +539,32 @@ export const ViewerApp = () => { return ( <MapArea> {selectedFeatureAttributes && renderAttributesPanel()} - <DeckGlWrapper - id="viewer-deck-container" - parentViewState={{ - ...viewState, - main: { - ...viewState.main, - }, - }} - pickable={isLayerPickable()} - layers3d={layers3d} - lastLayerSelectedId={selectedLayerIds[0] || ""} - loadedTilesets={loadedTilesets} - selectedTilesetBasePath={selectedTilesetBasePath} - selectedIndex={selectedFeatureIndex} - onAfterRender={handleOnAfterRender} - getTooltip={getTooltip} - onClick={handleClick} - onViewStateChange={onViewStateChangeHandler} - onTilesetLoad={onTilesetLoad} - onTileLoad={onTileLoad} - onWebGLInitialized={onWebGLInitialized} - preventTransitions={preventTransitions} - /> + {selectedBaseMapId !== "ArcGis" && ( + <DeckGlWrapper + id="viewer-deck-container" + parentViewState={{ + ...viewState, + main: { + ...viewState.main, + }, + }} + pickable={isLayerPickable()} + layers3d={layers3d} + lastLayerSelectedId={selectedLayerIds[0] || ""} + loadedTilesets={loadedTilesets} + selectedTilesetBasePath={selectedTilesetBasePath} + selectedIndex={selectedFeatureIndex} + onAfterRender={handleOnAfterRender} + getTooltip={getTooltip} + onClick={handleClick} + onViewStateChange={onViewStateChangeHandler} + onTilesetLoad={onTilesetLoad} + onTileLoad={onTileLoad} + onWebGLInitialized={onWebGLInitialized} + preventTransitions={preventTransitions} + /> + )} + {selectedBaseMapId === "ArcGis" && <ArcgisWrapper />} {layout !== Layout.Mobile && ( <OnlyToolsPanelWrapper layout={layout}> diff --git a/src/redux/slices/base-maps-slice.spec.ts b/src/redux/slices/base-maps-slice.spec.ts index f102075b..ceded39c 100644 --- a/src/redux/slices/base-maps-slice.spec.ts +++ b/src/redux/slices/base-maps-slice.spec.ts @@ -8,6 +8,7 @@ import reducer, { setSelectedBaseMaps, deleteBaseMaps, } from "./base-maps-slice"; +import { BASE_MAPS } from "../../constants/map-styles"; jest.mock("@loaders.gl/i3s", () => { return jest.fn().mockImplementation(() => { @@ -18,21 +19,7 @@ jest.mock("@loaders.gl/i3s", () => { describe("slice: base-maps", () => { it("Reducer should return the initial state", () => { expect(reducer(undefined, { type: undefined })).toEqual({ - baseMap: [ - { - id: "Dark", - mapUrl: - "https://basemaps.cartocdn.com/gl/dark-matter-nolabels-gl-style/style.json", - name: "Dark", - }, - { - id: "Light", - mapUrl: - "https://basemaps.cartocdn.com/gl/positron-nolabels-gl-style/style.json", - name: "Light", - }, - { id: "Terrain", mapUrl: "", name: "Terrain" }, - ], + baseMap: BASE_MAPS, selectedBaseMap: "Dark", }); }); @@ -168,21 +155,7 @@ describe("slice: base-maps", () => { }; expect(reducer(previousState, setInitialBaseMaps())).toEqual({ - baseMap: [ - { - id: "Dark", - mapUrl: - "https://basemaps.cartocdn.com/gl/dark-matter-nolabels-gl-style/style.json", - name: "Dark", - }, - { - id: "Light", - mapUrl: - "https://basemaps.cartocdn.com/gl/positron-nolabels-gl-style/style.json", - name: "Light", - }, - { id: "Terrain", mapUrl: "", name: "Terrain" }, - ], + baseMap: BASE_MAPS, selectedBaseMap: "Dark", }); }); @@ -191,21 +164,7 @@ describe("slice: base-maps", () => { const store = setupStore(); const state = store.getState(); expect(selectSelectedBaseMapId(state)).toEqual("Dark"); - expect(selectBaseMaps(state)).toEqual([ - { - id: "Dark", - mapUrl: - "https://basemaps.cartocdn.com/gl/dark-matter-nolabels-gl-style/style.json", - name: "Dark", - }, - { - id: "Light", - mapUrl: - "https://basemaps.cartocdn.com/gl/positron-nolabels-gl-style/style.json", - name: "Light", - }, - { id: "Terrain", mapUrl: "", name: "Terrain" }, - ]); + expect(selectBaseMaps(state)).toEqual(BASE_MAPS); }); it("Selectors should return updated value", () => { @@ -229,6 +188,11 @@ describe("slice: base-maps", () => { name: "Light", }, { id: "Terrain", mapUrl: "", name: "Terrain" }, + { + id: "ArcGis", + name: "ArcGis", + mapUrl: "", + }, { id: "first", mapUrl: "https://first-url.com", diff --git a/src/utils/testing-utils/e2e-layers-panel.tsx b/src/utils/testing-utils/e2e-layers-panel.tsx index 3bece459..1c96de31 100644 --- a/src/utils/testing-utils/e2e-layers-panel.tsx +++ b/src/utils/testing-utils/e2e-layers-panel.tsx @@ -65,8 +65,8 @@ export const checkLayersPanel = async ( `${panelId} > :nth-child(4) > :first-child > :nth-child(2) > div`, (nodes) => nodes.map((node) => node.innerText) ); - expect(baseMapsNames.length).toBe(3); - expect(baseMapsNames).toEqual(["Dark", "Light", "Terrain"]); + expect(baseMapsNames.length).toBe(4); + expect(baseMapsNames).toEqual(["Dark", "Light", "Terrain", "ArcGis"]); // Dark is selected const darkMapBackground = await page.$eval( diff --git a/yarn.lock b/yarn.lock index 0ff69e26..6579ca76 100644 --- a/yarn.lock +++ b/yarn.lock @@ -26,6 +26,20 @@ "@jridgewell/gen-mapping" "^0.1.0" "@jridgewell/trace-mapping" "^0.3.9" +"@arcgis/core@^4.28.7": + version "4.28.7" + resolved "https://registry.yarnpkg.com/@arcgis/core/-/core-4.28.7.tgz#706510632e76d529a86da6be816b48bd8fce7f60" + integrity sha512-uZtD7xI3qYWPkxJWoj6FwTfFxJJMKpj1s5vRn7vBpGv/eLl78OdCXMvb1Ce3302+5ShwC08WppQmERvISSkpUA== + dependencies: + "@esri/arcgis-html-sanitizer" "~3.0.1" + "@esri/calcite-colors" "~6.1.0" + "@esri/calcite-components" "^1.9.2" + "@popperjs/core" "~2.11.8" + "@zip.js/zip.js" "~2.7.29" + focus-trap "~7.5.3" + luxon "~3.4.3" + sortablejs "~1.15.0" + "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.16.7": version "7.16.7" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.7.tgz#44416b6bd7624b998f5b1af5d470856c40138789" @@ -1666,6 +1680,14 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== +"@deck.gl/arcgis@^8.9.32": + version "8.9.32" + resolved "https://registry.yarnpkg.com/@deck.gl/arcgis/-/arcgis-8.9.32.tgz#d681a0020e6785a46125d3e66733f5316a7e9a1c" + integrity sha512-OivrBVMqVPkDl7Unm6MXCceOm7eqB1z/YLj0HgEXy5S61k9ek/0uUbCe2zT1eqJ2sWvzIkG+E6TVThHfo1OIVQ== + dependencies: + "@babel/runtime" "^7.0.0" + esri-loader "^3.3.0" + "@deck.gl/core@^8.9.32": version "8.9.32" resolved "https://registry.yarnpkg.com/@deck.gl/core/-/core-8.9.32.tgz#45285a662068b08ebf04bf4509597c97adb923b4" @@ -1793,6 +1815,60 @@ minimatch "^3.0.4" strip-json-comments "^3.1.1" +"@esri/arcgis-html-sanitizer@~3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@esri/arcgis-html-sanitizer/-/arcgis-html-sanitizer-3.0.1.tgz#a4feaf3744bdd532012593fdb929b376a22c39cd" + integrity sha512-cwZJwsYCJZwtBQU2AmaiIVFg5nZcVwInPYja1/OgC9iKYO+ytZRoc5h+0S9/ygbFNoS8Nd0RX9A85stLX/BgiA== + dependencies: + xss "1.0.13" + +"@esri/calcite-colors@~6.1.0": + version "6.1.0" + resolved "https://registry.yarnpkg.com/@esri/calcite-colors/-/calcite-colors-6.1.0.tgz#2d75e859a88772d8de91ccae40cbe29b8a4d27b8" + integrity sha512-wHQYWFtDa6c328EraXEVZvgOiaQyYr0yuaaZ0G3cB4C3lSkWefW34L/e5TLAhtuG3zJ/wR6pl5X1YYNfBc0/4Q== + +"@esri/calcite-components@^1.9.2": + version "1.10.0" + resolved "https://registry.yarnpkg.com/@esri/calcite-components/-/calcite-components-1.10.0.tgz#2183e2ea53914c65acc9e6c9fe5f313d88479e2c" + integrity sha512-nKTwU7hseSAXTqEQelVfo+qDa5jCGvabky4atRsJxROkHbSQkhdFFfwOrrffHOr9CtZBxtvZhfh/Tb6Nky15hw== + dependencies: + "@floating-ui/dom" "1.5.3" + "@stencil/core" "2.22.3" + "@types/color" "3.0.4" + color "4.2.3" + composed-offset-position "0.0.4" + dayjs "1.11.10" + focus-trap "7.5.4" + form-request-submit-polyfill "2.0.0" + lodash-es "4.17.21" + sortablejs "1.15.0" + timezone-groups "0.8.0" + +"@esri/react-arcgis@^5.2.0": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@esri/react-arcgis/-/react-arcgis-5.2.0.tgz#fcdb2ff3ddbb85b66bd5f082e0335c5c95ad120c" + integrity sha512-85sSih2lI4ISB9ISu77fxIPUg32UaZjM+SrwaJkxwGzdKnmyhdBqOHMm3kTqjLGPCmuDk9xtEDJWqdxxskkLzQ== + +"@floating-ui/core@^1.4.2": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.5.0.tgz#5c05c60d5ae2d05101c3021c1a2a350ddc027f8c" + integrity sha512-kK1h4m36DQ0UHGj5Ah4db7R0rHemTqqO0QLvUqi1/mUUp3LuAWbWxdxSIf/XsnH9VS6rRVPLJCncjRzUvyCLXg== + dependencies: + "@floating-ui/utils" "^0.1.3" + +"@floating-ui/dom@1.5.3": + version "1.5.3" + resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.5.3.tgz#54e50efcb432c06c23cd33de2b575102005436fa" + integrity sha512-ClAbQnEqJAKCJOEbbLo5IUlZHkNszqhuxS4fHAVxRPXPya6Ysf2G8KypnYcOTpx6I8xcgF9bbHb6g/2KpbV8qA== + dependencies: + "@floating-ui/core" "^1.4.2" + "@floating-ui/utils" "^0.1.3" + +"@floating-ui/utils@^0.1.3": + version "0.1.6" + resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.1.6.tgz#22958c042e10b67463997bd6ea7115fe28cbcaf9" + integrity sha512-OfX7E2oUDYxtBvsuS4e/jSn4Q9Qb6DzgeYtsAdkPZ47znpoNsMgZw0+tVijiv3uGNR6dgNlty6r9rzIzHjtd/A== + "@fortawesome/fontawesome-common-types@^0.2.36": version "0.2.36" resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.36.tgz#b44e52db3b6b20523e0c57ef8c42d315532cb903" @@ -2682,6 +2758,11 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" +"@popperjs/core@~2.11.8": + version "2.11.8" + resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.8.tgz#6b79032e760a0899cd4204710beede972a3a185f" + integrity sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A== + "@probe.gl/env@3.5.0", "@probe.gl/env@^3.5.0": version "3.5.0" resolved "https://registry.yarnpkg.com/@probe.gl/env/-/env-3.5.0.tgz#c6d8fbf414fda3eba7b3813cc274e76245216fe0" @@ -2767,6 +2848,11 @@ dependencies: "@sinonjs/commons" "^1.7.0" +"@stencil/core@2.22.3": + version "2.22.3" + resolved "https://registry.yarnpkg.com/@stencil/core/-/core-2.22.3.tgz#83987e20bba855c450f6d6780e3a20192603f13f" + integrity sha512-kmVA0M/HojwsfkeHsifvHVIYe4l5tin7J5+DLgtl8h6WWfiMClND5K3ifCXXI2ETDNKiEk21p6jql3Fx9o2rng== + "@svgr/babel-plugin-add-jsx-attribute@^6.0.0": version "6.0.0" resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-6.0.0.tgz#bd6d1ff32a31b82b601e73672a789cc41e84fe18" @@ -3053,6 +3139,25 @@ dependencies: "@types/node" "*" +"@types/color-convert@*": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@types/color-convert/-/color-convert-2.0.2.tgz#a5fa5da9b866732f8bf86b01964869011e2a2356" + integrity sha512-KGRIgCxwcgazts4MXRCikPbIMzBpjfdgEZSy8TRHU/gtg+f9sOfHdtK8unPfxIoBtyd2aTTwINVLSNENlC8U8A== + dependencies: + "@types/color-name" "*" + +"@types/color-name@*": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.2.tgz#bdeeb6fdcb78969033767951ab0cb26c7514a658" + integrity sha512-JWO/ZyxTKk0bLuOhAavGjnwLR73rUE7qzACnU7gMeyA/gdrSHm2xJwqNPipw2MtaZUaqQ2UG/q7pP6AQiZ8mqw== + +"@types/color@3.0.4": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@types/color/-/color-3.0.4.tgz#53ceca0946660c7779442948878172c6ace13777" + integrity sha512-OpisS4bqJJwbkkQRrMvURf3DOxBoAg9mysHYI7WgrWpSYHqHGKYBULHdz4ih77SILcLDo/zyHGFyfIl9yb8NZQ== + dependencies: + "@types/color-convert" "*" + "@types/command-line-args@5.2.0": version "5.2.0" resolved "https://registry.yarnpkg.com/@types/command-line-args/-/command-line-args-5.2.0.tgz#adbb77980a1cc376bb208e3f4142e907410430f6" @@ -3668,6 +3773,11 @@ resolved "https://registry.yarnpkg.com/@zeit/schemas/-/schemas-2.6.0.tgz#004e8e553b4cd53d538bd38eac7bcbf58a867fe3" integrity sha512-uUrgZ8AxS+Lio0fZKAipJjAh415JyrOZowliZAzmnJSsf7piVL5w+G0+gFJ0KSu3QRhvui/7zuvpLz03YjXAhg== +"@zip.js/zip.js@~2.7.29": + version "2.7.30" + resolved "https://registry.yarnpkg.com/@zip.js/zip.js/-/zip.js-2.7.30.tgz#88db2d23d682a73c1fc649d1df7012e508591e9c" + integrity sha512-nhMvQCj+TF1ATBqYzFds7v+yxPBhdDYHh8J341KtC1D2UrVBUIYcYK4Jy1/GiTsxOXEiKOXSUxvPG/XR+7jMqw== + abab@^2.0.3, abab@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.5.tgz#c0b678fb32d60fc1219c784d6a826fe385aeb79a" @@ -4471,11 +4581,27 @@ color-name@1.1.3: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= -color-name@~1.1.4: +color-name@^1.0.0, color-name@~1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== +color-string@^1.9.0: + version "1.9.1" + resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.9.1.tgz#4467f9146f036f855b764dfb5bf8582bf342c7a4" + integrity sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg== + dependencies: + color-name "^1.0.0" + simple-swizzle "^0.2.2" + +color@4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/color/-/color-4.2.3.tgz#d781ecb5e57224ee43ea9627560107c0e0c6463a" + integrity sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A== + dependencies: + color-convert "^2.0.1" + color-string "^1.9.0" + colorette@^2.0.10, colorette@^2.0.14: version "2.0.16" resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.16.tgz#713b9af84fdb000139f04546bd4a93f62a5085da" @@ -4508,7 +4634,7 @@ command-line-usage@7.0.1, command-line-usage@^7.0.0: table-layout "^3.0.0" typical "^7.1.1" -commander@^2.20.0: +commander@^2.20.0, commander@^2.20.3: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== @@ -4533,6 +4659,11 @@ commondir@^1.0.1: resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= +composed-offset-position@0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/composed-offset-position/-/composed-offset-position-0.0.4.tgz#ca8854abf15e3c235ecf4df125a27fe88af76ea4" + integrity sha512-vMlvu1RuNegVE0YsCDSV/X4X10j56mq7PCIyOKK74FxkXzGLwhOUmdkJLSdOBOMwWycobGUMgft2lp+YgTe8hw== + compressible@~2.0.14, compressible@~2.0.16: version "2.0.18" resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba" @@ -4775,6 +4906,11 @@ cssesc@^3.0.0: resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== +cssfilter@0.0.10: + version "0.0.10" + resolved "https://registry.yarnpkg.com/cssfilter/-/cssfilter-0.0.10.tgz#c6d2672632a2e5c83e013e6864a42ce8defd20ae" + integrity sha512-FAaLDaplstoRsDR8XGYH51znUN0UY7nMc6Z9/fvE8EXGwvJE9hu7W2vHwx1+bd6gCYnln9nLbzxFTrcO9YQDZw== + csso@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/csso/-/csso-4.2.0.tgz#ea3a561346e8dc9f546d6febedd50187cf389529" @@ -4882,6 +5018,11 @@ data-urls@^2.0.0: whatwg-mimetype "^2.3.0" whatwg-url "^8.0.0" +dayjs@1.11.10: + version "1.11.10" + resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.10.tgz#68acea85317a6e164457d6d6947564029a6a16a0" + integrity sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ== + debug@2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -5349,6 +5490,11 @@ esrecurse@^4.3.0: dependencies: estraverse "^5.2.0" +esri-loader@^3.3.0: + version "3.7.0" + resolved "https://registry.yarnpkg.com/esri-loader/-/esri-loader-3.7.0.tgz#be2432664f53d4878b34ab903499248bbca3e087" + integrity sha512-cB1Sw9EQjtW4mtT7eFBjn/6VaaIWNTjmTd2asnnEyuZk1xVSFRMCfLZSBSjZM7ZarDcVu5WIjOP0t0MYVu4hVQ== + estraverse@^4.1.1: version "4.3.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" @@ -5685,6 +5831,13 @@ flatted@^3.1.0: resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.5.tgz#76c8584f4fc843db64702a6bd04ab7a8bd666da3" integrity sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg== +focus-trap@7.5.4, focus-trap@~7.5.3: + version "7.5.4" + resolved "https://registry.yarnpkg.com/focus-trap/-/focus-trap-7.5.4.tgz#6c4e342fe1dae6add9c2aa332a6e7a0bbd495ba2" + integrity sha512-N7kHdlgsO/v+iD/dMoJKtsSqs5Dz/dXZVebRgJw23LDk+jMi/974zyiOYDziY2JPp8xivq9BmUGwIJMiuSBi7w== + dependencies: + tabbable "^6.2.0" + follow-redirects@^1.0.0: version "1.14.7" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.7.tgz#2004c02eb9436eee9a21446a6477debf17e81685" @@ -5721,6 +5874,11 @@ form-data@^3.0.0: combined-stream "^1.0.8" mime-types "^2.1.12" +form-request-submit-polyfill@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/form-request-submit-polyfill/-/form-request-submit-polyfill-2.0.0.tgz#2557c9c2385989954461e327e81619993b5bce96" + integrity sha512-p0+M92y2gFnP0AuuL8VJ0GYVzAT0bYp3GsSkmPFhvUopdnfDLP/9xplQTBBc4w8qOjKRzdK7GaFcdL9IhlXdTQ== + forwarded@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" @@ -6262,6 +6420,11 @@ is-arrayish@^0.2.1: resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= +is-arrayish@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" + integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ== + is-binary-path@~2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" @@ -7162,7 +7325,7 @@ locate-path@^5.0.0: dependencies: p-locate "^4.1.0" -lodash-es@^4.17.15: +lodash-es@4.17.21, lodash-es@^4.17.15: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee" integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw== @@ -7223,6 +7386,11 @@ lru-cache@^6.0.0: dependencies: yallist "^4.0.0" +luxon@~3.4.3: + version "3.4.3" + resolved "https://registry.yarnpkg.com/luxon/-/luxon-3.4.3.tgz#8ddf0358a9492267ffec6a13675fbaab5551315d" + integrity sha512-tFWBiv3h7z+T/tDaoxA8rqTxy1CHV6gHS//QdaH4pulbq/JuBSGgQspQQqcgnwdAx6pNI7cmvz5Sv/addzHmUg== + lz-string@^1.4.4: version "1.4.4" resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.4.4.tgz#c0d8eaf36059f705796e1e344811cf4c498d3a26" @@ -8835,6 +9003,13 @@ signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.6: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== +simple-swizzle@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a" + integrity sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg== + dependencies: + is-arrayish "^0.3.1" + sisteransi@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" @@ -8881,6 +9056,11 @@ sort-object@^3.0.3: sort-desc "^0.2.0" union-value "^1.0.1" +sortablejs@1.15.0, sortablejs@~1.15.0: + version "1.15.0" + resolved "https://registry.yarnpkg.com/sortablejs/-/sortablejs-1.15.0.tgz#53230b8aa3502bb77a29e2005808ffdb4a5f7e2a" + integrity sha512-bv9qgVMjUMf89wAvM6AxVvS/4MX3sPeN0+agqShejLU5z5GX4C75ow1O2e5k4L6XItUyAK3gH6AxSbXrOM5e8w== + source-map-js@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" @@ -9155,6 +9335,11 @@ symbol-tree@^3.2.4: resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== +tabbable@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/tabbable/-/tabbable-6.2.0.tgz#732fb62bc0175cfcec257330be187dcfba1f3b97" + integrity sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew== + table-layout@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/table-layout/-/table-layout-3.0.2.tgz#69c2be44388a5139b48c59cf21e73b488021769a" @@ -9266,6 +9451,11 @@ thunky@^1.0.2: resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d" integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA== +timezone-groups@0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/timezone-groups/-/timezone-groups-0.8.0.tgz#b7bd35322939bed7cfbf0624cc3eeefd0910800d" + integrity sha512-t7E/9sPfCU0m0ZbS7Cqw52D6CB/UyeaiIBmyJCokI1SyOyOgA/ESiQ/fbreeFaUG9QSenGlZSSk/7rEbkipbOA== + tinycolor2@^1.4.1: version "1.4.2" resolved "https://registry.yarnpkg.com/tinycolor2/-/tinycolor2-1.4.2.tgz#3f6a4d1071ad07676d7fa472e1fac40a719d8803" @@ -9861,6 +10051,14 @@ xmlchars@^2.2.0: resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw== +xss@1.0.13: + version "1.0.13" + resolved "https://registry.yarnpkg.com/xss/-/xss-1.0.13.tgz#6e48f616128b39f366dfadc57411e1eb5b341c6c" + integrity sha512-clu7dxTm1e8Mo5fz3n/oW3UCXBfV89xZ72jM8yzo1vR/pIS0w3sgB3XV2H8Vm6zfGnHL0FzvLJPJEBhd86/z4Q== + dependencies: + commander "^2.20.3" + cssfilter "0.0.10" + y18n@^5.0.5: version "5.0.8" resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" From e75fb3c97b74545039d8b301a7eb0582d938a9d6 Mon Sep 17 00:00:00 2001 From: unclFedor <103448502+unclFedor@users.noreply.github.com> Date: Thu, 16 Nov 2023 12:26:58 +0100 Subject: [PATCH 03/40] added layer to arcgis map (#312) --- .../arcgis-wrapper/arcgis-wrapper.tsx | 124 +++++++++++++----- src/index.html | 4 + 2 files changed, 92 insertions(+), 36 deletions(-) diff --git a/src/components/arcgis-wrapper/arcgis-wrapper.tsx b/src/components/arcgis-wrapper/arcgis-wrapper.tsx index db7a9317..6ae2ce8d 100644 --- a/src/components/arcgis-wrapper/arcgis-wrapper.tsx +++ b/src/components/arcgis-wrapper/arcgis-wrapper.tsx @@ -1,42 +1,94 @@ -import { Map as ArcGisMap } from "@esri/react-arcgis"; import { loadArcGISModules } from "@deck.gl/arcgis"; -import { useEffect, useState } from "react"; +import { useEffect, useState, useRef } from "react"; +import styled from "styled-components"; +import { INITIAL_EXAMPLE } from "../../constants/i3s-examples"; -function DeckGLLayer(props) { - const [layer, setLayer] = useState(null); +export const StyledMapContainer = styled.div` + overflow: hidden; + position: absolute; + width: 100%; + height: 100%; + left: 0; + top: 0; +`; + +const INITIAL_VIEW_STATE = { + longitude: -122.44, + latitude: 37.78, + bearing: 0, +}; + +export const ArcgisWrapper = () => { + const mapContainer = useRef<HTMLDivElement | null>(null); + const [sceneView, setSceneView] = useState<unknown | null>(null); + const { longitude, latitude, bearing } = { + longitude: INITIAL_VIEW_STATE.longitude, + latitude: INITIAL_VIEW_STATE.latitude, + bearing: INITIAL_VIEW_STATE.bearing, + }; + const isLoadingRef = useRef<boolean>(false); + + useEffect(() => { + if (!sceneView) { + return; + } + // @ts-expect-error no ArcGIS types + sceneView.goTo([longitude, latitude], { animate: false }); + }, [longitude, latitude, sceneView]); useEffect(() => { - let deckLayer; - loadArcGISModules().then(({ DeckLayer }) => { - deckLayer = new DeckLayer({}); - setLayer(deckLayer); - props.map.add(deckLayer); - }); - return () => deckLayer && props.map.remove(deckLayer); - }, []); - - if (layer) { - // @ts-expect-error @deck.gl/arcgis has no types - layer.deck.set(props); - } - - return null; -} - -export function ArcgisWrapper() { - const layers = []; - - return ( - <ArcGisMap - mapProperties={{ basemap: "dark-gray-vector" }} - viewProperties={{ - center: [-122.44, 37.75], - zoom: 12, - }} - > - <DeckGLLayer layers={layers} /> - </ArcGisMap> - ); -} + if (mapContainer.current == null) { + return; + } + if (sceneView || isLoadingRef.current) { + return; + } + isLoadingRef.current = true; + let deckRenderer: unknown; + loadArcGISModules([ + "esri/Map", + "esri/views/SceneView", + "esri/views/3d/externalRenderers", + "esri/layers/SceneLayer", + ]).then( + ({ + DeckRenderer, + modules: [ArcGISMap, SceneView, externalRenderers, SceneLayer], + }) => { + const map = new ArcGISMap({ + basemap: "dark-gray-vector", + }); + + const sceneView = new SceneView({ + container: mapContainer.current, + map: map, + environment: { + atmosphereEnabled: false, + starsEnabled: false, + }, + qualityProfile: "high", + camera: { + position: { x: longitude, y: latitude, z: 100 }, + heading: 10, + tilt: 71, + }, + ui: { components: ["attribution"] }, + viewingMode: "local", + }); + setSceneView(sceneView); + const sceneLayer = new SceneLayer({ + url: INITIAL_EXAMPLE.url, + popupEnabled: false, + }); + map.add(sceneLayer); + + deckRenderer = new DeckRenderer(sceneView, sceneLayer); + externalRenderers.add(sceneView, deckRenderer); + } + ); + }, [sceneView, mapContainer, bearing, latitude, longitude]); + + return <StyledMapContainer ref={mapContainer} />; +}; export default ArcgisWrapper; diff --git a/src/index.html b/src/index.html index 4d665028..c0011577 100644 --- a/src/index.html +++ b/src/index.html @@ -3,6 +3,10 @@ <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> + <link + rel="stylesheet" + href="https://js.arcgis.com/4.27/esri/themes/light/main.css" + /> <title>I3S Explorer From fea25eef9d4cda5156f60efdef1d03bfeed5ab74 Mon Sep 17 00:00:00 2001 From: unclFedor <103448502+unclFedor@users.noreply.github.com> Date: Thu, 23 Nov 2023 14:22:24 +0100 Subject: [PATCH 04/40] fix: controls on arcgis map (#315) * fixed controls on arcgis map * fixed test issue * fixed layer changing * fixed inspection's comments * restored renderBoundingVolumeLayer * fixed redux hook issue --- .../arcgis-wrapper/arcgis-wrapper.tsx | 793 ++++++++++++++++-- .../deck-gl-wrapper/deck-gl-wrapper.tsx | 6 +- .../map-control-panel/map-control-panel.tsx | 30 +- .../use-arcgis-hook/use-arcgis-hook.spec.ts | 13 + src/hooks/use-arcgis-hook/use-arcgis-hook.ts | 106 +++ src/pages/viewer-app/viewer-app.tsx | 53 +- 6 files changed, 895 insertions(+), 106 deletions(-) create mode 100644 src/hooks/use-arcgis-hook/use-arcgis-hook.spec.ts create mode 100644 src/hooks/use-arcgis-hook/use-arcgis-hook.ts diff --git a/src/components/arcgis-wrapper/arcgis-wrapper.tsx b/src/components/arcgis-wrapper/arcgis-wrapper.tsx index 6ae2ce8d..c817a85b 100644 --- a/src/components/arcgis-wrapper/arcgis-wrapper.tsx +++ b/src/components/arcgis-wrapper/arcgis-wrapper.tsx @@ -1,7 +1,64 @@ -import { loadArcGISModules } from "@deck.gl/arcgis"; -import { useEffect, useState, useRef } from "react"; +import { useArcgis } from "../../hooks/use-arcgis-hook/use-arcgis-hook"; +import { LineLayer, ScatterplotLayer } from "@deck.gl/layers"; +import { TerrainLayer, Tile3DLayer } from "@deck.gl/geo-layers"; +import { Tile3D, Tileset3D } from "@loaders.gl/tiles"; +import { I3SLoader, SceneLayer3D } from "@loaders.gl/i3s"; +import { CesiumIonLoader, Tiles3DLoader } from "@loaders.gl/3d-tiles"; +import { + FlyToInterpolator, + COORDINATE_SYSTEM, + MapView, + WebMercatorViewport, + PickingInfo, +} from "@deck.gl/core"; +import { useEffect, useMemo, useState, useRef } from "react"; +import { + NormalsDebugData, + ViewStateSet, + LoadOptions, + TilesetType, + MinimapPosition, +} from "../../types"; +import { BoundingVolumeLayer } from "../../layers"; +import ColorMap from "../../utils/debug/colors-map"; +import { + selectDebugTextureForTile, + selectDebugTextureForTileset, + selectOriginalTextureForTile, + selectOriginalTextureForTileset, +} from "../../utils/debug/texture-selector-utils"; +import { getElevationByCentralTile } from "../../utils/terrain-elevation"; +import { getFrustumBounds } from "../../utils/debug/frustum-utils"; +import { buildMinimapData } from "../../utils/debug/build-minimap-data"; +import { + getNormalSourcePosition, + getNormalTargetPosition, +} from "../../utils/debug/normals-utils"; +import { getLonLatWithElevationOffset } from "../../utils/elevation-utils"; + +import { useAppDispatch, useAppSelector } from "../../redux/hooks"; +import { selectColorsByAttribute } from "../../redux/slices/colors-by-attribute-slice"; +import { selectDragMode } from "../../redux/slices/drag-mode-slice"; +import { + fetchUVDebugTexture, + selectUVDebugTexture, +} from "../../redux/slices/uv-debug-texture-slice"; +import { + selectMiniMap, + selectMiniMapViewPort, + selectBoundingVolume, + selectLoadTiles, + selectShowUVDebugTexture, + selectWireframe, + selectTileColorMode, + selectBoundingVolumeColorMode, + selectBoundingVolumeType, +} from "../../redux/slices/debug-options-slice"; +import { + selectBaseMaps, + selectSelectedBaseMapId, +} from "../../redux/slices/base-maps-slice"; import styled from "styled-components"; -import { INITIAL_EXAMPLE } from "../../constants/i3s-examples"; export const StyledMapContainer = styled.div` overflow: hidden; @@ -12,82 +69,690 @@ export const StyledMapContainer = styled.div` top: 0; `; +const TRANSITION_DURAITON = 4000; const INITIAL_VIEW_STATE = { - longitude: -122.44, - latitude: 37.78, + longitude: -120, + latitude: 34, + pitch: 45, + maxPitch: 90, bearing: 0, + minZoom: 2, + maxZoom: 30, + zoom: 14.5, + transitionDuration: 0, + transitionInterpolator: null, }; -export const ArcgisWrapper = () => { - const mapContainer = useRef(null); - const [sceneView, setSceneView] = useState(null); - const { longitude, latitude, bearing } = { - longitude: INITIAL_VIEW_STATE.longitude, - latitude: INITIAL_VIEW_STATE.latitude, - bearing: INITIAL_VIEW_STATE.bearing, - }; - const isLoadingRef = useRef(false); +// https://github.com/tilezen/joerd/blob/master/docs/use-service.md#additional-amazon-s3-endpoints +const MAPZEN_TERRAIN_IMAGES = `https://s3.amazonaws.com/elevation-tiles-prod/terrarium/{z}/{x}/{y}.png`; +const ARCGIS_STREET_MAP_SURFACE_IMAGES = + "https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}"; +const MAPZEN_ELEVATION_DECODE_PARAMETERS = { + rScaler: 256, + gScaler: 1, + bScaler: 1 / 256, + offset: -32768, +}; +const TERRAIN_LAYER_MAX_ZOOM = 15; + +const DEFAULT_BG_OPACITY = 100; + +const NORMALS_COLOR = [255, 0, 0]; + +const colorMap = new ColorMap(); + +type ArcGisMapProps = { + /** DeckGL component id */ + id?: string; + /** + * View state controlled by parent component + * if is not set `viewState` state variable will be used + */ + parentViewState?: ViewStateSet; + /** User selected tiles colors */ + coloredTilesMap?: { [key: string]: string }; + /** Allows layers picking to handle mouse events */ + pickable?: boolean; + /** Layers loading data */ + layers3d: { + id?: number; + url?: string; + token?: string | null; + type: TilesetType; + }[]; + /** Last selected layer id. Prop to reset some settings when new layer selected */ + lastLayerSelectedId: string; + /** Load debug texture image */ + loadDebugTextureImage?: boolean; + /** If `true` picking will select I3S features + * If `false` picking will select the whole tile + */ + featurePicking?: boolean; + /** Data for normals visualization */ + normalsDebugData?: NormalsDebugData | null; + /** Percentage of triangles to show normals for */ + normalsTrianglesPercentage?: number; + /** Normals lenght in meters */ + normalsLength?: number; + /** http:///SceneServer json */ + metadata?: { layers: SceneLayer3D[] } | null; + /** Basepath of the tileset of the selected tile */ + selectedTilesetBasePath?: string | null; + /** Tile, selected by picking event */ + selectedTile?: Tile3D | null; + /** Index of picked object */ + selectedIndex?: number; + /** Deckgl flag to highlight picked objects automaticaly */ + autoHighlight?: boolean; + /** List of initialized tilesets */ + loadedTilesets?: Tileset3D[]; + /** I3S option to choose type of geometry */ + useDracoGeometry?: boolean; + /** I3S option to choose type of textures */ + useCompressedTextures?: boolean; + /** enables or disables viewport interactivity */ + disableController?: boolean; + /** allows update a layer */ + loadNumber?: number; + /** prevent transition to a layer */ + preventTransitions?: boolean; + /** calculate position of minimap */ + minimapPosition?: MinimapPosition; + onViewStateChange?: (viewStates: ViewStateSet) => void; + onWebGLInitialized?: (gl: any) => void; + /** DeckGL after render callback */ + onAfterRender?: () => void; + /** DeckGL callback. On layer hover behavior */ + getTooltip?: (info: { object: Tile3D; index: number; layer: any }) => void; + /** DeckGL callback. On layer click behavior */ + onClick?: (info: PickingInfo) => void; + /** Tile3DLayer callback. Triggers after a tileset was initialized */ + onTilesetLoad: (tileset: Tileset3D) => void; + /** Tile3DLayer callback. Triggers after tile content was loaded */ + onTileLoad?: (tile: Tile3D) => void; + /** Tile3DLayer callback. Triggers after tile contenst was unloaded */ + onTileUnload?: (tile: Tile3D) => void; +}; +export const ArcgisWrapper = ({ + // eslint-disable-next-line + id, + parentViewState, + coloredTilesMap, + pickable = false, + layers3d, + lastLayerSelectedId, + loadDebugTextureImage = false, + featurePicking = true, + normalsDebugData, + normalsTrianglesPercentage = 100, + normalsLength = 1, + metadata, + selectedTilesetBasePath, + selectedTile, + selectedIndex, + autoHighlight = false, + loadedTilesets = [], + useDracoGeometry = true, + useCompressedTextures = true, + disableController = false, + loadNumber = 0, + preventTransitions = false, + minimapPosition, + onViewStateChange, + // eslint-disable-next-line + onWebGLInitialized, + // eslint-disable-next-line + onAfterRender, + // eslint-disable-next-line + getTooltip, + onClick, + onTilesetLoad, + onTileLoad, + // eslint-disable-next-line @typescript-eslint/no-empty-function + onTileUnload = () => {}, +}: ArcGisMapProps) => { + const dragMode = useAppSelector(selectDragMode); + const showMinimap = useAppSelector(selectMiniMap); + const loadTiles = useAppSelector(selectLoadTiles); + const showDebugTexture = useAppSelector(selectShowUVDebugTexture); + const createIndependentMinimapViewport = useAppSelector( + selectMiniMapViewPort + ); + const tileColorMode = useAppSelector(selectTileColorMode); + const boundingVolumeColorMode = useAppSelector(selectBoundingVolumeColorMode); + const wireframe = useAppSelector(selectWireframe); + const baseMaps = useAppSelector(selectBaseMaps); + const selectedBaseMapId = useAppSelector(selectSelectedBaseMapId); + const selectedBaseMap = baseMaps.find((map) => map.id === selectedBaseMapId); + const showTerrain = selectedBaseMap?.id === "Terrain"; + const boundingVolume = useAppSelector(selectBoundingVolume); + const boundingVolumeType = useAppSelector(selectBoundingVolumeType); + + const VIEWS = useMemo( + () => [ + new MapView({ + id: "main", + controller: disableController ? false : { inertia: true }, + farZMultiplier: 2.02, + }), + new MapView({ + id: "minimap", + + // Position on top of main map + x: minimapPosition?.x, + y: minimapPosition?.y, + width: "20%", + height: "20%", + + // Minimap is overlaid on top of an existing view, so need to clear the background + clear: true, + controller: disableController + ? false + : { + maxZoom: 9, + minZoom: 9, + dragRotate: false, + keyboard: false, + }, + }), + ], + [disableController, dragMode] + ); + const [viewState, setViewState] = useState({ + main: INITIAL_VIEW_STATE, + minimap: { + latitude: INITIAL_VIEW_STATE.latitude, + longitude: INITIAL_VIEW_STATE.longitude, + zoom: 9, + pitch: 0, + bearing: 0, + }, + }); + const [terrainTiles, setTerrainTiles] = useState({}); + const uvDebugTexture = useAppSelector(selectUVDebugTexture); + const uvDebugTextureRef = useRef(null); + uvDebugTextureRef.current = uvDebugTexture; + const [needTransitionToTileset, setNeedTransitionToTileset] = useState(false); + + const showDebugTextureRef = useRef(false); + showDebugTextureRef.current = showDebugTexture; + + const currentViewport: WebMercatorViewport = null; + + const colorsByAttribute = useAppSelector(selectColorsByAttribute); + const dispatch = useAppDispatch(); + + /** Load debug texture if necessary */ useEffect(() => { - if (!sceneView) { - return; + if (loadDebugTextureImage && !uvDebugTexture) { + dispatch(fetchUVDebugTexture()); } - // @ts-expect-error no ArcGIS types - sceneView.goTo([longitude, latitude], { animate: false }); - }, [longitude, latitude, sceneView]); + }, [loadDebugTextureImage]); + /** + * Hook to call multiple changing function based on selected tileset. + */ useEffect(() => { - if (mapContainer.current == null) { - return; + setNeedTransitionToTileset(true); + colorMap._resetColorsMap(); + }, [lastLayerSelectedId]); + + /** Independent minimap viewport toggle */ + useEffect(() => { + const viewportTraversersMap = { + main: "main", + minimap: createIndependentMinimapViewport ? "minimap" : "main", + }; + loadedTilesets.forEach((tileset) => { + tileset.setProps({ + viewportTraversersMap, + loadTiles, + }); + tileset.selectTiles(); + }); + }, [createIndependentMinimapViewport]); + + /** Load tiles toggle */ + useEffect(() => { + loadedTilesets.forEach((tileset) => { + tileset.setProps({ + loadTiles, + }); + tileset.selectTiles(); + }); + }, [loadTiles]); + + useEffect(() => { + loadedTilesets.forEach((tileset) => { + if (showDebugTexture) { + selectDebugTextureForTileset(tileset, uvDebugTexture); + } else { + selectOriginalTextureForTileset(); + } + }); + }, [showDebugTexture]); + + const getViewState = () => + parentViewState || (showMinimap && viewState) || { main: viewState.main }; + + // eslint-disable-next-line + const getViews = () => (showMinimap ? VIEWS : [VIEWS[0]]); + + const onViewStateChangeHandler = ({ + interactionState, + viewState, + viewId, + }) => { + const { + longitude, + latitude, + position: [, , oldElevation], + } = viewState; + const viewportCenterTerrainElevation = + getElevationByCentralTile(longitude, latitude, terrainTiles) || 0; + let cameraTerrainElevation: number | null = null; + + if (currentViewport) { + const cameraPosition = currentViewport.unprojectPosition( + currentViewport.cameraPosition + ); + cameraTerrainElevation = + getElevationByCentralTile( + cameraPosition[0], + cameraPosition[1], + terrainTiles + ) || 0; } - if (sceneView || isLoadingRef.current) { - return; + let elevation = + cameraTerrainElevation === null || + viewportCenterTerrainElevation > cameraTerrainElevation + ? viewportCenterTerrainElevation + : cameraTerrainElevation; + if (!interactionState.isZooming) { + if (oldElevation - elevation > 5) { + elevation = oldElevation - 5; + } else if (elevation - oldElevation > 5) { + elevation = oldElevation + 5; + } } - isLoadingRef.current = true; - let deckRenderer: unknown; - loadArcGISModules([ - "esri/Map", - "esri/views/SceneView", - "esri/views/3d/externalRenderers", - "esri/layers/SceneLayer", - ]).then( - ({ - DeckRenderer, - modules: [ArcGISMap, SceneView, externalRenderers, SceneLayer], - }) => { - const map = new ArcGISMap({ - basemap: "dark-gray-vector", - }); - - const sceneView = new SceneView({ - container: mapContainer.current, - map: map, - environment: { - atmosphereEnabled: false, - starsEnabled: false, + + if (parentViewState && onViewStateChange) { + let newViewState; + if (viewId === "minimap") { + newViewState = { + main: { + ...parentViewState.main, + longitude: viewState.longitude, + latitude: viewState.latitude, + position: [0, 0, elevation], }, - qualityProfile: "high", - camera: { - position: { x: longitude, y: latitude, z: 100 }, - heading: 10, - tilt: 71, + minimap: viewState, + }; + } else { + newViewState = { + main: { + ...viewState, + position: [0, 0, elevation], }, - ui: { components: ["attribution"] }, - viewingMode: "local", - }); - setSceneView(sceneView); - const sceneLayer = new SceneLayer({ - url: INITIAL_EXAMPLE.url, - popupEnabled: false, - }); - map.add(sceneLayer); - - deckRenderer = new DeckRenderer(sceneView, sceneLayer); - externalRenderers.add(sceneView, deckRenderer); + minimap: { + ...parentViewState.minimap, + longitude: viewState.longitude, + latitude: viewState.latitude, + }, + }; + } + onViewStateChange(newViewState); + } else { + setViewState((prevValues) => { + let newViewState; + if (viewId === "minimap") { + newViewState = { + main: { + ...prevValues.main, + longitude: viewState.longitude, + latitude: viewState.latitude, + position: [0, 0, elevation], + }, + minimap: viewState, + }; + } else { + newViewState = { + main: { + ...viewState, + position: [0, 0, elevation], + }, + minimap: { + ...prevValues.minimap, + longitude: viewState.longitude, + latitude: viewState.latitude, + }, + }; + } + return newViewState; + }); + } + }; + + const onTilesetLoadHandler = (tileset: Tileset3D) => { + if (needTransitionToTileset && !preventTransitions) { + const { zoom, cartographicCenter } = tileset; + const [longitude, latitude] = cartographicCenter || []; + const viewport = new VIEWS[0].ViewportType(viewState.main); + const { + main: { pitch, bearing }, + } = viewState; + + const { zmin = 0 } = metadata?.layers?.[0]?.fullExtent || {}; + const [pLongitude, pLatitude] = getLonLatWithElevationOffset( + zmin, + pitch, + bearing, + longitude, + latitude, + viewport + ); + + const newViewState = { + main: { + ...viewState.main, + zoom: zoom + 2, + longitude: pLongitude, + latitude: pLatitude, + transitionDuration: TRANSITION_DURAITON, + transitionInterpolator: new FlyToInterpolator(), + }, + minimap: { + ...viewState.minimap, + longitude: pLongitude, + latitude: pLatitude, + }, + }; + setNeedTransitionToTileset(false); + if (parentViewState && onViewStateChange) { + onViewStateChange(newViewState); + } else { + setViewState(newViewState); + } + } + + // eslint-disable-next-line + const viewportTraversersMap = { + main: "main", + minimap: createIndependentMinimapViewport ? "minimap" : "main", + }; + tileset.setProps({ + //todo: viewportTraversersMap, + loadTiles, + }); + onTilesetLoad(tileset); + }; + + const onTileLoadHandler = (tile) => { + if (!featurePicking) { + // delete featureIds from data to have instance picking instead of feature picking + delete tile.content.featureIds; + } + if (showDebugTextureRef.current) { + selectDebugTextureForTile(tile, uvDebugTextureRef.current); + } else { + selectOriginalTextureForTile(tile); + } + if (onTileLoad) { + onTileLoad(tile); + } + }; + + const onTerrainTileLoad = (tile) => { + const { + bbox: { east, north, south, west }, + } = tile; + + setTerrainTiles((prevValue) => ({ + ...prevValue, + [`${east};${north};${south};${west}`]: tile, + })); + }; + + const getAllTilesFromTilesets = (tilesets) => { + const allTiles = tilesets.map((tileset) => tileset.tiles); + return allTiles.flat(); + }; + + const getBoundingVolumeColor = (tile) => { + const color = colorMap.getBoundingVolumeColor(tile, { + coloredBy: boundingVolumeColorMode, + }); + + return [...color, DEFAULT_BG_OPACITY]; + }; + + const getMeshColor = (tile) => { + const result = colorMap.getTileColor(tile, { + coloredBy: tileColorMode, + selectedTileId: selectedTile?.id, + coloredTilesMap, + }); + + return result; + }; + + const renderBoundingVolumeLayer = () => { + if (!boundingVolume) { + return null; + } + const tiles = getAllTilesFromTilesets(loadedTilesets); + // @ts-expect-error - Expected 0 arguments, but got 1. + return new BoundingVolumeLayer({ + id: "bounding-volume-layer", + visible: boundingVolume, + tiles, + getBoundingVolumeColor, + boundingVolumeType, + }); + }; + + const renderFrustum = () => { + if (!showMinimap) { + return false; + } + const viewport = new WebMercatorViewport(viewState.main); + const frustumBounds = getFrustumBounds(viewport); + return new LineLayer({ + id: "frustum", + data: frustumBounds, + getSourcePosition: (d) => d.source, + getTargetPosition: (d) => d.target, + getColor: (d) => d.color, + getWidth: 2, + }); + }; + + const renderMainOnMinimap = () => { + if (!createIndependentMinimapViewport) { + return null; + } + let data = []; + + if (loadedTilesets.length) { + const tiles = getAllTilesFromTilesets(loadedTilesets); + data = buildMinimapData(tiles); + } + + return new ScatterplotLayer({ + id: "main-on-minimap", + data, + pickable: false, + opacity: 0.8, + stroked: true, + filled: true, + radiusScale: 1, + radiusMinPixels: 1, + radiusMaxPixels: 100, + lineWidthMinPixels: 1, + getPosition: (d) => d.coordinates, + getRadius: (d) => d.radius, + getFillColor: () => [255, 140, 0, 100], + getLineColor: () => [0, 0, 0, 120], + }); + }; + + const renderNormals = () => { + if (!normalsDebugData) { + return; + } + return new LineLayer({ + id: "normals-debug", + data: normalsDebugData, + getSourcePosition: (_, { index, data }) => + getNormalSourcePosition(index, data, normalsTrianglesPercentage), + getTargetPosition: (_, { index, data }) => + getNormalTargetPosition( + index, + data, + normalsTrianglesPercentage, + normalsLength + ), + getColor: () => NORMALS_COLOR, + modelMatrix: normalsDebugData?.cartographicModelMatrix, + coordinateOrigin: normalsDebugData?.cartographicOrigin, + coordinateSystem: COORDINATE_SYSTEM.METER_OFFSETS, + getWidth: 1, + }); + }; + + const renderI3SLayer = (layer) => { + const loadOptions: LoadOptions = { + i3s: { + coordinateSystem: COORDINATE_SYSTEM.LNGLAT_OFFSETS, + useDracoGeometry, + useCompressedTextures, + colorsByAttribute: colorsByAttribute, + }, + }; + if (layer.token) { + loadOptions.i3s.token = layer.token; + } + return new Tile3DLayer({ + id: `tile-layer-${layer.id}-draco-${useDracoGeometry}-compressed-textures-${useCompressedTextures}--colors-by-attribute-${colorsByAttribute?.attributeName}--colors-by-attribute-mode-${colorsByAttribute?.mode}--${loadNumber}`, + data: layer.url, + loader: I3SLoader, + onClick: onClick, + onTilesetLoad: onTilesetLoadHandler, + onTileLoad: onTileLoadHandler, + onTileUnload, + loadOptions, + pickable, + autoHighlight, + _subLayerProps: { + mesh: { + wireframe, + }, + }, + _getMeshColor: getMeshColor, + highlightedObjectIndex: autoHighlight + ? undefined + : layer.url === selectedTilesetBasePath + ? selectedIndex + : -1, + }); + }; + + const render3DTilesLayer = (layer) => { + const loadOptions = + layer.type === TilesetType.CesiumIon + ? { "cesium-ion": { accessToken: layer.token } } + : {}; + const loader = + layer.type === TilesetType.CesiumIon ? CesiumIonLoader : Tiles3DLoader; + return new Tile3DLayer({ + id: `tile-layer-${layer.id}--${loadNumber}`, + data: layer.url, + loader, + loadOptions, + onTilesetLoad: onTilesetLoadHandler, + onTileLoad: onTileLoadHandler, + onTileUnload, + }); + }; + + const renderLayers = () => { + const tile3dLayers = layers3d.map((layer) => { + switch (layer.type) { + case TilesetType.CesiumIon: + case TilesetType.Tiles3D: + return render3DTilesLayer(layer); + case TilesetType.I3S: + default: + return renderI3SLayer(layer); } - ); - }, [sceneView, mapContainer, bearing, latitude, longitude]); + }); + if (showTerrain) { + const terrainLayer = new TerrainLayer({ + id: "terrain", + maxZoom: TERRAIN_LAYER_MAX_ZOOM, + elevationDecoder: MAPZEN_ELEVATION_DECODE_PARAMETERS, + elevationData: MAPZEN_TERRAIN_IMAGES, + texture: ARCGIS_STREET_MAP_SURFACE_IMAGES, + onTileLoad: (tile) => onTerrainTileLoad(tile), + color: [255, 255, 255], + }); + tile3dLayers.push(terrainLayer); + } + + return [ + ...tile3dLayers, + renderFrustum(), + renderBoundingVolumeLayer(), + renderNormals(), + renderMainOnMinimap(), + ]; + }; + + // eslint-disable-next-line + const layerFilter = ({ layer, viewport }) => { + const { id: viewportId } = viewport; + const { + id: layerId, + props: { viewportIds = null }, + } = layer; + if ( + viewportId !== "minimap" && + (layerId === "frustum" || layerId === "main-on-minimap") + ) { + // only display frustum in the minimap + return false; + } + if ( + showMinimap && + viewportId === "minimap" && + layerId.indexOf("obb-debug-") !== -1 + ) { + return false; + } + if (viewportIds && !viewportIds.includes(viewportId)) { + return false; + } + if (viewportId === "minimap" && layerId === "normals-debug") { + return false; + } + if (viewportId === "minimap" && layerId.indexOf("terrain") !== -1) { + return false; + } + return true; + }; + // Trying to keep code alligned to deck-gl-wrapper above this line + // All Arcgis specific code is allocated below this line + const mapContainer = useRef(null); + const map = useArcgis(mapContainer, getViewState(), onViewStateChangeHandler); + if (map) { + const layers = renderLayers(); + // @ts-expect-error @deck.gl/arcgis has no types + map.deck.set({ layers }); + // @ts-expect-error @deck.gl/arcgis has no types + map.deck.layerFilter = layerFilter; + } return ; }; diff --git a/src/components/deck-gl-wrapper/deck-gl-wrapper.tsx b/src/components/deck-gl-wrapper/deck-gl-wrapper.tsx index dffbbf78..583392d0 100644 --- a/src/components/deck-gl-wrapper/deck-gl-wrapper.tsx +++ b/src/components/deck-gl-wrapper/deck-gl-wrapper.tsx @@ -217,6 +217,9 @@ export const DeckGlWrapper = ({ const selectedBaseMap = baseMaps.find((map) => map.id === selectedBaseMapId); const showTerrain = selectedBaseMap?.id === "Terrain"; const mapStyle = selectedBaseMap?.mapUrl; + const boundingVolume = useAppSelector(selectBoundingVolume); + const boundingVolumeType = useAppSelector(selectBoundingVolumeType); + const VIEWS = useMemo( () => [ new MapView({ @@ -526,9 +529,6 @@ export const DeckGlWrapper = ({ }; const renderBoundingVolumeLayer = () => { - const boundingVolume = useAppSelector(selectBoundingVolume); - const boundingVolumeType = useAppSelector(selectBoundingVolumeType); - if (!boundingVolume) { return null; } diff --git a/src/components/map-control-panel/map-control-panel.tsx b/src/components/map-control-panel/map-control-panel.tsx index 96c4a86c..cd0a3f25 100644 --- a/src/components/map-control-panel/map-control-panel.tsx +++ b/src/components/map-control-panel/map-control-panel.tsx @@ -83,6 +83,7 @@ type MapControlPanelProps = { onZoomIn: () => void; onZoomOut: () => void; onCompassClick: () => void; + isDragModeVisible?: boolean; }; type CompassProps = { @@ -106,6 +107,7 @@ export const MapControllPanel = ({ onZoomIn, onZoomOut, onCompassClick, + isDragModeVisible = true, }: MapControlPanelProps) => { const [expandState, expand] = useExpand(ExpandState.expanded); const dragMode = useAppSelector(selectDragMode); @@ -144,18 +146,22 @@ export const MapControllPanel = ({ - - + {isDragModeVisible === true && ( + <> + + + + )} )} + ); +}; diff --git a/src/components/arcgis-user/arcgis-user.spec.tsx b/src/components/arcgis-user/arcgis-user.spec.tsx new file mode 100644 index 00000000..172d3ab7 --- /dev/null +++ b/src/components/arcgis-user/arcgis-user.spec.tsx @@ -0,0 +1,30 @@ +import { screen } from "@testing-library/react"; +import userEvent from "@testing-library/user-event"; +import { renderWithTheme } from "../../utils/testing-utils/render-with-theme"; +import { AcrGisUser } from "./arcgis-user"; + +const onClickMock = jest.fn(); + +const callRender = (renderFunc, props) => { + return renderFunc( + + ); +}; + +describe("AcrGisUser", () => { + it("Should render Logout button", () => { + const { container } = callRender(renderWithTheme, { children: 'Test Button' }); + expect(container).toBeInTheDocument(); + const button = screen.getByText('Test Button'); + const buttonIcon = button.nextSibling as Element; + const buttonHeight = getComputedStyle(buttonIcon).getPropertyValue( + "height" + ); + expect(buttonHeight).toEqual('17px'); + userEvent.click(buttonIcon); + expect(onClickMock).toHaveBeenCalled(); + }); + +}); diff --git a/src/components/arcgis-user/arcgis-user.tsx b/src/components/arcgis-user/arcgis-user.tsx new file mode 100644 index 00000000..ad00d99e --- /dev/null +++ b/src/components/arcgis-user/arcgis-user.tsx @@ -0,0 +1,61 @@ +import styled from "styled-components"; +import LogoutIcon from "../../../public/icons/logout.svg"; +import { + color_canvas_secondary_inverted, +} from "../../constants/colors"; + +const Container = styled.div` + display: flex; + justify-content: flex-start; + align-items: center; + margin-left: 50px; + margin-top: -18px; +`; + +const UserInfo = styled.div` + height: 17px; + margin-right: 8px; + font-weight: 500; + font-size: 14px; + line-height: 17px; + color: ${({ theme }) => ( + theme.colors.logoutButtonTextColor + )}; +`; + +const IconButton = styled.div` + display: flex; + justify-content: flex-start; + width: 63px; + height: 17px; + cursor: pointer; + &:hover { + > * { + stroke: ${({ theme }) => (theme.colors.logoutButtonIconColorHover)}; + } + } +`; + +const StyledIcon = styled(LogoutIcon)` + margin-top: 1px; + stroke: ${color_canvas_secondary_inverted}; +`; + +type ArcGisUserProps = { + children?: React.ReactNode; + onClick?: () => void; +}; + +export const AcrGisUser = ({ + children, + onClick, +}: ArcGisUserProps) => { + return ( + + {children} + + + + + ); +}; diff --git a/src/components/layers-panel/layers-control-panel.spec.tsx b/src/components/layers-panel/layers-control-panel.spec.tsx index bcd544cd..8d07588a 100644 --- a/src/components/layers-panel/layers-control-panel.spec.tsx +++ b/src/components/layers-panel/layers-control-panel.spec.tsx @@ -3,18 +3,18 @@ import { renderWithTheme } from "../../utils/testing-utils/render-with-theme"; import { LayersControlPanel } from "./layers-control-panel"; // Mocked components -import { PlusButton } from "../plus-button/plus-button"; +import { ActionIconButton } from "../action-icon-button/action-icon-button"; import { DeleteConfirmation } from "./delete-confirmation"; import { LayerOptionsMenu } from "./layer-options-menu/layer-options-menu"; import { ListItem } from "./list-item/list-item"; jest.mock("./list-item/list-item"); -jest.mock("../plus-button/plus-button"); +jest.mock("../action-icon-button/action-icon-button"); jest.mock("./delete-confirmation"); jest.mock("./layer-options-menu/layer-options-menu"); const ListItemMock = ListItem as unknown as jest.Mocked; -const PlusButtonMock = PlusButton as unknown as jest.Mocked; +const PlusButtonMock = ActionIconButton as unknown as jest.Mocked; const DeleteConfirmationMock = DeleteConfirmation as unknown as jest.Mocked; const LayerOptionsMenuMock = LayerOptionsMenu as unknown as jest.Mocked; diff --git a/src/components/layers-panel/layers-control-panel.tsx b/src/components/layers-panel/layers-control-panel.tsx index 1a7a2759..bf377d81 100644 --- a/src/components/layers-panel/layers-control-panel.tsx +++ b/src/components/layers-panel/layers-control-panel.tsx @@ -4,12 +4,17 @@ import styled from "styled-components"; import { SelectionState, LayerExample, LayerViewState, ListItemType } from "../../types"; import { ListItem } from "./list-item/list-item"; -import { PlusButton } from "../plus-button/plus-button"; +import PlusIcon from "../../../public/icons/plus.svg"; +import ImportIcon from "../../../public/icons/import.svg"; +import EsriImage from "../../../public/images/esri.svg"; +import { ActionIconButton } from "../action-icon-button/action-icon-button"; +import { AcrGisUser } from "../arcgis-user/arcgis-user"; import { DeleteConfirmation } from "./delete-confirmation"; import { LayerOptionsMenu } from "./layer-options-menu/layer-options-menu"; import { handleSelectAllLeafsInGroup } from "../../utils/layer-utils"; import { ButtonSize } from "../../types"; +import { PanelHorizontalLine } from "../common"; type LayersControlPanelProps = { layers: LayerExample[]; @@ -35,18 +40,13 @@ const LayersList = styled.div` display: flex; flex-direction: column; width: 100%; - margin-bottom: 10px; `; const InsertButtons = styled.div` display: flex; flex-direction: column; - padding-left: 10px; - > * { - &:first-child { - margin-bottom: 28px; - } - } + row-gap: 8px; + margin-top: 8px; `; const ChildrenContainer = styled.div` @@ -57,6 +57,18 @@ const ChildrenContainer = styled.div` padding-left: 12px; `; +const ActionIconButtonContainer = styled.div` + display: flex; + flex-direction: row; + justify-content: start; + align-items: center; +`; + +const EsriStyledImage = styled(EsriImage)` + margin-left: 16px; + fill: ${({ theme }) => theme.colors.esriImageColor}; +`; + export const LayersControlPanel = ({ layers, type, @@ -73,6 +85,13 @@ export const LayersControlPanel = ({ const [showLayerSettings, setShowLayerSettings] = useState(false); const [layerToDeleteId, setLayerToDeleteId] = useState(""); + /// Stab { + const username = 'Michael-g'; + const [isLoggedIn, setIsLoggedIn] = useState(false); + const onArcGisActionClick = () => { !isLoggedIn && setIsLoggedIn(true) }; + const onArcGisLogoutClick = () => { setIsLoggedIn(false) }; + /// Stab } + const isListItemSelected = ( layer: LayerExample, parentLayer?: LayerExample @@ -178,12 +197,28 @@ export const LayersControlPanel = ({ {renderLayers(layers)} - + Insert layer - - + + Insert scene - + + + + + + + {!isLoggedIn && "Login to ArcGIS"} + {isLoggedIn && "Import from ArcGIS"} + + + + + {isLoggedIn && ( + + {username} + + )} ); diff --git a/src/components/layers-panel/map-options-panel.spec.tsx b/src/components/layers-panel/map-options-panel.spec.tsx index 6ee488ac..e5f2a171 100644 --- a/src/components/layers-panel/map-options-panel.spec.tsx +++ b/src/components/layers-panel/map-options-panel.spec.tsx @@ -4,7 +4,7 @@ import { renderWithThemeProviders } from "../../utils/testing-utils/render-with- import { MapOptionPanel } from "./map-options-panel"; import { BaseMapListItem } from "./base-map-list-item/base-map-list-item"; -import { PlusButton } from "../plus-button/plus-button"; +import { ActionIconButton } from "../action-icon-button/action-icon-button"; import { DeleteConfirmation } from "./delete-confirmation"; import { BaseMapOptionsMenu } from "./basemap-options-menu/basemap-options-menu"; import { setupStore } from "../../redux/store"; @@ -15,12 +15,12 @@ import { } from "../../redux/slices/base-maps-slice"; jest.mock("./base-map-list-item/base-map-list-item"); -jest.mock("../plus-button/plus-button"); +jest.mock("../action-icon-button/action-icon-button"); jest.mock("./delete-confirmation"); jest.mock("./basemap-options-menu/basemap-options-menu"); const BaseMapListItemMock = BaseMapListItem as unknown as jest.Mocked; -const PlusButtonMock = PlusButton as unknown as jest.Mocked; +const PlusButtonMock = ActionIconButton as unknown as jest.Mocked; const DeleteConfirmationMock = DeleteConfirmation as unknown as jest.Mocked; const BaseMapOptionsMenuMock = diff --git a/src/components/layers-panel/map-options-panel.tsx b/src/components/layers-panel/map-options-panel.tsx index a3ae5ddd..22ff4f71 100644 --- a/src/components/layers-panel/map-options-panel.tsx +++ b/src/components/layers-panel/map-options-panel.tsx @@ -1,7 +1,8 @@ import { useState, Fragment } from "react"; import styled from "styled-components"; import { BaseMapListItem } from "./base-map-list-item/base-map-list-item"; -import { PlusButton } from "../plus-button/plus-button"; +import PlusIcon from "../../../public/icons/plus.svg"; +import { ActionIconButton } from "../action-icon-button/action-icon-button"; import { DeleteConfirmation } from "./delete-confirmation"; import { SelectionState } from "../../types"; import { BaseMapOptionsMenu } from "./basemap-options-menu/basemap-options-menu"; @@ -41,19 +42,12 @@ const MapList = styled.div` display: flex; flex-direction: column; width: 100%; - margin-bottom: 10px; `; const InsertButtons = styled.div` display: flex; flex-direction: column; - padding-left: 10px; - - > * { - &:first-child { - margin-bottom: 0px; - } - } + row-gap: 8px; `; export const MapOptionPanel = ({ insertBaseMap }: MapOptionPanelProps) => { @@ -120,9 +114,9 @@ export const MapOptionPanel = ({ insertBaseMap }: MapOptionPanelProps) => { })} - + Insert Base Map - + ); diff --git a/src/components/plus-button/plus-button.tsx b/src/components/plus-button/plus-button.tsx deleted file mode 100644 index 5343e69f..00000000 --- a/src/components/plus-button/plus-button.tsx +++ /dev/null @@ -1,75 +0,0 @@ -import styled from "styled-components"; -import { color_brand_tertiary } from "../../constants/colors"; -import { ButtonSize } from "../../types"; - -type PlusButtonProps = { - children?: React.ReactNode; - buttonSize: ButtonSize; - onClick?: () => void; -}; - -const Button = styled.div` - display: flex; - cursor: pointer; - justify-content: flex-start; - align-items: center; - - &:hover { - > * { - &:first-child { - // Keep rgba format to avoid issue with opacity inheritance and pseudo elements. - background: rgba(96, 93, 236, 0.2); - } - } - } -`; - -const PlusIcon = styled.div<{ buttonSize: number }>` - position: relative; - width: ${(props) => (props.buttonSize === ButtonSize.Big ? "40px" : "24px")}; - height: ${(props) => (props.buttonSize === ButtonSize.Big ? "40px" : "24px")}; - // Keep rgba format to avoid issue with opacity inheritance and pseudo elements. - background: rgba(96, 93, 236, 0.4); - cursor: pointer; - border-radius: 4px; - margin-right: 16px; - - &:after { - content: ""; - position: absolute; - transform: translate(-50%, -50%); - height: 2px; - width: 50%; - background: ${color_brand_tertiary}; - top: 50%; - left: 50%; - } - - &:before { - content: ""; - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - background: ${color_brand_tertiary}; - height: 50%; - width: 2px; - } -`; - -const ButtonText = styled.div` - color: ${color_brand_tertiary}; -`; - -export const PlusButton = ({ - children, - buttonSize, - onClick, -}: PlusButtonProps) => { - return ( - - ); -}; diff --git a/src/utils/testing-utils/e2e-layers-panel.tsx b/src/utils/testing-utils/e2e-layers-panel.tsx index 3bece459..20c1d604 100644 --- a/src/utils/testing-utils/e2e-layers-panel.tsx +++ b/src/utils/testing-utils/e2e-layers-panel.tsx @@ -37,12 +37,12 @@ export const checkLayersPanel = async ( // Insert buttons const insertLayerText = await page.$eval( - `${panelId} > :nth-child(4) > :first-child > :nth-child(2) > :first-child :last-child`, + `${panelId} > :nth-child(4) > :first-child > :nth-child(2) > :first-child > :last-child`, (node) => node.innerText ); expect(insertLayerText).toBe("Insert layer"); const insertSceneText = await page.$eval( - `${panelId} > :nth-child(4) > :first-child > :nth-child(2) > :last-child :last-child`, + `${panelId} > :nth-child(4) > :first-child > :nth-child(2) > :nth-child(2) > :last-child`, (node) => node.innerText ); expect(insertSceneText).toBe("Insert scene"); From dd8a7712b711c2acfd95a725f0da36ce550f674d Mon Sep 17 00:00:00 2001 From: mspivak-actionengine <118991512+mspivak-actionengine@users.noreply.github.com> Date: Wed, 20 Dec 2023 13:33:16 +0300 Subject: [PATCH 13/40] feat(arcgis): auth slice (#332) --- .env | 1 - .env-template | 1 + .gitignore | 1 + __mocks__/@esri/arcgis-rest-request.ts | 26 ++ package.json | 2 + public/icons/download-2.svg | 4 - src/app.tsx | 1 + .../action-icon-button.spec.tsx | 37 ++- .../action-icon-button/action-icon-button.tsx | 63 +++-- .../arcgis-user/arcgis-user.spec.tsx | 20 +- src/components/arcgis-user/arcgis-user.tsx | 17 +- src/components/common.tsx | 3 +- .../layers-control-panel.spec.tsx | 249 ++++++++++++++---- .../layers-panel/layers-control-panel.tsx | 110 ++++++-- .../modal-dialog/modal-dialog.spec.tsx | 44 ++++ src/components/modal-dialog/modal-dialog.tsx | 140 ++++++++++ src/pages/auth/auth.tsx | 44 ++++ src/pages/auth/e2e.auth.spec.ts | 23 ++ src/pages/index.ts | 1 + src/redux/slices/arcgis-auth-slice.spec.ts | 76 ++++++ src/redux/slices/arcgis-auth-slice.ts | 44 ++++ src/redux/store.ts | 2 + src/utils/arcgis-auth.spec.ts | 44 ++++ src/utils/arcgis-auth.ts | 99 +++++++ webpack.dev.config.js | 1 + 25 files changed, 910 insertions(+), 143 deletions(-) delete mode 100644 .env create mode 100644 .env-template create mode 100644 __mocks__/@esri/arcgis-rest-request.ts delete mode 100644 public/icons/download-2.svg create mode 100644 src/components/modal-dialog/modal-dialog.spec.tsx create mode 100644 src/components/modal-dialog/modal-dialog.tsx create mode 100644 src/pages/auth/auth.tsx create mode 100644 src/pages/auth/e2e.auth.spec.ts create mode 100644 src/redux/slices/arcgis-auth-slice.spec.ts create mode 100644 src/redux/slices/arcgis-auth-slice.ts create mode 100644 src/utils/arcgis-auth.spec.ts create mode 100644 src/utils/arcgis-auth.ts diff --git a/.env b/.env deleted file mode 100644 index 756b2061..00000000 --- a/.env +++ /dev/null @@ -1 +0,0 @@ -REACT_APP_ARCGIS_REST_CLIENT_ID=abcdef diff --git a/.env-template b/.env-template new file mode 100644 index 00000000..8f85508b --- /dev/null +++ b/.env-template @@ -0,0 +1 @@ +REACT_APP_ARCGIS_REST_CLIENT_ID=abcd diff --git a/.gitignore b/.gitignore index eb7b4d44..8a67cf5e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ node_modules/ build/ coverage/ +.env diff --git a/__mocks__/@esri/arcgis-rest-request.ts b/__mocks__/@esri/arcgis-rest-request.ts new file mode 100644 index 00000000..391ef811 --- /dev/null +++ b/__mocks__/@esri/arcgis-rest-request.ts @@ -0,0 +1,26 @@ +const mockEmailExpected = "usermail@gmail.com"; +const mockSessionExpected = '{"usermail": "usermail"}'; + +export class ArcGISIdentityManager { + static beginOAuth2 = async () => { + const session = { + usermail: mockEmailExpected, + serialize: () => { + return mockSessionExpected; + }, + getUser: async () => { + return { email: mockEmailExpected }; + }, + }; + return session; + }; + static completeOAuth2 = async () => { + return; + }; + static destroy = async () => { + return; + }; + static deserialize = (session) => { + return { usermail: "usermail" }; + }; +} diff --git a/package.json b/package.json index 9938aaa7..bd93774c 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,8 @@ "author": "", "license": "ISC", "dependencies": { + "@esri/arcgis-rest-auth": "^3.7.0", + "@esri/arcgis-rest-request": "^4.2.0", "@fortawesome/fontawesome-svg-core": "^1.2.36", "@fortawesome/free-solid-svg-icons": "^5.15.4", "@fortawesome/react-fontawesome": "^0.1.17", diff --git a/public/icons/download-2.svg b/public/icons/download-2.svg deleted file mode 100644 index bdfae70b..00000000 --- a/public/icons/download-2.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/src/app.tsx b/src/app.tsx index 43e316f1..a709d385 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -164,6 +164,7 @@ export const App = () => { } /> } /> } /> + } /> { return renderFunc( + {...props} + /> ); }; -describe("Plus Button", () => { - it("Should render small Plus button", () => { - const { container } = callRender(renderWithTheme, { children: 'Test Button' }); +describe("ActionIconButton", () => { + it("Should render small Plus icon in the button", () => { + const { container } = callRender(renderWithTheme, { + children: "Test Button", + }); expect(container).toBeInTheDocument(); - const button = screen.getByText('Test Button'); - const buttonHeight = getComputedStyle(button.previousSibling as Element).getPropertyValue("height"); - expect(buttonHeight).toEqual('24px'); + const button = screen.getByText("Test Button"); + const buttonHeight = getComputedStyle( + button.previousSibling as Element + ).getPropertyValue("height"); + expect(buttonHeight).toEqual("24px"); userEvent.click(button); expect(onClickMock).toHaveBeenCalled(); }); - it("Should render Big Plus button", () => { - const { container } = callRender(renderWithTheme, { children: 'Test Button', size: ButtonSize.Big }); + it("Should render Big Plus icon in the button", () => { + const { container } = callRender(renderWithTheme, { + children: "Test Button", + size: ButtonSize.Big, + }); expect(container).toBeInTheDocument(); - const button = screen.getByText('Test Button'); - const buttonHeight = getComputedStyle(button.previousSibling as Element).getPropertyValue("height"); - expect(buttonHeight).toEqual('40px'); + const button = screen.getByText("Test Button"); + const buttonHeight = getComputedStyle( + button.previousSibling as Element + ).getPropertyValue("height"); + expect(buttonHeight).toEqual("40px"); userEvent.click(button); expect(onClickMock).toHaveBeenCalled(); }); - }); diff --git a/src/components/action-icon-button/action-icon-button.tsx b/src/components/action-icon-button/action-icon-button.tsx index 8e2b6433..c30690d3 100644 --- a/src/components/action-icon-button/action-icon-button.tsx +++ b/src/components/action-icon-button/action-icon-button.tsx @@ -1,10 +1,12 @@ import React from "react"; -import styled, { StyledComponent, DefaultTheme, useTheme } from "styled-components"; +import styled, { + StyledComponent, + DefaultTheme, + useTheme, +} from "styled-components"; import { ButtonSize } from "../../types"; -import { - color_brand_tertiary, -} from "../../constants/colors"; +import { color_brand_tertiary } from "../../constants/colors"; const Button = styled.div<{ grayed?: boolean }>` display: flex; @@ -23,11 +25,10 @@ const Button = styled.div<{ grayed?: boolean }>` } > :nth-child(2) { - color: ${({ theme, grayed }) => ( - grayed - ? theme.colors.actionIconButtonTextDisabledColorHover - : color_brand_tertiary - )}; + color: ${({ theme, grayed }) => + grayed + ? theme.colors.actionIconButtonTextDisabledColorHover + : color_brand_tertiary}; } } `; @@ -37,27 +38,25 @@ const ButtonText = styled.div<{ grayed?: boolean }>` font-weight: 500; font-size: 16px; line-height: 19px; - color: ${({ theme, grayed }) => ( + color: ${({ theme, grayed }) => grayed ? theme.colors.actionIconButtonTextDisabledColor - : color_brand_tertiary - )}; - `; + : color_brand_tertiary}; +`; -const IconContainer = styled.div<{ buttonSize: number, grayed?: boolean }>` +const IconContainer = styled.div<{ buttonSize: number; grayed?: boolean }>` display: flex; justify-content: center; align-items: center; border-radius: 4px; width: ${(props) => (props.buttonSize === ButtonSize.Big ? "40px" : "24px")}; height: ${(props) => (props.buttonSize === ButtonSize.Big ? "40px" : "24px")}; - - background: ${({ theme, grayed }) => ( + + background: ${({ theme, grayed }) => grayed ? theme.colors.actionIconButtonDisabledBG - : `${color_brand_tertiary}66` - )}; - `; + : `${color_brand_tertiary}66`}; +`; type ActionIconButtonProps = { children?: React.ReactNode; @@ -67,18 +66,30 @@ type ActionIconButtonProps = { onClick?: () => void; }; -export const ActionIconButton = ({ Icon, style, size, children, onClick }: ActionIconButtonProps) => { +export const ActionIconButton = ({ + Icon, + style, + size, + children, + onClick, +}: ActionIconButtonProps) => { const grayed = style === "disabled"; const theme = useTheme(); return ( - diff --git a/src/components/arcgis-user/arcgis-user.spec.tsx b/src/components/arcgis-user/arcgis-user.spec.tsx index 172d3ab7..e2fa389f 100644 --- a/src/components/arcgis-user/arcgis-user.spec.tsx +++ b/src/components/arcgis-user/arcgis-user.spec.tsx @@ -6,25 +6,21 @@ import { AcrGisUser } from "./arcgis-user"; const onClickMock = jest.fn(); const callRender = (renderFunc, props) => { - return renderFunc( - - ); + return renderFunc(); }; describe("AcrGisUser", () => { it("Should render Logout button", () => { - const { container } = callRender(renderWithTheme, { children: 'Test Button' }); + const { container } = callRender(renderWithTheme, { + children: "Test Button", + }); expect(container).toBeInTheDocument(); - const button = screen.getByText('Test Button'); + const button = screen.getByText("Test Button"); const buttonIcon = button.nextSibling as Element; - const buttonHeight = getComputedStyle(buttonIcon).getPropertyValue( - "height" - ); - expect(buttonHeight).toEqual('17px'); + const buttonHeight = + getComputedStyle(buttonIcon).getPropertyValue("height"); + expect(buttonHeight).toEqual("17px"); userEvent.click(buttonIcon); expect(onClickMock).toHaveBeenCalled(); }); - }); diff --git a/src/components/arcgis-user/arcgis-user.tsx b/src/components/arcgis-user/arcgis-user.tsx index ad00d99e..8cfb94ca 100644 --- a/src/components/arcgis-user/arcgis-user.tsx +++ b/src/components/arcgis-user/arcgis-user.tsx @@ -1,8 +1,6 @@ import styled from "styled-components"; import LogoutIcon from "../../../public/icons/logout.svg"; -import { - color_canvas_secondary_inverted, -} from "../../constants/colors"; +import { color_canvas_secondary_inverted } from "../../constants/colors"; const Container = styled.div` display: flex; @@ -18,9 +16,7 @@ const UserInfo = styled.div` font-weight: 500; font-size: 14px; line-height: 17px; - color: ${({ theme }) => ( - theme.colors.logoutButtonTextColor - )}; + color: ${({ theme }) => theme.colors.logoutButtonTextColor}; `; const IconButton = styled.div` @@ -31,7 +27,7 @@ const IconButton = styled.div` cursor: pointer; &:hover { > * { - stroke: ${({ theme }) => (theme.colors.logoutButtonIconColorHover)}; + stroke: ${({ theme }) => theme.colors.logoutButtonIconColorHover}; } } `; @@ -46,14 +42,11 @@ type ArcGisUserProps = { onClick?: () => void; }; -export const AcrGisUser = ({ - children, - onClick, -}: ArcGisUserProps) => { +export const AcrGisUser = ({ children, onClick }: ArcGisUserProps) => { return ( {children} - + diff --git a/src/components/common.tsx b/src/components/common.tsx index 785213fc..5fce3c01 100644 --- a/src/components/common.tsx +++ b/src/components/common.tsx @@ -26,8 +26,7 @@ export const PanelContainer = styled.div` display: flex; flex-direction: column; width: 359px; - background: ${({ theme }) => theme.colors.mainCanvasColor}; - opacity: ${({ theme }) => (theme.name === Theme.Dark ? 0.9 : 1)}; + background: ${({ theme }) => `${theme.colors.mainCanvasColor}${theme.name === Theme.Dark ? 'e6' : 'ff'}` }; border-radius: 8px; padding-bottom: 26px; position: relative; diff --git a/src/components/layers-panel/layers-control-panel.spec.tsx b/src/components/layers-panel/layers-control-panel.spec.tsx index 8d07588a..eb0dcb1b 100644 --- a/src/components/layers-panel/layers-control-panel.spec.tsx +++ b/src/components/layers-panel/layers-control-panel.spec.tsx @@ -1,17 +1,31 @@ -import { act, screen } from "@testing-library/react"; -import { renderWithTheme } from "../../utils/testing-utils/render-with-theme"; +import { act, screen, within } from "@testing-library/react"; +import { renderWithThemeProviders } from "../../utils/testing-utils/render-with-theme"; import { LayersControlPanel } from "./layers-control-panel"; +import userEvent from "@testing-library/user-event"; +import { + arcGisLogin, + arcGisLogout, +} from "../../redux/slices/arcgis-auth-slice"; // Mocked components import { ActionIconButton } from "../action-icon-button/action-icon-button"; import { DeleteConfirmation } from "./delete-confirmation"; import { LayerOptionsMenu } from "./layer-options-menu/layer-options-menu"; import { ListItem } from "./list-item/list-item"; +import { setupStore } from "../../redux/store"; + +import { + getAuthenticatedUser, + arcGisRequestLogin, + arcGisCompleteLogin, + arcGisRequestLogout, +} from "../../utils/arcgis-auth"; jest.mock("./list-item/list-item"); jest.mock("../action-icon-button/action-icon-button"); jest.mock("./delete-confirmation"); jest.mock("./layer-options-menu/layer-options-menu"); +jest.mock("../../utils/arcgis-auth"); const ListItemMock = ListItem as unknown as jest.Mocked; const PlusButtonMock = ActionIconButton as unknown as jest.Mocked; @@ -19,18 +33,17 @@ const DeleteConfirmationMock = DeleteConfirmation as unknown as jest.Mocked; const LayerOptionsMenuMock = LayerOptionsMenu as unknown as jest.Mocked; -beforeAll(() => { - ListItemMock.mockImplementation((props) => ( -
{`ListItem-${props.id}`}
- )); - PlusButtonMock.mockImplementation(({ children, onClick }) => ( -
{children}
- )); - DeleteConfirmationMock.mockImplementation(() => ( -
Delete Conformation
- )); - LayerOptionsMenuMock.mockImplementation(() =>
Layers Options
); -}); +const getAuthenticatedUserMock = + getAuthenticatedUser as unknown as jest.Mocked; +const arcGisRequestLoginMock = + arcGisRequestLogin as unknown as jest.Mocked; +const arcGisCompleteLoginMock = + arcGisCompleteLogin as unknown as jest.Mocked; +const arcGisRequestLogoutMock = + arcGisRequestLogout as unknown as jest.Mocked; + +const mockEmailExpected = "usermail@gmail.com"; +let mockStorageUserinfo = ""; const onInsertLayerMock = jest.fn(); const onInsertSceneMock = jest.fn(); @@ -39,7 +52,7 @@ const onSelectLayerMock = jest.fn(); const onLayerSettingsClickMock = jest.fn(); const onPointToLayerMock = jest.fn(); -const callRender = (renderFunc, props = {}) => { +const callRender = (renderFunc, props = {}, store = setupStore()) => { return renderFunc( { onPointToLayer={onPointToLayerMock} deleteLayer={onDeleteLayerMock} {...props} - /> + />, + store ); }; +beforeAll(() => { + ListItemMock.mockImplementation((props) => ( +
{`ListItem-${props.id}`}
+ )); + PlusButtonMock.mockImplementation(({ children, onClick }) => ( +
{children}
+ )); + DeleteConfirmationMock.mockImplementation(() => ( +
Delete Conformation
+ )); + LayerOptionsMenuMock.mockImplementation(() =>
Layers Options
); +}); + +describe("Layers Control Panel - ArcGIS auth", () => { + beforeAll(() => { + arcGisRequestLoginMock.mockImplementation(async () => { + mockStorageUserinfo = mockEmailExpected; + return mockStorageUserinfo; + }); + arcGisCompleteLoginMock.mockImplementation(async () => { + return mockStorageUserinfo; + }); + arcGisRequestLogoutMock.mockImplementation(async () => { + mockStorageUserinfo = ""; + return mockStorageUserinfo; + }); + getAuthenticatedUserMock.mockImplementation(() => { + return mockStorageUserinfo; + }); + }); + + it("Should render ArcGIS Login button", async () => { + const store = setupStore(); + // Let's Log out... + await store.dispatch(arcGisLogout()); + const { container } = callRender( + renderWithThemeProviders, + undefined, + store + ); + expect(container).toBeInTheDocument(); + expect(arcGisRequestLogoutMock).toHaveBeenCalledTimes(1); + + // We are in the "Logged out" state, so the "Log in" button should be there. + const loginButton = await screen.findByText("Login to ArcGIS"); + expect(loginButton).toBeInTheDocument(); + loginButton && userEvent.click(loginButton); + expect(arcGisRequestLoginMock).toHaveBeenCalledTimes(1); + + const importButton = screen.queryByText("Import from ArcGIS"); + expect(importButton).not.toBeInTheDocument(); + }); + + it("Should render ArcGIS Import and Logout buttons", async () => { + const store = setupStore(); + // Let's Log in... + await store.dispatch(arcGisLogin()); + const { container } = callRender( + renderWithThemeProviders, + undefined, + store + ); + expect(container).toBeInTheDocument(); + expect(arcGisRequestLoginMock).toHaveBeenCalledTimes(1); + + // We are in the "Logged in" state, so the "Log in" button should NOT be there. + const importButton = await screen.findByText("Import from ArcGIS"); + expect(importButton).toBeInTheDocument(); + + const logoutUserInfo = await screen.findByText(mockEmailExpected); + expect(logoutUserInfo).toBeInTheDocument(); + + const loginButton = screen.queryByText("Login to ArcGIS"); + expect(loginButton).not.toBeInTheDocument(); + }); + + it("Should respond to action on the ArcGIS Login button", async () => { + const store = setupStore(); + // Let's Log out... + await store.dispatch(arcGisLogout()); + const { container } = callRender( + renderWithThemeProviders, + undefined, + store + ); + expect(container).toBeInTheDocument(); + + const loginButton = screen.getByText("Login to ArcGIS"); + loginButton && userEvent.click(loginButton); + expect(arcGisRequestLoginMock).toHaveBeenCalledTimes(1); + + const importButton = await screen.findByText("Import from ArcGIS"); + expect(importButton).toBeInTheDocument(); + + const loginButtonHidden = screen.queryByText("Login to ArcGIS"); + expect(loginButtonHidden).not.toBeInTheDocument(); + }); + + it("Should respond to action on ArcGIS Logout button", async () => { + const store = setupStore(); + // Let's Log in... + await store.dispatch(arcGisLogin()); + const { container } = callRender( + renderWithThemeProviders, + undefined, + store + ); + + const logoutButton = await screen.findByTestId("userinfo-button"); + logoutButton && userEvent.click(logoutButton); + + const modalDialog = await screen.findByTestId("modal-dialog-content"); + expect(modalDialog).toContainHTML("Are you sure you want to log out?"); + + const cancelButton = within(modalDialog).getByText("Log out"); + cancelButton && userEvent.click(cancelButton); + + const modalDialogHidden = screen.queryByTestId("modal-dialog-content"); + expect(modalDialogHidden).not.toBeInTheDocument(); + + const loginButton = await screen.findByText("Login to ArcGIS"); + expect(loginButton).toBeInTheDocument(); + }); +}); + describe("Layers Control Panel", () => { it("Should render LayersControlPanel without layers", () => { - const { container } = callRender(renderWithTheme); + const store = setupStore(); + const { container } = callRender( + renderWithThemeProviders, + undefined, + store + ); expect(container).toBeInTheDocument(); // Insert Buttons should be present @@ -68,37 +212,42 @@ describe("Layers Control Panel", () => { }); it("Should render LayersControlPanel with layers", () => { - const { container } = callRender(renderWithTheme, { - layers: [ - { id: "first", name: "first name", url: "https://first-url.com" }, - { id: "second", name: "second name", url: "https://second-url.com" }, - { - id: "third", - name: "third name", - url: "", - layers: [ - { - id: "fourth", - name: "fourth name", - url: "https://fourth-url.com", - }, - { id: "fith", name: "fith name", url: "https://fith-url.com" }, - { - id: "sixth", - name: "sixth name", - url: "https://sixth-url.com", - layers: [ - { - id: "seventh", - name: "seventh name", - url: "https://seventh-url.com", - }, - ], - }, - ], - }, - ], - }); + const store = setupStore(); + const { container } = callRender( + renderWithThemeProviders, + { + layers: [ + { id: "first", name: "first name", url: "https://first-url.com" }, + { id: "second", name: "second name", url: "https://second-url.com" }, + { + id: "third", + name: "third name", + url: "", + layers: [ + { + id: "fourth", + name: "fourth name", + url: "https://fourth-url.com", + }, + { id: "fith", name: "fith name", url: "https://fith-url.com" }, + { + id: "sixth", + name: "sixth name", + url: "https://sixth-url.com", + layers: [ + { + id: "seventh", + name: "seventh name", + url: "https://seventh-url.com", + }, + ], + }, + ], + }, + ], + }, + store + ); expect(container).toBeInTheDocument(); expect(screen.getByText("ListItem-first")).toBeInTheDocument(); @@ -111,7 +260,7 @@ describe("Layers Control Panel", () => { }); it("Should be able to call functions", () => { - const { container } = callRender(renderWithTheme, { + const { container } = callRender(renderWithThemeProviders, { layers: [ { id: "first", name: "first name", mapUrl: "https://first-url.com" }, ], @@ -139,7 +288,7 @@ describe("Layers Control Panel", () => { }); it("Should render conformation panel", () => { - callRender(renderWithTheme, { + callRender(renderWithThemeProviders, { layers: [ { id: "first", name: "first name", mapUrl: "https://first-url.com" }, // Candidate to delete diff --git a/src/components/layers-panel/layers-control-panel.tsx b/src/components/layers-panel/layers-control-panel.tsx index bf377d81..1da26ab2 100644 --- a/src/components/layers-panel/layers-control-panel.tsx +++ b/src/components/layers-panel/layers-control-panel.tsx @@ -1,20 +1,29 @@ import { Fragment, ReactEventHandler, useState } from "react"; import styled from "styled-components"; - -import { SelectionState, LayerExample, LayerViewState, ListItemType } from "../../types"; - +import { + SelectionState, + LayerExample, + LayerViewState, + ListItemType, +} from "../../types"; import { ListItem } from "./list-item/list-item"; import PlusIcon from "../../../public/icons/plus.svg"; import ImportIcon from "../../../public/icons/import.svg"; import EsriImage from "../../../public/images/esri.svg"; import { ActionIconButton } from "../action-icon-button/action-icon-button"; import { AcrGisUser } from "../arcgis-user/arcgis-user"; - import { DeleteConfirmation } from "./delete-confirmation"; import { LayerOptionsMenu } from "./layer-options-menu/layer-options-menu"; import { handleSelectAllLeafsInGroup } from "../../utils/layer-utils"; import { ButtonSize } from "../../types"; import { PanelHorizontalLine } from "../common"; +import { + arcGisLogin, + arcGisLogout, + selectUser, +} from "../../redux/slices/arcgis-auth-slice"; +import { useAppDispatch, useAppSelector } from "../../redux/hooks"; +import { ModalDialog } from "../modal-dialog/modal-dialog"; type LayersControlPanelProps = { layers: LayerExample[]; @@ -69,6 +78,20 @@ const EsriStyledImage = styled(EsriImage)` fill: ${({ theme }) => theme.colors.esriImageColor}; `; +const TextInfo = styled.div` + font-style: normal; + font-weight: 500; + font-size: 16px; + line-height: 19px; +`; + +const TextUser = styled.div` + font-style: normal; + font-weight: 700; + font-size: 16px; + line-height: 19px; +`; + export const LayersControlPanel = ({ layers, type, @@ -81,16 +104,22 @@ export const LayersControlPanel = ({ onPointToLayer, deleteLayer, }: LayersControlPanelProps) => { + const dispatch = useAppDispatch(); + + const username = useAppSelector(selectUser); + const isLoggedIn = !!username; + + const [showLogoutWarning, setShowLogoutWarning] = useState(false); const [settingsLayerId, setSettingsLayerId] = useState(""); const [showLayerSettings, setShowLayerSettings] = useState(false); const [layerToDeleteId, setLayerToDeleteId] = useState(""); - /// Stab { - const username = 'Michael-g'; - const [isLoggedIn, setIsLoggedIn] = useState(false); - const onArcGisActionClick = () => { !isLoggedIn && setIsLoggedIn(true) }; - const onArcGisLogoutClick = () => { setIsLoggedIn(false) }; - /// Stab } + const onArcGisActionClick = () => { + !isLoggedIn && dispatch(arcGisLogin()); + }; + const onArcGisLogoutClick = () => { + setShowLogoutWarning(true); + }; const isListItemSelected = ( layer: LayerExample, @@ -101,23 +130,31 @@ export const LayersControlPanel = ({ let selectedState = SelectionState.unselected; if (!childLayers.length) { - selectedState = selectedLayerIds.includes(layer.id) ? SelectionState.selected : SelectionState.unselected; + selectedState = selectedLayerIds.includes(layer.id) + ? SelectionState.selected + : SelectionState.unselected; } if (childLayers.length && !parentLayer) { - selectedState = groupLeafs.some((leaf) => selectedLayerIds.includes(leaf.id)) ? SelectionState.selected : SelectionState.unselected; + selectedState = groupLeafs.some((leaf) => + selectedLayerIds.includes(leaf.id) + ) + ? SelectionState.selected + : SelectionState.unselected; } if (childLayers.length && parentLayer) { const isAllChildLayersSelected = !groupLeafs.some( - (leaf) => !selectedLayerIds.includes(leaf.id)); - const isAnyChildLayerSelected = groupLeafs.some( - (leaf) => selectedLayerIds.includes(leaf.id)); + (leaf) => !selectedLayerIds.includes(leaf.id) + ); + const isAnyChildLayerSelected = groupLeafs.some((leaf) => + selectedLayerIds.includes(leaf.id) + ); if (isAllChildLayersSelected) { selectedState = SelectionState.selected; } else if (isAnyChildLayerSelected) { - selectedState = SelectionState.indeterminate + selectedState = SelectionState.indeterminate; } } @@ -197,17 +234,30 @@ export const LayersControlPanel = ({ {renderLayers(layers)} - + Insert layer - + Insert scene - + {!isLoggedIn && "Login to ArcGIS"} {isLoggedIn && "Import from ArcGIS"} @@ -215,9 +265,25 @@ export const LayersControlPanel = ({ {isLoggedIn && ( - - {username} - + {username} + )} + + {showLogoutWarning && ( + { + dispatch(arcGisLogout()); + setShowLogoutWarning(false); + }} + onCancel={() => { + setShowLogoutWarning(false); + }} + > + Are you sure you want to log out? + You are logged in as + {username} + )} diff --git a/src/components/modal-dialog/modal-dialog.spec.tsx b/src/components/modal-dialog/modal-dialog.spec.tsx new file mode 100644 index 00000000..849f5657 --- /dev/null +++ b/src/components/modal-dialog/modal-dialog.spec.tsx @@ -0,0 +1,44 @@ +import { screen, within } from "@testing-library/react"; +import { renderWithThemeProviders } from "../../utils/testing-utils/render-with-theme"; +import { ModalDialog } from "./modal-dialog"; +import userEvent from "@testing-library/user-event"; +import { setupStore } from "../../redux/store"; + +const onCancel = jest.fn(); +const onConfirm = jest.fn(); + +const callRender = (renderFunc, store = setupStore()) => { + return renderFunc( + + <> + , + store + ); +}; + +describe("ModalDialog", () => { + it("Should render dialog", async () => { + const store = setupStore(); + const { container } = callRender(renderWithThemeProviders, store); + expect(container).toBeInTheDocument(); + const dialog = screen.getByTestId("modal-dialog-content"); + expect(dialog).toBeInTheDocument(); + + const title = within(dialog).getByText("Test Title"); + expect(title).toBeInTheDocument(); + + const okButton = within(dialog).getByText("Log out"); + okButton && userEvent.click(okButton); + expect(onConfirm).toHaveBeenCalledTimes(1); + + const cancelButton = within(dialog).getByText("Exit"); + cancelButton && userEvent.click(cancelButton); + expect(onCancel).toHaveBeenCalledTimes(1); + }); +}); diff --git a/src/components/modal-dialog/modal-dialog.tsx b/src/components/modal-dialog/modal-dialog.tsx new file mode 100644 index 00000000..e2248bba --- /dev/null +++ b/src/components/modal-dialog/modal-dialog.tsx @@ -0,0 +1,140 @@ +import styled, { useTheme } from "styled-components"; +import { ActionButton } from "../action-button/action-button"; +import { ActionButtonVariant } from "../../types"; +import CloseIcon from "../../../public/icons/close.svg"; +import { color_brand_primary } from "../../constants/colors"; + +const Overlay = styled.div` + position: fixed; + left: 0; + top: 0; + width: 100%; + height: 100%; + display: flex; + justify-content: center; + align-items: center; + background: ${color_brand_primary}80; + z-index: 103; +`; + +const WrapperContainer = styled.div` + position: fixed; + left: 0; + top: 0; + width: 100%; + height: 100%; + display: flex; + justify-content: center; + align-items: center; + visibility: hidden; + z-index: 104; +`; + +const Container = styled.div` + position: absolute; + display: flex; + flex-direction: column; + border-radius: 8px; + background: ${({ theme }) => theme.colors.mainHelpPanelColor}; + visibility: visible; + z-index: 105; +`; + +const IconContainer = styled.div` + position: absolute; + display: flex; + justify-content: center; + align-items: center; + border-radius: 8px; + top: 13px; + right: 14px; + width: 44px; + height: 44px; +`; + +const ContentContainer = styled.div` + display: flex; + flex-direction: column; + justify-content: start; + height: 100%; + width: 100%; + margin: 32px 32px 0 32px; + row-gap: 16px; + color: ${({ theme }) => theme.colors.fontColor}; +`; + +const Title = styled.div` + font-style: normal; + font-weight: 700; + font-size: 32px; + line-height: 45px; +`; + +const ButtonsContainer = styled.div` + display: flex; + flex-direction: row; + justify-content: center; + margin: 32px; + column-gap: 18px; + { + > * { + width: 180px; + } + } +`; + +type LogoutPanelProps = { + title: string; + children: JSX.Element | JSX.Element[]; + okButtonText?: string; + cancelButtonText?: string; + onCancel: () => void; + onConfirm: () => void; +}; + +const CloseCrossButton = styled(CloseIcon)` + cursor: pointer; + &:hover { + fill: ${({ theme }) => theme.colors.mainDimColorInverted}; + } +`; + +export const ModalDialog = ({ + title, + children, + cancelButtonText = "Cancel", + okButtonText = "Ok", + onCancel, + onConfirm, +}: LogoutPanelProps) => { + const theme = useTheme(); + + return ( + <> + + + + + + + + {title} + {children} + + + + {cancelButtonText} + + {okButtonText} + + + + + ); +}; diff --git a/src/pages/auth/auth.tsx b/src/pages/auth/auth.tsx new file mode 100644 index 00000000..2bb257d7 --- /dev/null +++ b/src/pages/auth/auth.tsx @@ -0,0 +1,44 @@ +import { useEffect } from "react"; +import Background from "../../../public/images/tools-background.webp"; +import styled from "styled-components"; +import { + getCurrentLayoutProperty, + useAppLayout, +} from "../../utils/hooks/layout"; + +import { arcGisCompleteLogin } from "../../utils/arcgis-auth"; + +export type LayoutProps = { + layout: string; +}; + +const AuthContainer = styled.div` + display: flex; + flex-direction: column; + width: 100%; + overflow: auto; + overflow-x: hidden; + background: url(${Background}); + background-attachment: fixed; + background-size: cover; + + height: ${getCurrentLayoutProperty({ + desktop: "calc(100vh - 65px)", + tablet: "calc(100vh - 65px)", + mobile: "calc(100vh - 58px)", + })}; + + margin-top: ${getCurrentLayoutProperty({ + desktop: "65px", + tablet: "65px", + mobile: "58px", + })}; +`; + +export const AuthApp = () => { + const layout = useAppLayout(); + useEffect(() => { + arcGisCompleteLogin(); + }, []); + return ; +}; diff --git a/src/pages/auth/e2e.auth.spec.ts b/src/pages/auth/e2e.auth.spec.ts new file mode 100644 index 00000000..7f486212 --- /dev/null +++ b/src/pages/auth/e2e.auth.spec.ts @@ -0,0 +1,23 @@ +import puppeteer from "puppeteer"; + +describe("Auth page Default View", () => { + let browser; + let page; + + beforeAll(async () => { + browser = await puppeteer.launch(); + page = await browser.newPage(); + await page.setViewport({ width: 1366, height: 768 }); + await page.goto("http://localhost:3000"); + }); + + afterAll(() => browser.close()); + + it("Should render the page", async () => { + const authPageUrl = "http://localhost:3000/auth"; + + await page.goto(authPageUrl); + const currentUrl = page.url(); + expect(currentUrl).toBe(authPageUrl); + }); +}); diff --git a/src/pages/index.ts b/src/pages/index.ts index 870791a3..ae493050 100644 --- a/src/pages/index.ts +++ b/src/pages/index.ts @@ -2,4 +2,5 @@ export { Dashboard } from "./dashboard/dashboard"; export { ViewerApp } from "./viewer-app/viewer-app"; export { DebugApp } from "./debug-app/debug-app"; export { Comparison } from './comparison/comparison'; +export { AuthApp } from './auth/auth'; diff --git a/src/redux/slices/arcgis-auth-slice.spec.ts b/src/redux/slices/arcgis-auth-slice.spec.ts new file mode 100644 index 00000000..8023ff9a --- /dev/null +++ b/src/redux/slices/arcgis-auth-slice.spec.ts @@ -0,0 +1,76 @@ +import { setupStore } from "../store"; +import reducer, { + selectUser, + arcGisLogin, + arcGisLogout, +} from "./arcgis-auth-slice"; + +import { + getAuthenticatedUser, + arcGisRequestLogin, + arcGisCompleteLogin, + arcGisRequestLogout, +} from "../../utils/arcgis-auth"; + +jest.mock("../../utils/arcgis-auth"); + +const getAuthenticatedUserMock = + getAuthenticatedUser as unknown as jest.Mocked; +const arcGisRequestLoginMock = + arcGisRequestLogin as unknown as jest.Mocked; +const arcGisCompleteLoginMock = + arcGisCompleteLogin as unknown as jest.Mocked; +const arcGisRequestLogoutMock = + arcGisRequestLogout as unknown as jest.Mocked; + +const mockEmailExpected = "usermail@gmail.com"; +let mockStorageUserinfo = mockEmailExpected; + +describe("slice: arcgis-auth", () => { + beforeAll(() => { + arcGisRequestLoginMock.mockImplementation(async () => { + mockStorageUserinfo = mockEmailExpected; + return mockStorageUserinfo; + }); + arcGisCompleteLoginMock.mockImplementation(async () => { + return mockStorageUserinfo; + }); + arcGisRequestLogoutMock.mockImplementation(async () => { + mockStorageUserinfo = ""; + return mockStorageUserinfo; + }); + getAuthenticatedUserMock.mockImplementation(() => { + return mockStorageUserinfo; + }); + }); + + beforeEach(() => { + mockStorageUserinfo = mockEmailExpected; + }); + + it("Reducer should return the initial state", () => { + expect(reducer(undefined, { type: undefined })).toEqual({ + user: mockEmailExpected, + }); + }); + + it("Selector should return the initial state", () => { + const store = setupStore(); + const state = store.getState(); + expect(selectUser(state)).toEqual(mockEmailExpected); + }); + + it("Selector should return the updated value after Login", async () => { + const store = setupStore(); + await store.dispatch(arcGisLogin()); + const state = store.getState(); + expect(selectUser(state)).toEqual(mockEmailExpected); + }); + + it("Selector should return the updated value after Logout", async () => { + const store = setupStore(); + await store.dispatch(arcGisLogout()); + const state = store.getState(); + expect(selectUser(state)).toEqual(""); + }); +}); diff --git a/src/redux/slices/arcgis-auth-slice.ts b/src/redux/slices/arcgis-auth-slice.ts new file mode 100644 index 00000000..7e7f6ea6 --- /dev/null +++ b/src/redux/slices/arcgis-auth-slice.ts @@ -0,0 +1,44 @@ +import { createSlice, createAsyncThunk } from "@reduxjs/toolkit"; +import { RootState } from "../store"; +import { + getAuthenticatedUser, + arcGisRequestLogin, + arcGisRequestLogout, +} from "../../utils/arcgis-auth"; + +// Define a type for the slice state +export interface ArcGisAuthState { + user: string; +} + +// "lazy initializer" +const initialState = () => { + return { user: getAuthenticatedUser() }; +}; + +const arcGisAuthSlice = createSlice({ + name: "arcGisAuth", + initialState, + reducers: {}, + extraReducers: (builder) => { + builder + .addCase(arcGisLogin.fulfilled, (state, action) => { + state.user = action.payload || ""; + }) + .addCase(arcGisLogout.fulfilled, (state) => { + state.user = ""; + }); + }, +}); + +export const arcGisLogin = createAsyncThunk("arcGisLogin", async () => { + return await arcGisRequestLogin(); +}); + +export const arcGisLogout = createAsyncThunk("arcGisLogout", async () => { + return await arcGisRequestLogout(); +}); + +export const selectUser = (state: RootState): string => state.arcGisAuth.user; + +export default arcGisAuthSlice.reducer; diff --git a/src/redux/store.ts b/src/redux/store.ts index 61230baa..4b5b407d 100644 --- a/src/redux/store.ts +++ b/src/redux/store.ts @@ -10,6 +10,7 @@ import debugOptionsSliceReducer from "./slices/debug-options-slice"; import i3sStatsSliceReducer from "./slices/i3s-stats-slice"; import baseMapsSliceReducer from "./slices/base-maps-slice"; import symbolizationSliceReducer from "./slices/symbolization-slice"; +import arcGisAuthSliceReducer from "./slices/arcgis-auth-slice"; // Create the root reducer separately so we can extract the RootState type const rootReducer = combineReducers({ @@ -20,6 +21,7 @@ const rootReducer = combineReducers({ baseMaps: baseMapsSliceReducer, symbolization: symbolizationSliceReducer, i3sStats: i3sStatsSliceReducer, + arcGisAuth: arcGisAuthSliceReducer, }); export const setupStore = (preloadedState?: PreloadedState) => { diff --git a/src/utils/arcgis-auth.spec.ts b/src/utils/arcgis-auth.spec.ts new file mode 100644 index 00000000..34ebf69d --- /dev/null +++ b/src/utils/arcgis-auth.spec.ts @@ -0,0 +1,44 @@ +import { + getAuthenticatedUser, + arcGisRequestLogin, + arcGisRequestLogout, +} from "./arcgis-auth"; + +jest.mock("@esri/arcgis-rest-request"); + +const ARCGIS_REST_USER_INFO = "__ARCGIS_REST_USER_INFO__"; +const mockEmailExpected = "usermail@gmail.com"; + +let OLD_ENV = {}; + +beforeAll(() => { + OLD_ENV = process.env; +}); + +describe("ArcGIS auth functions", () => { + beforeEach(() => { + jest.resetModules(); // Clear the cache + process.env = { ...OLD_ENV }; + process.env.REACT_APP_ARCGIS_REST_CLIENT_ID = "CLIENT_ID"; + }); + + afterAll(() => { + process.env = OLD_ENV; + }); + + it("Should return email of user logged in", () => { + localStorage.setItem(ARCGIS_REST_USER_INFO, mockEmailExpected); + const email = getAuthenticatedUser(); + expect(email).toEqual(mockEmailExpected); + }); + + it("Should request login and return email of user", async () => { + const email = await arcGisRequestLogin(); + expect(email).toBe(mockEmailExpected); + }); + + it("Should request logout and return empty string", async () => { + const email = await arcGisRequestLogout(); + expect(email).toBe(""); + }); +}); diff --git a/src/utils/arcgis-auth.ts b/src/utils/arcgis-auth.ts new file mode 100644 index 00000000..36d397ca --- /dev/null +++ b/src/utils/arcgis-auth.ts @@ -0,0 +1,99 @@ +import { ArcGISIdentityManager } from "@esri/arcgis-rest-request"; + +const ARCGIS_REST_USER_SESSION = "__ARCGIS_REST_USER_SESSION__"; +const ARCGIS_REST_USER_INFO = "__ARCGIS_REST_USER_INFO__"; + +const updateSessionInfo = async ( + session?: ArcGISIdentityManager +): Promise => { + let email = ""; + if (session) { + localStorage.setItem(ARCGIS_REST_USER_SESSION, session.serialize()); + const user = await session.getUser(); + email = user.email || ""; + localStorage.setItem(ARCGIS_REST_USER_INFO, email); + } else { + localStorage.removeItem(ARCGIS_REST_USER_SESSION); + localStorage.removeItem(ARCGIS_REST_USER_INFO); + } + return email; +}; + +function getArcGisSession(): ArcGISIdentityManager | undefined { + let session; + const itemString = localStorage.getItem(ARCGIS_REST_USER_SESSION); + if (itemString) { + session = ArcGISIdentityManager.deserialize(itemString); + } + return session; +} + +/** + * Gets the redirection URL and the client ID to use in the ArcGIS authentication workflow. + * @returns the redirection URL and the client ID. + */ +const getAuthOptions = () => { + const port = window.location.port ? `:${window.location.port}` : ""; + const options = { + redirectUri: `${window.location.protocol}//${window.location.hostname}${port}/auth`, + clientId: process.env.REACT_APP_ARCGIS_REST_CLIENT_ID || "", + popup: true, + pkce: true, + }; + + if (!options.clientId) { + console.error("The ClientId is not defined in .env file."); + } + return options; +}; + +/** + * Gets the email of the currently logged in user. + * @returns the user's email or an empty string if the user is not logged in. + */ +export const getAuthenticatedUser = (): string => { + return localStorage.getItem(ARCGIS_REST_USER_INFO) || ""; +}; + +/** + * Makes an ArcGIS login request by opening a popup dialog. + * @returns email of the user logged in or an empty string if the user is not logged in. + */ +export const arcGisRequestLogin = async () => { + let email = ""; + + const options = getAuthOptions(); + if (options.clientId) { + let session: ArcGISIdentityManager | undefined; + try { + session = await ArcGISIdentityManager.beginOAuth2(options); + } finally { + // In case of an exception the session is not set. + // So the following call will remove any session stored in the local storage. + email = await updateSessionInfo(session); + } + } + return email; +}; + +/** + * Completes the ArcGIS login request started by {@link arcGisRequestLogin}. + */ +export const arcGisCompleteLogin = async () => { + const options = getAuthOptions(); + if (options.clientId) { + ArcGISIdentityManager.completeOAuth2(options); + } +}; + +/** + * Makes an ArcGIS logout request. + * @returns empty string + */ +export const arcGisRequestLogout = async () => { + const session = getArcGisSession(); + if (session) { + await ArcGISIdentityManager.destroy(session); + } + return await updateSessionInfo(); +}; diff --git a/webpack.dev.config.js b/webpack.dev.config.js index 3b952f7d..a5288e44 100644 --- a/webpack.dev.config.js +++ b/webpack.dev.config.js @@ -100,6 +100,7 @@ module.exports = (env) => { devServer: { open: true, port: 3000, + server: 'https', client: { overlay: { errors: true, From f7d49a54cf14923c0b647c41fd768096eba252af Mon Sep 17 00:00:00 2001 From: mspivak-actionengine <118991512+mspivak-actionengine@users.noreply.github.com> Date: Tue, 9 Jan 2024 22:32:53 +0300 Subject: [PATCH 14/40] fix(e2e-test): random failures on navigation (#340) --- src/pages/dashboard/e2e.dashboard.spec.ts | 102 +++++++++++--------- src/pages/debug-app/e2e.debug-app.spec.ts | 4 +- src/pages/viewer-app/e2e.viewer-app.spec.ts | 4 +- src/utils/testing-utils/utils.ts | 36 +++++++ 4 files changed, 95 insertions(+), 51 deletions(-) create mode 100644 src/utils/testing-utils/utils.ts diff --git a/src/pages/dashboard/e2e.dashboard.spec.ts b/src/pages/dashboard/e2e.dashboard.spec.ts index c9116c94..dda77457 100644 --- a/src/pages/dashboard/e2e.dashboard.spec.ts +++ b/src/pages/dashboard/e2e.dashboard.spec.ts @@ -1,4 +1,5 @@ import puppeteer from "puppeteer"; +import { clickAndNavigate } from "../../utils/testing-utils/utils"; describe("Dashboard Default View", () => { let browser; @@ -50,9 +51,12 @@ describe("Dashboard Default View", () => { it("Should go to the Viewer page", async () => { await page.goto("http://localhost:3000"); await page.waitForSelector("#header-links-default"); - await page.click("a[href='/viewer']"); - await page.waitForTimeout(5000); - const currentUrl = page.url(); + + const currentUrl = await clickAndNavigate( + page, + "a[href='/viewer']", + "tileset=" + ); expect(currentUrl).toBe( "http://localhost:3000/viewer?tileset=san-francisco-v1_7" ); @@ -63,9 +67,11 @@ describe("Dashboard Default View", () => { it("Should go to the Debug page", async () => { await page.goto("http://localhost:3000"); await page.waitForSelector("#header-links-default"); - await page.click("a[href='/debug']"); - await page.waitForTimeout(5000); - const currentUrl = page.url(); + const currentUrl = await clickAndNavigate( + page, + "a[href='/debug']", + "tileset=" + ); expect(currentUrl).toBe( "http://localhost:3000/debug?tileset=san-francisco-v1_7" ); @@ -78,9 +84,10 @@ describe("Dashboard Default View", () => { await page.waitForSelector("#compare-default-button"); await page.click("#compare-default-button"); await page.hover("a[href='/compare-across-layers']"); - await page.click("a[href='/compare-across-layers']"); - - const currentUrl = page.url(); + const currentUrl = await clickAndNavigate( + page, + "a[href='/compare-across-layers']" + ); expect(currentUrl).toBe("http://localhost:3000/compare-across-layers"); }); @@ -89,28 +96,28 @@ describe("Dashboard Default View", () => { await page.waitForSelector("#compare-default-button"); await page.click("#compare-default-button"); await page.hover("a[href='/compare-within-layer']"); - await page.click("a[href='/compare-within-layer']"); - - const currentUrl = page.url(); + const currentUrl = await clickAndNavigate( + page, + "a[href='/compare-within-layer']" + ); expect(currentUrl).toBe("http://localhost:3000/compare-within-layer"); }); it("Should go to the project GitHub page", async () => { await page.goto("http://localhost:3000"); await page.waitForSelector("#header-links-default"); - await page.click("a[href='https://github.com/visgl/loaders.gl-showcases']"); - await page.waitForTimeout(5000); + const currentUrl = await clickAndNavigate( + page, + "a[href='https://github.com/visgl/loaders.gl-showcases']" + ); - const currentUrl = page.url(); expect(currentUrl).toBe("https://github.com/visgl/loaders.gl-showcases"); await page.goto("http://localhost:3000"); }); it("Should return from viewer page to Dashboard", async () => { await page.goto("http://localhost:3000/viewer"); - await page.waitForSelector("#header-links-default"); - await page.click("a[href='/dashboard']"); - const currentUrl = page.url(); + const currentUrl = await clickAndNavigate(page, "a[href='/dashboard']"); expect(currentUrl).toBe("http://localhost:3000/dashboard"); const dashboardCanvas = await page.$$("#dashboard-app"); expect(dashboardCanvas).toBeDefined(); @@ -287,9 +294,7 @@ describe("Dashboard Default View", () => { it("Should go to viewer page from tools description", async () => { await page.waitForSelector("#viewer-link"); - await page.click("#viewer-link"); - - const currentUrl = page.url(); + const currentUrl = await clickAndNavigate(page, "#viewer-link", "tileset="); expect(currentUrl).toBe( "http://localhost:3000/viewer?tileset=san-francisco-v1_7" ); @@ -298,9 +303,7 @@ describe("Dashboard Default View", () => { it("Should go to debug page from tools description", async () => { await page.goto("http://localhost:3000"); await page.waitForSelector("#debug-link"); - await page.click("#debug-link"); - await page.waitForTimeout(5000); - const currentUrl = page.url(); + const currentUrl = await clickAndNavigate(page, "#debug-link", "tileset="); expect(currentUrl).toBe( "http://localhost:3000/debug?tileset=san-francisco-v1_7" ); @@ -309,9 +312,11 @@ describe("Dashboard Default View", () => { it("Should go to the Comparison Across Layers Page", async () => { await page.goto("http://localhost:3000"); await page.waitForSelector("#comparison-link"); - await page.click("#comparison-link"); - - const currentUrl = page.url(); + const currentUrl = await clickAndNavigate( + page, + "#comparison-link", + "tileset=" + ); expect(currentUrl).toBe("http://localhost:3000/compare-across-layers"); }); }); @@ -412,10 +417,11 @@ describe("Dashboard Tablet or Mobile view", () => { await page.waitForSelector("#burger-menu"); await page.click("#burger-menu"); await page.waitForSelector("#header-links"); - await page.click("a[href='/viewer']"); - await page.waitForTimeout(5000); - - const currentUrl = page.url(); + const currentUrl = await clickAndNavigate( + page, + "a[href='/viewer']", + "tileset=" + ); expect(currentUrl).toBe( "http://localhost:3000/viewer?tileset=san-francisco-v1_7" ); @@ -429,10 +435,11 @@ describe("Dashboard Tablet or Mobile view", () => { await page.waitForSelector("#burger-menu"); await page.click("#burger-menu"); await page.waitForSelector("#header-links"); - await page.click("a[href='/debug']"); - await page.waitForTimeout(5000); - - const currentUrl = page.url(); + const currentUrl = await clickAndNavigate( + page, + "a[href='/debug']", + "tileset=" + ); expect(currentUrl).toBe( "http://localhost:3000/debug?tileset=san-francisco-v1_7" ); @@ -446,10 +453,11 @@ describe("Dashboard Tablet or Mobile view", () => { await page.waitForSelector("#burger-menu"); await page.click("#burger-menu"); await page.waitForSelector("#header-links"); - await page.click("a[href='https://github.com/visgl/loaders.gl-showcases']"); - await page.waitForTimeout(5000); + const currentUrl = await clickAndNavigate( + page, + "a[href='https://github.com/visgl/loaders.gl-showcases']" + ); - const currentUrl = page.url(); expect(currentUrl).toBe("https://github.com/visgl/loaders.gl-showcases"); expect(!(await page.$("#tablet-or-mobile-menu"))); }); @@ -459,9 +467,7 @@ describe("Dashboard Tablet or Mobile view", () => { await page.waitForSelector("#burger-menu"); await page.click("#burger-menu"); await page.waitForSelector("#header-links"); - await page.click("a[href='/dashboard']"); - - const currentUrl = page.url(); + const currentUrl = await clickAndNavigate(page, "a[href='/dashboard']"); expect(currentUrl).toBe("http://localhost:3000/dashboard"); const dashboardCanvas = await page.$$("#dashboard-app"); expect(dashboardCanvas).toBeDefined(); @@ -501,15 +507,16 @@ describe("Dashboard Tablet or Mobile view", () => { await page.click("#compare-tablet-or-mobile-button"); await page.hover("a[href='/compare-across-layers']"); - await page.click("a[href='/compare-across-layers']"); + const currentUrl = await clickAndNavigate( + page, + "a[href='/compare-across-layers']" + ); await page.waitForSelector("#left-deck-container"); await page.waitForSelector("#right-deck-container"); expect(await page.$$("#left-deck-container")).toBeDefined(); expect(await page.$$("#right-deck-container")).toBeDefined(); - - const currentUrl = page.url(); expect(currentUrl).toBe("http://localhost:3000/compare-across-layers"); }); @@ -521,15 +528,16 @@ describe("Dashboard Tablet or Mobile view", () => { await page.click("#compare-tablet-or-mobile-button"); await page.hover("a[href='/compare-within-layer']"); - await page.click("a[href='/compare-within-layer']"); + const currentUrl = await clickAndNavigate( + page, + "a[href='/compare-within-layer']" + ); await page.waitForSelector("#left-deck-container"); await page.waitForSelector("#right-deck-container"); expect(await page.$$("#left-deck-container")).toBeDefined(); expect(await page.$$("#right-deck-container")).toBeDefined(); - - const currentUrl = page.url(); expect(currentUrl).toBe("http://localhost:3000/compare-within-layer"); }); }); diff --git a/src/pages/debug-app/e2e.debug-app.spec.ts b/src/pages/debug-app/e2e.debug-app.spec.ts index 22f916bd..79b22117 100644 --- a/src/pages/debug-app/e2e.debug-app.spec.ts +++ b/src/pages/debug-app/e2e.debug-app.spec.ts @@ -31,7 +31,7 @@ describe("Debug", () => { expect( await page.$eval( "#header-links-default>a[active='1']", - (node) => node.innerText + (node) => node.textContent ) ).toEqual("Debug"); }); @@ -134,7 +134,7 @@ describe("Debug - Layers panel", () => { expect( await page.$eval( "#debug--layers-panel #san-francisco-v1_7>input", - (node) => node.checked + (node) => (node as HTMLInputElement).checked ) ).toBeTruthy(); }); diff --git a/src/pages/viewer-app/e2e.viewer-app.spec.ts b/src/pages/viewer-app/e2e.viewer-app.spec.ts index f34bf9a0..fc59db2b 100644 --- a/src/pages/viewer-app/e2e.viewer-app.spec.ts +++ b/src/pages/viewer-app/e2e.viewer-app.spec.ts @@ -31,7 +31,7 @@ describe("Viewer", () => { expect( await page.$eval( "#header-links-default>a[active='1']", - (node) => node.innerText + (node) => node.textContent ) ).toEqual("Viewer"); }); @@ -118,7 +118,7 @@ describe("Viewer - Layers panel", () => { expect( await page.$eval( "#viewer--layers-panel #san-francisco-v1_7>input", - (node) => node.checked + (node) => (node as HTMLInputElement).checked ) ).toBeTruthy(); }); diff --git a/src/utils/testing-utils/utils.ts b/src/utils/testing-utils/utils.ts new file mode 100644 index 00000000..8605c92e --- /dev/null +++ b/src/utils/testing-utils/utils.ts @@ -0,0 +1,36 @@ +import { Page } from "puppeteer"; + +const URL_CHECKING_INTERVAL = 500; +const URL_CHECKING_TIMEOUT = 10000; +/** + * Clicks on an element and waits until indirect navigations complete. + * In case of multiple navigations performed by the application with unpredictable timings + * you might want to wait for the current URL to match some string before returning. + * @param page - Page instance. + * @param selector - Selector of the element to click on. + * @param waitFor - substring that is expected to be a part of the URL. + * @returns current URL. + */ +export const clickAndNavigate = async ( + page: Page, + selector: string, + waitFor?: string +) => { + await Promise.all([ + page.waitForNavigation({ + waitUntil: ["load", "domcontentloaded", "networkidle0"], + }), + page.click(selector), + ]); + let currentUrl = page.url(); + if (waitFor) { + for (let i = 0; i < URL_CHECKING_TIMEOUT / URL_CHECKING_INTERVAL; i++) { + await page.waitForTimeout(URL_CHECKING_INTERVAL); + currentUrl = page.url(); + if (currentUrl.indexOf(waitFor) !== -1) { + break; + } + } + } + return currentUrl; +}; From 5b8d178777e683f2f77bd4ec7eef51b6676a8fe3 Mon Sep 17 00:00:00 2001 From: mspivak-actionengine <118991512+mspivak-actionengine@users.noreply.github.com> Date: Tue, 9 Jan 2024 22:38:51 +0300 Subject: [PATCH 15/40] feat(arcgis): convert link to rest format (#338) --- src/components/layers-panel/layers-panel.tsx | 4 ++- src/utils/url-utils.spec.ts | 14 +++++++++++ src/utils/url-utils.ts | 26 ++++++++++++++++++++ 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/src/components/layers-panel/layers-panel.tsx b/src/components/layers-panel/layers-panel.tsx index bec8fa9d..8fa137de 100644 --- a/src/components/layers-panel/layers-panel.tsx +++ b/src/components/layers-panel/layers-panel.tsx @@ -34,7 +34,7 @@ import { useClickOutside } from "../../utils/hooks/use-click-outside-hook"; import { ArcGISWebSceneLoader } from "@loaders.gl/i3s"; import { ActiveSublayer } from "../../utils/active-sublayer"; import { useAppLayout } from "../../utils/hooks/layout"; -import { getTilesetType } from "../../utils/url-utils"; +import { getTilesetType, convertUrlToRestFormat } from "../../utils/url-utils"; import { convertArcGisSlidesToBookmars } from "../../utils/bookmarks-utils"; import { useAppDispatch } from "../../redux/hooks"; import { addBaseMap } from "../../redux/slices/base-maps-slice"; @@ -253,6 +253,8 @@ export const LayersPanel = ({ url: string; token?: string; }) => { + scene.url = convertUrlToRestFormat(scene.url); + const existedScene = layers.some( (exisLayer) => exisLayer.url.trim() === scene.url.trim() ); diff --git a/src/utils/url-utils.spec.ts b/src/utils/url-utils.spec.ts index 533b8685..5854c18d 100644 --- a/src/utils/url-utils.spec.ts +++ b/src/utils/url-utils.spec.ts @@ -5,6 +5,7 @@ import { parseTilesetUrlParams, urlParamsToViewState, viewStateToUrlParams, + convertUrlToRestFormat, } from "./url-utils"; const mockResponse = jest.fn(); @@ -179,3 +180,16 @@ describe("Url Utils - urlParamsToViewState", () => { }); }); }); + +describe("Url Utils - convertUrlToRestFormat", () => { + test("Should convert to the format required", () => { + const urlExpected = "https://www.arcgis.com/sharing/rest/content/items/ae34b234d390148/data"; + + const urlItem = "https://some.maps.arcgis.com/home/item.html?id=ae34b234d390148"; + const urlViewer = "https://some.maps.arcgis.com/home/webscene/viewer.html?webscene=ae34b234d390148"; + expect(convertUrlToRestFormat(urlItem)).toEqual(urlExpected); + expect(convertUrlToRestFormat(urlViewer)).toEqual(urlExpected); + + expect(convertUrlToRestFormat(urlExpected)).toEqual(urlExpected); + }); +}); diff --git a/src/utils/url-utils.ts b/src/utils/url-utils.ts index 3618e107..f6b8559d 100644 --- a/src/utils/url-utils.ts +++ b/src/utils/url-utils.ts @@ -96,3 +96,29 @@ export const urlParamsToViewState = (viewState: ViewStateSet) => { } return urlViewStateParams; }; + +/** + * Converts the link of a webscene that can be copied from ArcGIS + * to the format required by i3s-explorer to insert a webscene. + * @param url - Url copied from ArcGIS. + * @returns Url converted. + */ +export const convertUrlToRestFormat = (url: string): string => { + let urlRest = "https://www.arcgis.com/sharing/rest/content/items/"; + const urlObject = new URL(url); + + let param: string | null = null; + for (const paramName of ["id", "webscene"]) { + param = urlObject.searchParams.get(paramName); + if (param) { + break; + } + } + if (param) { + urlRest += param + "/data"; + } else { + // The url cannot be converted. Use it "as is". + return url; + } + return urlRest; +}; From e531f73171db24cf714b842f99a822c11a9df72f Mon Sep 17 00:00:00 2001 From: mspivak-actionengine <118991512+mspivak-actionengine@users.noreply.github.com> Date: Tue, 16 Jan 2024 20:20:36 +0300 Subject: [PATCH 16/40] feat(arcgis): support arcgis content (#335) --- __mocks__/@esri/arcgis-rest-portal.ts | 28 ++ __mocks__/@esri/arcgis-rest-request.ts | 27 +- package.json | 1 + src/components/common.tsx | 4 +- src/components/expand-icon/expand-icon.tsx | 21 +- .../arcgis-control-panel.spec.tsx | 150 ++++++++ .../layers-panel/arcgis-control-panel.tsx | 133 ++++++++ .../arcgis-import-panel.spec.tsx | 146 ++++++++ .../arcgis-import-panel.tsx | 320 ++++++++++++++++++ .../layers-control-panel.spec.tsx | 139 +------- .../layers-panel/layers-control-panel.tsx | 88 +---- src/components/layers-panel/layers-panel.tsx | 15 +- src/components/modal-dialog/modal-dialog.tsx | 37 +- src/pages/auth/auth.tsx | 2 +- src/pages/comparison/e2e.comparison.spec.ts | 2 +- src/pages/debug-app/e2e.debug-app.spec.ts | 2 +- src/pages/viewer-app/e2e.viewer-app.spec.ts | 2 +- src/redux/slices/arcgis-auth-slice.spec.ts | 28 +- src/redux/slices/arcgis-auth-slice.ts | 2 +- src/redux/slices/arcgis-content-slice.spec.ts | 162 +++++++++ src/redux/slices/arcgis-content-slice.ts | 129 +++++++ src/redux/store.ts | 2 + src/types.ts | 12 + .../{arcgis-auth.spec.ts => arcgis.spec.ts} | 36 +- src/utils/{arcgis-auth.ts => arcgis.ts} | 49 +++ src/utils/format/format-utils.spec.ts | 14 +- src/utils/format/format-utils.ts | 14 + src/utils/testing-utils/e2e-layers-panel.tsx | 12 +- 28 files changed, 1288 insertions(+), 289 deletions(-) create mode 100644 __mocks__/@esri/arcgis-rest-portal.ts create mode 100644 src/components/layers-panel/arcgis-control-panel.spec.tsx create mode 100644 src/components/layers-panel/arcgis-control-panel.tsx create mode 100644 src/components/layers-panel/arcgis-import-panel/arcgis-import-panel.spec.tsx create mode 100644 src/components/layers-panel/arcgis-import-panel/arcgis-import-panel.tsx create mode 100644 src/redux/slices/arcgis-content-slice.spec.ts create mode 100644 src/redux/slices/arcgis-content-slice.ts rename src/utils/{arcgis-auth.spec.ts => arcgis.spec.ts} (51%) rename src/utils/{arcgis-auth.ts => arcgis.ts} (67%) diff --git a/__mocks__/@esri/arcgis-rest-portal.ts b/__mocks__/@esri/arcgis-rest-portal.ts new file mode 100644 index 00000000..a278e2e4 --- /dev/null +++ b/__mocks__/@esri/arcgis-rest-portal.ts @@ -0,0 +1,28 @@ +const mockContent = { + items: [ + { + id: "new-york", + name: "NewYork.slpk", + url: "https://123.com", + created: 123456, + type: "Scene Service", + typeKeywords: "This is a Hosted Service", + title: "New York", + token: "token-https://123.com", + }, + { + id: "turanga-library", + name: "TurangaLibrary.slpk", + url: "https://456.com", + created: 123457, + type: "Scene Service", + typeKeywords: "This is a Hosted Service", + title: "Turanga Library", + token: "token-https://456.com", + }, + ], +}; + +export const getUserContent = async (authentication) => { + return mockContent; +}; diff --git a/__mocks__/@esri/arcgis-rest-request.ts b/__mocks__/@esri/arcgis-rest-request.ts index 391ef811..45ca3611 100644 --- a/__mocks__/@esri/arcgis-rest-request.ts +++ b/__mocks__/@esri/arcgis-rest-request.ts @@ -1,17 +1,22 @@ const mockEmailExpected = "usermail@gmail.com"; const mockSessionExpected = '{"usermail": "usermail"}'; +const mockTokenExpectedPrefix = "token-"; + +const session = { + usermail: mockEmailExpected, + serialize: () => { + return mockSessionExpected; + }, + getUser: async () => { + return { email: mockEmailExpected }; + }, + getToken: async (url: string) => { + return mockTokenExpectedPrefix + url; + }, +}; export class ArcGISIdentityManager { static beginOAuth2 = async () => { - const session = { - usermail: mockEmailExpected, - serialize: () => { - return mockSessionExpected; - }, - getUser: async () => { - return { email: mockEmailExpected }; - }, - }; return session; }; static completeOAuth2 = async () => { @@ -20,7 +25,7 @@ export class ArcGISIdentityManager { static destroy = async () => { return; }; - static deserialize = (session) => { - return { usermail: "usermail" }; + static deserialize = () => { + return session; }; } diff --git a/package.json b/package.json index bd93774c..92225483 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "dependencies": { "@esri/arcgis-rest-auth": "^3.7.0", "@esri/arcgis-rest-request": "^4.2.0", + "@esri/arcgis-rest-portal": "^4.4.0", "@fortawesome/fontawesome-svg-core": "^1.2.36", "@fortawesome/free-solid-svg-icons": "^5.15.4", "@fortawesome/react-fontawesome": "^0.1.17", diff --git a/src/components/common.tsx b/src/components/common.tsx index 5fce3c01..1c566be2 100644 --- a/src/components/common.tsx +++ b/src/components/common.tsx @@ -64,8 +64,10 @@ export const PanelContent = styled.div` export const PanelHorizontalLine = styled.div<{ top?: number; bottom?: number; + left?: number; + right?: number; }>` - margin: ${({ top = 24, bottom = 16 }) => `${top}px 16px ${bottom}px 16px`}; + margin: ${({ top = 24, bottom = 16, left = 16, right = 16 }) => `${top}px ${right}px ${bottom}px ${left}px`}; border: 1px solid ${({ theme }) => theme.colors.mainHiglightColorInverted}; border-radius: 1px; background: ${({ theme }) => theme.colors.mainHiglightColorInverted}; diff --git a/src/components/expand-icon/expand-icon.tsx b/src/components/expand-icon/expand-icon.tsx index 45ce62dd..e826462a 100644 --- a/src/components/expand-icon/expand-icon.tsx +++ b/src/components/expand-icon/expand-icon.tsx @@ -47,6 +47,17 @@ const IconButton = styled.div<{ } `; +const IconButtonContainer = styled.div<{ + width: number; + height: number; +}>` + display: flex; + justify-content: center; + align-items: center; + width: ${({ width }) => `${width}px`}} + height: ${({ height }) => `${height}px`}} +`; + type ExpandIconProps = { /** expanded/collapsed */ expandState: ExpandState; @@ -56,6 +67,10 @@ type ExpandIconProps = { fillExpanded?: string; /** icon color for collapsed state */ fillCollapsed?: string; + /** Width of the icon */ + width?: number; + /** Height of the icon */ + height?: number; /** click event handler */ onClick: (e: SyntheticEvent) => void; }; @@ -65,6 +80,8 @@ export const ExpandIcon = ({ fillExpanded, fillCollapsed, collapseDirection = CollapseDirection.top, + width = 8, + height = 12, }: ExpandIconProps) => { return ( - + + + ); }; diff --git a/src/components/layers-panel/arcgis-control-panel.spec.tsx b/src/components/layers-panel/arcgis-control-panel.spec.tsx new file mode 100644 index 00000000..1a7b1028 --- /dev/null +++ b/src/components/layers-panel/arcgis-control-panel.spec.tsx @@ -0,0 +1,150 @@ +import { renderWithThemeProviders } from "../../utils/testing-utils/render-with-theme"; +import { screen, within } from "@testing-library/react"; +import { setupStore } from "../../redux/store"; +import { ArcGisControlPanel } from "./arcgis-control-panel"; +import userEvent from "@testing-library/user-event"; +import { + arcGisLogin, + arcGisLogout, +} from "../../redux/slices/arcgis-auth-slice"; +import { + getAuthenticatedUser, + arcGisRequestLogin, + arcGisCompleteLogin, + arcGisRequestLogout, +} from "../../utils/arcgis"; + +jest.mock("../../utils/arcgis"); + +const getAuthenticatedUserMock = + getAuthenticatedUser as unknown as jest.Mocked; +const arcGisRequestLoginMock = + arcGisRequestLogin as unknown as jest.Mocked; +const arcGisCompleteLoginMock = + arcGisCompleteLogin as unknown as jest.Mocked; +const arcGisRequestLogoutMock = + arcGisRequestLogout as unknown as jest.Mocked; + +const EMAIL_EXPECTED = "usermail@gmail.com"; +let storageUserinfo = ""; + +const onArcGisImportMock = jest.fn(); + +const callRender = (renderFunc, props = {}, store = setupStore()) => { + return renderFunc( + , + store + ); +}; + +describe("Layers Control Panel - ArcGIS auth", () => { + beforeAll(() => { + arcGisRequestLoginMock.mockImplementation(async () => { + storageUserinfo = EMAIL_EXPECTED; + return storageUserinfo; + }); + arcGisCompleteLoginMock.mockImplementation(async () => { + return storageUserinfo; + }); + arcGisRequestLogoutMock.mockImplementation(async () => { + storageUserinfo = ""; + return storageUserinfo; + }); + getAuthenticatedUserMock.mockImplementation(() => { + return storageUserinfo; + }); + }); + + it("Should render ArcGIS Login button", async () => { + const store = setupStore(); + // Let's Log out... + await store.dispatch(arcGisLogout()); + const { container } = callRender( + renderWithThemeProviders, + undefined, + store + ); + expect(container).toBeInTheDocument(); + expect(arcGisRequestLogoutMock).toHaveBeenCalledTimes(1); + + // We are in the "Logged out" state, so the "Log in" button should be there. + const loginButton = await screen.findByText("Login to ArcGIS"); + expect(loginButton).toBeInTheDocument(); + loginButton && userEvent.click(loginButton); + expect(arcGisRequestLoginMock).toHaveBeenCalledTimes(1); + + const importButton = screen.queryByText("Import from ArcGIS"); + expect(importButton).not.toBeInTheDocument(); + }); + + it("Should render ArcGIS Import and Logout buttons", async () => { + const store = setupStore(); + // Let's Log in... + await store.dispatch(arcGisLogin()); + const { container } = callRender( + renderWithThemeProviders, + undefined, + store + ); + expect(container).toBeInTheDocument(); + expect(arcGisRequestLoginMock).toHaveBeenCalledTimes(1); + + // We are in the "Logged in" state, so the "Log in" button should NOT be there. + const importButton = await screen.findByText("Import from ArcGIS"); + expect(importButton).toBeInTheDocument(); + + const logoutUserInfo = await screen.findByText(EMAIL_EXPECTED); + expect(logoutUserInfo).toBeInTheDocument(); + + const loginButton = screen.queryByText("Login to ArcGIS"); + expect(loginButton).not.toBeInTheDocument(); + }); + + it("Should respond to action on the ArcGIS Login button", async () => { + const store = setupStore(); + // Let's Log out... + await store.dispatch(arcGisLogout()); + const { container } = callRender( + renderWithThemeProviders, + undefined, + store + ); + expect(container).toBeInTheDocument(); + + const loginButton = screen.getByText("Login to ArcGIS"); + loginButton && userEvent.click(loginButton); + expect(arcGisRequestLoginMock).toHaveBeenCalledTimes(1); + + const importButton = await screen.findByText("Import from ArcGIS"); + expect(importButton).toBeInTheDocument(); + + const loginButtonHidden = screen.queryByText("Login to ArcGIS"); + expect(loginButtonHidden).not.toBeInTheDocument(); + }); + + it("Should respond to action on ArcGIS Logout button", async () => { + const store = setupStore(); + // Let's Log in... + await store.dispatch(arcGisLogin()); + callRender( + renderWithThemeProviders, + undefined, + store + ); + + const logoutButton = await screen.findByTestId("userinfo-button"); + logoutButton && userEvent.click(logoutButton); + + const modalDialog = await screen.findByTestId("modal-dialog-content"); + expect(modalDialog).toContainHTML("Are you sure you want to log out?"); + + const cancelButton = within(modalDialog).getByText("Log out"); + cancelButton && userEvent.click(cancelButton); + + const modalDialogHidden = screen.queryByTestId("modal-dialog-content"); + expect(modalDialogHidden).not.toBeInTheDocument(); + + const loginButton = await screen.findByText("Login to ArcGIS"); + expect(loginButton).toBeInTheDocument(); + }); +}); diff --git a/src/components/layers-panel/arcgis-control-panel.tsx b/src/components/layers-panel/arcgis-control-panel.tsx new file mode 100644 index 00000000..ec4b07a1 --- /dev/null +++ b/src/components/layers-panel/arcgis-control-panel.tsx @@ -0,0 +1,133 @@ +import { useState } from "react"; +import styled from "styled-components"; +import ImportIcon from "../../../public/icons/import.svg"; +import { AcrGisUser } from "../arcgis-user/arcgis-user"; +import { + arcGisLogin, + arcGisLogout, + selectUser, +} from "../../redux/slices/arcgis-auth-slice"; +import { getArcGisContent } from "../../redux/slices/arcgis-content-slice"; +import { ModalDialog } from "../modal-dialog/modal-dialog"; +import EsriImage from "../../../public/images/esri.svg"; +import { useAppDispatch, useAppSelector } from "../../redux/hooks"; +import { ActionIconButton } from "../action-icon-button/action-icon-button"; +import { ButtonSize } from "../../types"; +import { ArcGisImportPanel } from "./arcgis-import-panel/arcgis-import-panel"; + +type ArcGisControlPanelProps = { + onArcGisImportClick: (layer: { + name: string; + url: string; + token?: string; + }) => void; +}; + +const ActionButtonsContainer = styled.div` + display: flex; + flex-direction: column; + width: 100%; + row-gap: 8px; + margin-top: 8px; +`; + +const ActionIconButtonContainer = styled.div` + display: flex; + flex-direction: row; + justify-content: start; + align-items: center; +`; + +const EsriStyledImage = styled(EsriImage)` + margin-left: 16px; + fill: ${({ theme }) => theme.colors.esriImageColor}; +`; + +const TextInfo = styled.div` + font-style: normal; + font-weight: 500; + font-size: 16px; + line-height: 19px; +`; + +const TextUser = styled.div` + font-style: normal; + font-weight: 700; + font-size: 16px; + line-height: 19px; +`; + +export const ArcGisControlPanel = ({ + onArcGisImportClick, +}: ArcGisControlPanelProps) => { + const dispatch = useAppDispatch(); + + const username = useAppSelector(selectUser); + const isLoggedIn = !!username; + + const [showLogoutWarning, setShowLogoutWarning] = useState(false); + const [showArcGisImportPanel, setShowArcGisImportPanel] = useState(false); + + const onArcGisActionClick = () => { + if (isLoggedIn) { + dispatch(getArcGisContent()); + setShowArcGisImportPanel(true); + } else { + dispatch(arcGisLogin()); + } + }; + const onArcGisLogoutClick = () => { + setShowLogoutWarning(true); + }; + + return ( + <> + + + + {isLoggedIn ? "Import from ArcGIS" : "Login to ArcGIS"} + + + + + {isLoggedIn && ( + {username} + )} + + + {showArcGisImportPanel && ( + { + onArcGisImportClick(item); + setShowArcGisImportPanel(false); + }} + onCancel={() => setShowArcGisImportPanel(false)} + /> + )} + + {showLogoutWarning && ( + { + dispatch(arcGisLogout()); + setShowLogoutWarning(false); + }} + onCancel={() => { + setShowLogoutWarning(false); + }} + > + Are you sure you want to log out? + You are logged in as + {username} + + )} + + ); +}; diff --git a/src/components/layers-panel/arcgis-import-panel/arcgis-import-panel.spec.tsx b/src/components/layers-panel/arcgis-import-panel/arcgis-import-panel.spec.tsx new file mode 100644 index 00000000..a4b25961 --- /dev/null +++ b/src/components/layers-panel/arcgis-import-panel/arcgis-import-panel.spec.tsx @@ -0,0 +1,146 @@ +import { screen } from "@testing-library/react"; +import userEvent from "@testing-library/user-event"; +import { renderWithThemeProviders } from "../../../utils/testing-utils/render-with-theme"; +import { ArcGisImportPanel } from "./arcgis-import-panel"; +import { setupStore } from "../../../redux/store"; +import { + selectArcGisContent, + getArcGisContent, +} from "../../../redux/slices/arcgis-content-slice"; +import { getArcGisUserContent } from "../../../utils/arcgis"; + +jest.mock("../../../utils/arcgis"); + +const getArcGisUserContentMock = + getArcGisUserContent as unknown as jest.Mocked; + +const onImportMock = jest.fn(); +const onCancelMock = jest.fn(); + +const CONTENT_EXPECTED = [ + { + id: "123", + name: "123.slpk", + url: "https://123.com", + created: 123453, + title: "City-123", + token: "token-https://123.com", + }, + { + id: "789", + name: "789.slpk", + url: "https://789.com", + created: 123457, + title: "City-789", + token: "token-https://789.com", + }, + { + id: "456", + name: "456.slpk", + url: "https://456.com", + created: 123454, + title: "City-456", + token: "token-https://456.com", + }, +]; + +const callRender = (renderFunc, props = {}, store = setupStore()) => { + return renderFunc( + , + store + ); +}; + +describe("Import panel", () => { + beforeAll(() => { + getArcGisUserContentMock.mockImplementation(async () => { + return CONTENT_EXPECTED; + }); + }); + + it("Should render import panel", async () => { + const store = setupStore(); + await store.dispatch(getArcGisContent()); + const { container } = callRender( + renderWithThemeProviders, + undefined, + store + ); + + expect(container).toBeInTheDocument(); + expect(screen.getByText("Select map to import")).toBeInTheDocument(); + expect(screen.getByText("Import Selected")).toBeInTheDocument(); + expect(screen.getByText("Title")).toBeInTheDocument(); + expect(screen.getByText("Date")).toBeInTheDocument(); + }); + + it("Should close the dialog", async () => { + const store = setupStore(); + callRender(renderWithThemeProviders, undefined, store); + + const cross = document.querySelector("svg"); + cross && userEvent.click(cross); + expect(onCancelMock).toHaveBeenCalledTimes(1); + }); + + it("Should import an item", async () => { + const store = setupStore(); + callRender(renderWithThemeProviders, undefined, store); + await store.dispatch(getArcGisContent()); + + const importSelected = screen.getByText("Import Selected"); + + // No item is selected yet. + importSelected && userEvent.click(importSelected); + expect(onImportMock).toHaveBeenCalledTimes(0); + + // Select an item to import + const row = screen.getByText("City-123"); + row && userEvent.click(row); + + importSelected && userEvent.click(importSelected); + expect(onImportMock).toHaveBeenCalledTimes(1); + }); + + it("Should change the sorting order", async () => { + const store = setupStore(); + callRender(renderWithThemeProviders, undefined, store); + await store.dispatch(getArcGisContent()); + + let state = store.getState(); + let cont = selectArcGisContent(state); + + const title = screen.getByText("Title"); + + title && userEvent.click(title); + state = store.getState(); + cont = selectArcGisContent(state); + expect(cont[0]["id"]).toBe("123"); + + title && userEvent.click(title); + state = store.getState(); + cont = selectArcGisContent(state); + expect(cont[0]["id"]).toBe("789"); + + const date = screen.getByText("Date"); + + date && userEvent.click(date); + state = store.getState(); + cont = selectArcGisContent(state); + expect(cont[0]["id"]).toBe("789"); + + date && userEvent.click(date); + state = store.getState(); + cont = selectArcGisContent(state); + expect(cont[0]["id"]).toBe("123"); + + date && userEvent.click(date); + state = store.getState(); + cont = selectArcGisContent(state); + expect(cont[0]["id"]).toBe("789"); + }); +}); diff --git a/src/components/layers-panel/arcgis-import-panel/arcgis-import-panel.tsx b/src/components/layers-panel/arcgis-import-panel/arcgis-import-panel.tsx new file mode 100644 index 00000000..4af11e31 --- /dev/null +++ b/src/components/layers-panel/arcgis-import-panel/arcgis-import-panel.tsx @@ -0,0 +1,320 @@ +import styled, { css, useTheme } from "styled-components"; +import { RadioButton } from "../../radio-button/radio-button"; +import { useEffect } from "react"; +import { useAppDispatch, useAppSelector } from "../../../redux/hooks"; +import { ModalDialog } from "../../modal-dialog/modal-dialog"; +import { + selectArcGisContent, + selectArcGisContentSelected, + selectSortAscending, + selectSortColumn, + selectStatus, + setSortAscending, + setSortColumn, + setArcGisContentSelected, + resetArcGisContentSelected, +} from "../../../redux/slices/arcgis-content-slice"; +import { + IArcGisContent, + ArcGisContentColumnName, + ExpandState, + CollapseDirection, +} from "../../../types"; +import { LoadingSpinner } from "../../loading-spinner/loading-spinner"; +import { ExpandIcon } from "../../expand-icon/expand-icon"; + +const SpinnerContainer = styled.div<{ visible: boolean }>` + position: absolute; + left: calc(50% - 22px); + top: calc(50% - 22px); + opacity: ${({ visible }) => (visible ? 1 : 0)}; +`; + +const Table = styled.table` + width: 584px; + border-collapse: collapse; +`; + +const TableHeader = styled.thead` + font-style: normal; + font-weight: 500; + font-size: 16px; + line-height: 19px; + color: ${({ theme }) => theme.colors.secondaryFontColor}; + overflow: hidden; +`; + +const TableHeaderCell = styled.th<{ width: number }>` + width: ${({ width }) => `${width}px`}; + padding: 0; +`; + +const TableRowCell = styled.td<{ + width: number; + fontWeight?: number; +}>` + width: ${({ width }) => `${width}px`}; + padding: 0; + ${({ fontWeight }) => + fontWeight !== undefined && + css` + font-weight: ${fontWeight}; + `} +`; + +const CellDiv = styled.div` + display: flex; + flex-direction: column; + justify-content: center; + align-items: start; + margin: 8px 0 8px 0; + height: 44px; +`; + +const TableContent = styled.tbody` + font-style: normal; + font-weight: 500; + font-size: 16px; + line-height: 19px; + overflow: auto; + max-height: 300px; +`; + +const TableRow = styled.tr<{ checked: boolean }>` + background: transparent; + cursor: pointer; + border: 0; + border-style: solid; + border-bottom: 1px solid + ${({ theme }) => `${theme.colors.mainHiglightColorInverted}1f`}; + border-radius: 1px; + + ${({ checked }) => + checked && + css` + > * > :first-child { + background: ${({ theme }) => theme.colors.mainHiglightColor}; + } + > :first-child > :first-child { + border-top-left-radius: 8px; + border-bottom-left-radius: 8px; + } + > :last-child > :first-child { + border-top-right-radius: 8px; + border-bottom-right-radius: 8px; + } + + box-shadow: 0px 17px 80px rgba(0, 0, 0, 0.1); + `} + &:hover { + > * > :first-child { + background: ${({ theme }) => theme.colors.mainDimColor}; + } + > :first-child > :first-child { + border-top-left-radius: 8px; + border-bottom-left-radius: 8px; + } + > :last-child > :first-child { + border-top-right-radius: 8px; + border-bottom-right-radius: 8px; + } + + box-shadow: 0px 17px 80px rgba(0, 0, 0, 0.1); + } +`; + +const Radio = styled.div` + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + width: 44px; + height: 44px; +`; + +const TitleCellContainer = styled.div` + display: flex; + flex-direction: row; + justify-content: start; + align-items: center; + gap: 4px; + cursor: pointer; +`; + +const IconContainer = styled.div<{ enabled: boolean }>` + display: flex; + justify-content: center; + align-items: center; + margin-top: 2px; + width: 16px; + height: 16px; + fill: ${({ theme }) => theme.colors.buttonDimIconColor}; + visibility: ${({ enabled }) => (enabled ? "visible" : "hidden")}; +`; + +type Column = { + id: string; + width: number; + fontWeight?: number; + dataColumnName?: ArcGisContentColumnName; + sortDataColumnName?: ArcGisContentColumnName; + columnName?: string; +}; + +const columns: Column[] = [ + { + id: "radio", + width: 44, + }, + { + id: "title", + width: 343, + fontWeight: 700, + dataColumnName: "title", + columnName: "Title", + }, + { + id: "created", + width: 149, + dataColumnName: "createdFormatted", + sortDataColumnName: "created", + columnName: "Date", + }, +]; + +type InsertLayerProps = { + onImport: (object: { name: string; url: string; token?: string }) => void; + onCancel: () => void; +}; + +export const ArcGisImportPanel = ({ onImport, onCancel }: InsertLayerProps) => { + const dispatch = useAppDispatch(); + const arcGisContentArray = useAppSelector(selectArcGisContent); + const arcGisContentSelected = useAppSelector(selectArcGisContentSelected); + const sortAscending = useAppSelector(selectSortAscending); + const sortColumn = useAppSelector(selectSortColumn); + const loadingStatus = useAppSelector(selectStatus); + + const isLoading = loadingStatus === "loading"; + + useEffect(() => { + dispatch(resetArcGisContentSelected()); + }, []); + + const handleImport = () => { + const arcGisItem = arcGisContentArray.find( + (item) => item.id === arcGisContentSelected + ); + if (arcGisItem) { + onImport(arcGisItem); + } + }; + + const onSort = (dataColumnName: ArcGisContentColumnName) => { + if (sortColumn === dataColumnName) { + dispatch(setSortAscending(!sortAscending)); + } else { + dispatch(setSortColumn(dataColumnName)); + } + }; + + const renderHeaderCell = (column: Column): JSX.Element => { + const sortDataColumnName = + column.sortDataColumnName || column.dataColumnName; + return ( + + {typeof sortDataColumnName !== "undefined" && ( + onSort(sortDataColumnName)}> + {column.columnName || ""} + + onSort(sortDataColumnName)} + fillExpanded={theme.colors.buttonDimIconColor} + width={6} + /> + + + )} + + ); + }; + + const renderRowCell = ( + column: Column, + contentItem: IArcGisContent, + isRowSelected: boolean + ): JSX.Element => { + const dataColumnName = column.dataColumnName; + return ( + + + {dataColumnName ? ( + contentItem[dataColumnName] + ) : ( + + { + dispatch(setArcGisContentSelected(contentItem.id)); + }} + /> + + )} + + + ); + }; + + const theme = useTheme(); + return ( + + + + + + + + {columns.map((column: Column) => renderHeaderCell(column))} + + + {arcGisContentArray.map((contentItem) => { + const isRowSelected = arcGisContentSelected === contentItem.id; + + return ( + { + dispatch(setArcGisContentSelected(contentItem.id)); + }} + > + {columns.map((column: Column) => + renderRowCell(column, contentItem, isRowSelected) + )} + + ); + })} + +
+
+ ); +}; diff --git a/src/components/layers-panel/layers-control-panel.spec.tsx b/src/components/layers-panel/layers-control-panel.spec.tsx index eb0dcb1b..a1b1eeb4 100644 --- a/src/components/layers-panel/layers-control-panel.spec.tsx +++ b/src/components/layers-panel/layers-control-panel.spec.tsx @@ -1,11 +1,6 @@ -import { act, screen, within } from "@testing-library/react"; +import { act, screen } from "@testing-library/react"; import { renderWithThemeProviders } from "../../utils/testing-utils/render-with-theme"; import { LayersControlPanel } from "./layers-control-panel"; -import userEvent from "@testing-library/user-event"; -import { - arcGisLogin, - arcGisLogout, -} from "../../redux/slices/arcgis-auth-slice"; // Mocked components import { ActionIconButton } from "../action-icon-button/action-icon-button"; @@ -14,18 +9,10 @@ import { LayerOptionsMenu } from "./layer-options-menu/layer-options-menu"; import { ListItem } from "./list-item/list-item"; import { setupStore } from "../../redux/store"; -import { - getAuthenticatedUser, - arcGisRequestLogin, - arcGisCompleteLogin, - arcGisRequestLogout, -} from "../../utils/arcgis-auth"; - jest.mock("./list-item/list-item"); jest.mock("../action-icon-button/action-icon-button"); jest.mock("./delete-confirmation"); jest.mock("./layer-options-menu/layer-options-menu"); -jest.mock("../../utils/arcgis-auth"); const ListItemMock = ListItem as unknown as jest.Mocked; const PlusButtonMock = ActionIconButton as unknown as jest.Mocked; @@ -33,18 +20,6 @@ const DeleteConfirmationMock = DeleteConfirmation as unknown as jest.Mocked; const LayerOptionsMenuMock = LayerOptionsMenu as unknown as jest.Mocked; -const getAuthenticatedUserMock = - getAuthenticatedUser as unknown as jest.Mocked; -const arcGisRequestLoginMock = - arcGisRequestLogin as unknown as jest.Mocked; -const arcGisCompleteLoginMock = - arcGisCompleteLogin as unknown as jest.Mocked; -const arcGisRequestLogoutMock = - arcGisRequestLogout as unknown as jest.Mocked; - -const mockEmailExpected = "usermail@gmail.com"; -let mockStorageUserinfo = ""; - const onInsertLayerMock = jest.fn(); const onInsertSceneMock = jest.fn(); const onDeleteLayerMock = jest.fn(); @@ -84,118 +59,6 @@ beforeAll(() => { LayerOptionsMenuMock.mockImplementation(() =>
Layers Options
); }); -describe("Layers Control Panel - ArcGIS auth", () => { - beforeAll(() => { - arcGisRequestLoginMock.mockImplementation(async () => { - mockStorageUserinfo = mockEmailExpected; - return mockStorageUserinfo; - }); - arcGisCompleteLoginMock.mockImplementation(async () => { - return mockStorageUserinfo; - }); - arcGisRequestLogoutMock.mockImplementation(async () => { - mockStorageUserinfo = ""; - return mockStorageUserinfo; - }); - getAuthenticatedUserMock.mockImplementation(() => { - return mockStorageUserinfo; - }); - }); - - it("Should render ArcGIS Login button", async () => { - const store = setupStore(); - // Let's Log out... - await store.dispatch(arcGisLogout()); - const { container } = callRender( - renderWithThemeProviders, - undefined, - store - ); - expect(container).toBeInTheDocument(); - expect(arcGisRequestLogoutMock).toHaveBeenCalledTimes(1); - - // We are in the "Logged out" state, so the "Log in" button should be there. - const loginButton = await screen.findByText("Login to ArcGIS"); - expect(loginButton).toBeInTheDocument(); - loginButton && userEvent.click(loginButton); - expect(arcGisRequestLoginMock).toHaveBeenCalledTimes(1); - - const importButton = screen.queryByText("Import from ArcGIS"); - expect(importButton).not.toBeInTheDocument(); - }); - - it("Should render ArcGIS Import and Logout buttons", async () => { - const store = setupStore(); - // Let's Log in... - await store.dispatch(arcGisLogin()); - const { container } = callRender( - renderWithThemeProviders, - undefined, - store - ); - expect(container).toBeInTheDocument(); - expect(arcGisRequestLoginMock).toHaveBeenCalledTimes(1); - - // We are in the "Logged in" state, so the "Log in" button should NOT be there. - const importButton = await screen.findByText("Import from ArcGIS"); - expect(importButton).toBeInTheDocument(); - - const logoutUserInfo = await screen.findByText(mockEmailExpected); - expect(logoutUserInfo).toBeInTheDocument(); - - const loginButton = screen.queryByText("Login to ArcGIS"); - expect(loginButton).not.toBeInTheDocument(); - }); - - it("Should respond to action on the ArcGIS Login button", async () => { - const store = setupStore(); - // Let's Log out... - await store.dispatch(arcGisLogout()); - const { container } = callRender( - renderWithThemeProviders, - undefined, - store - ); - expect(container).toBeInTheDocument(); - - const loginButton = screen.getByText("Login to ArcGIS"); - loginButton && userEvent.click(loginButton); - expect(arcGisRequestLoginMock).toHaveBeenCalledTimes(1); - - const importButton = await screen.findByText("Import from ArcGIS"); - expect(importButton).toBeInTheDocument(); - - const loginButtonHidden = screen.queryByText("Login to ArcGIS"); - expect(loginButtonHidden).not.toBeInTheDocument(); - }); - - it("Should respond to action on ArcGIS Logout button", async () => { - const store = setupStore(); - // Let's Log in... - await store.dispatch(arcGisLogin()); - const { container } = callRender( - renderWithThemeProviders, - undefined, - store - ); - - const logoutButton = await screen.findByTestId("userinfo-button"); - logoutButton && userEvent.click(logoutButton); - - const modalDialog = await screen.findByTestId("modal-dialog-content"); - expect(modalDialog).toContainHTML("Are you sure you want to log out?"); - - const cancelButton = within(modalDialog).getByText("Log out"); - cancelButton && userEvent.click(cancelButton); - - const modalDialogHidden = screen.queryByTestId("modal-dialog-content"); - expect(modalDialogHidden).not.toBeInTheDocument(); - - const loginButton = await screen.findByText("Login to ArcGIS"); - expect(loginButton).toBeInTheDocument(); - }); -}); - describe("Layers Control Panel", () => { it("Should render LayersControlPanel without layers", () => { const store = setupStore(); diff --git a/src/components/layers-panel/layers-control-panel.tsx b/src/components/layers-panel/layers-control-panel.tsx index 1da26ab2..4caf5dfb 100644 --- a/src/components/layers-panel/layers-control-panel.tsx +++ b/src/components/layers-panel/layers-control-panel.tsx @@ -8,22 +8,11 @@ import { } from "../../types"; import { ListItem } from "./list-item/list-item"; import PlusIcon from "../../../public/icons/plus.svg"; -import ImportIcon from "../../../public/icons/import.svg"; -import EsriImage from "../../../public/images/esri.svg"; import { ActionIconButton } from "../action-icon-button/action-icon-button"; -import { AcrGisUser } from "../arcgis-user/arcgis-user"; import { DeleteConfirmation } from "./delete-confirmation"; import { LayerOptionsMenu } from "./layer-options-menu/layer-options-menu"; import { handleSelectAllLeafsInGroup } from "../../utils/layer-utils"; import { ButtonSize } from "../../types"; -import { PanelHorizontalLine } from "../common"; -import { - arcGisLogin, - arcGisLogout, - selectUser, -} from "../../redux/slices/arcgis-auth-slice"; -import { useAppDispatch, useAppSelector } from "../../redux/hooks"; -import { ModalDialog } from "../modal-dialog/modal-dialog"; type LayersControlPanelProps = { layers: LayerExample[]; @@ -56,6 +45,7 @@ const InsertButtons = styled.div` flex-direction: column; row-gap: 8px; margin-top: 8px; + margin-bottom: 8px; `; const ChildrenContainer = styled.div` @@ -66,32 +56,6 @@ const ChildrenContainer = styled.div` padding-left: 12px; `; -const ActionIconButtonContainer = styled.div` - display: flex; - flex-direction: row; - justify-content: start; - align-items: center; -`; - -const EsriStyledImage = styled(EsriImage)` - margin-left: 16px; - fill: ${({ theme }) => theme.colors.esriImageColor}; -`; - -const TextInfo = styled.div` - font-style: normal; - font-weight: 500; - font-size: 16px; - line-height: 19px; -`; - -const TextUser = styled.div` - font-style: normal; - font-weight: 700; - font-size: 16px; - line-height: 19px; -`; - export const LayersControlPanel = ({ layers, type, @@ -104,23 +68,10 @@ export const LayersControlPanel = ({ onPointToLayer, deleteLayer, }: LayersControlPanelProps) => { - const dispatch = useAppDispatch(); - - const username = useAppSelector(selectUser); - const isLoggedIn = !!username; - - const [showLogoutWarning, setShowLogoutWarning] = useState(false); const [settingsLayerId, setSettingsLayerId] = useState(""); const [showLayerSettings, setShowLayerSettings] = useState(false); const [layerToDeleteId, setLayerToDeleteId] = useState(""); - const onArcGisActionClick = () => { - !isLoggedIn && dispatch(arcGisLogin()); - }; - const onArcGisLogoutClick = () => { - setShowLogoutWarning(true); - }; - const isListItemSelected = ( layer: LayerExample, parentLayer?: LayerExample @@ -248,43 +199,6 @@ export const LayersControlPanel = ({ > Insert scene
- - - - - - {!isLoggedIn && "Login to ArcGIS"} - {isLoggedIn && "Import from ArcGIS"} - - - - - {isLoggedIn && ( - {username} - )} - - {showLogoutWarning && ( - { - dispatch(arcGisLogout()); - setShowLogoutWarning(false); - }} - onCancel={() => { - setShowLogoutWarning(false); - }} - > - Are you sure you want to log out? - You are logged in as - {username} - - )} ); diff --git a/src/components/layers-panel/layers-panel.tsx b/src/components/layers-panel/layers-panel.tsx index bec8fa9d..17487a49 100644 --- a/src/components/layers-panel/layers-panel.tsx +++ b/src/components/layers-panel/layers-panel.tsx @@ -19,6 +19,7 @@ import { import { CloseButton } from "../close-button/close-button"; import { InsertPanel } from "./insert-panel/insert-panel"; import { LayersControlPanel } from "./layers-control-panel"; +import { ArcGisControlPanel } from "./arcgis-control-panel"; import { MapOptionPanel } from "./map-options-panel"; import { PanelContainer, @@ -207,7 +208,6 @@ export const LayersPanel = ({ ); if (existedLayer) { - setShowLayerInsertPanel(false); setShowExistedError(true); return; } @@ -221,7 +221,6 @@ export const LayersPanel = ({ }; onLayerInsert(newLayer); - setShowLayerInsertPanel(false); }; const prepareLayerExamples = (layers: OperationalLayer[]): LayerExample[] => { @@ -381,6 +380,13 @@ export const LayersPanel = ({ /> )} + + + + + + + {showExistedError && ( setWarningNode(element)}> handleInsertLayer(layer)} + onInsert={(layer) => { + handleInsertLayer(layer); + setShowLayerInsertPanel(false); + }} onCancel={() => setShowLayerInsertPanel(false)} /> diff --git a/src/components/modal-dialog/modal-dialog.tsx b/src/components/modal-dialog/modal-dialog.tsx index e2248bba..c25df8d8 100644 --- a/src/components/modal-dialog/modal-dialog.tsx +++ b/src/components/modal-dialog/modal-dialog.tsx @@ -50,6 +50,7 @@ const IconContainer = styled.div` right: 14px; width: 44px; height: 44px; + cursor: pointer; `; const ContentContainer = styled.div` @@ -70,10 +71,14 @@ const Title = styled.div` line-height: 45px; `; -const ButtonsContainer = styled.div` +type ButtonsContainerProps = { + justify: string; +}; + +const ButtonsContainer = styled.div` display: flex; flex-direction: row; - justify-content: center; + justify-content: ${(props) => props.justify}; margin: 32px; column-gap: 18px; { @@ -93,7 +98,6 @@ type LogoutPanelProps = { }; const CloseCrossButton = styled(CloseIcon)` - cursor: pointer; &:hover { fill: ${({ theme }) => theme.colors.mainDimColorInverted}; } @@ -102,8 +106,8 @@ const CloseCrossButton = styled(CloseIcon)` export const ModalDialog = ({ title, children, - cancelButtonText = "Cancel", - okButtonText = "Ok", + cancelButtonText, + okButtonText, onCancel, onConfirm, }: LogoutPanelProps) => { @@ -114,23 +118,22 @@ export const ModalDialog = ({ - - + + {title} {children} - - - {cancelButtonText} - + + {cancelButtonText && ( + + {cancelButtonText} + + )} {okButtonText} diff --git a/src/pages/auth/auth.tsx b/src/pages/auth/auth.tsx index 2bb257d7..1c6617a8 100644 --- a/src/pages/auth/auth.tsx +++ b/src/pages/auth/auth.tsx @@ -6,7 +6,7 @@ import { useAppLayout, } from "../../utils/hooks/layout"; -import { arcGisCompleteLogin } from "../../utils/arcgis-auth"; +import { arcGisCompleteLogin } from "../../utils/arcgis"; export type LayoutProps = { layout: string; diff --git a/src/pages/comparison/e2e.comparison.spec.ts b/src/pages/comparison/e2e.comparison.spec.ts index dc16bde1..89adc288 100644 --- a/src/pages/comparison/e2e.comparison.spec.ts +++ b/src/pages/comparison/e2e.comparison.spec.ts @@ -282,7 +282,7 @@ describe("Compare - Map Control Panel", () => { // Dropdown button const dropdownButton = await page.$eval( - `${panelId} > :first-child > svg`, + `${panelId} > :first-child > :first-child > svg`, (node) => node.innerHTML ); expect(dropdownButton).toBe(chevronSvgHtml); diff --git a/src/pages/debug-app/e2e.debug-app.spec.ts b/src/pages/debug-app/e2e.debug-app.spec.ts index 22f916bd..a1dedc16 100644 --- a/src/pages/debug-app/e2e.debug-app.spec.ts +++ b/src/pages/debug-app/e2e.debug-app.spec.ts @@ -333,7 +333,7 @@ describe("Debug - Map Control Panel", () => { // Dropdown button const dropdownButton = await page.$eval( - `${panelId} > :first-child > svg`, + `${panelId} > :first-child > :first-child > svg`, (node) => node.innerHTML ); expect(dropdownButton).toBe(chevronSvgHtml); diff --git a/src/pages/viewer-app/e2e.viewer-app.spec.ts b/src/pages/viewer-app/e2e.viewer-app.spec.ts index f34bf9a0..78537766 100644 --- a/src/pages/viewer-app/e2e.viewer-app.spec.ts +++ b/src/pages/viewer-app/e2e.viewer-app.spec.ts @@ -163,7 +163,7 @@ describe("Viewer - Map Control Panel", () => { // Dropdown button const dropdownButton = await page.$eval( - `${panelId} > :first-child > svg`, + `${panelId} > :first-child > :first-child > svg`, (node) => node.innerHTML ); expect(dropdownButton).toBe(chevronSvgHtml); diff --git a/src/redux/slices/arcgis-auth-slice.spec.ts b/src/redux/slices/arcgis-auth-slice.spec.ts index 8023ff9a..62b42483 100644 --- a/src/redux/slices/arcgis-auth-slice.spec.ts +++ b/src/redux/slices/arcgis-auth-slice.spec.ts @@ -10,9 +10,9 @@ import { arcGisRequestLogin, arcGisCompleteLogin, arcGisRequestLogout, -} from "../../utils/arcgis-auth"; +} from "../../utils/arcgis"; -jest.mock("../../utils/arcgis-auth"); +jest.mock("../../utils/arcgis"); const getAuthenticatedUserMock = getAuthenticatedUser as unknown as jest.Mocked; @@ -23,48 +23,48 @@ const arcGisCompleteLoginMock = const arcGisRequestLogoutMock = arcGisRequestLogout as unknown as jest.Mocked; -const mockEmailExpected = "usermail@gmail.com"; -let mockStorageUserinfo = mockEmailExpected; +const EMAIL_EXPECTED = "usermail@gmail.com"; +let storageUserinfo = EMAIL_EXPECTED; describe("slice: arcgis-auth", () => { beforeAll(() => { arcGisRequestLoginMock.mockImplementation(async () => { - mockStorageUserinfo = mockEmailExpected; - return mockStorageUserinfo; + storageUserinfo = EMAIL_EXPECTED; + return storageUserinfo; }); arcGisCompleteLoginMock.mockImplementation(async () => { - return mockStorageUserinfo; + return storageUserinfo; }); arcGisRequestLogoutMock.mockImplementation(async () => { - mockStorageUserinfo = ""; - return mockStorageUserinfo; + storageUserinfo = ""; + return storageUserinfo; }); getAuthenticatedUserMock.mockImplementation(() => { - return mockStorageUserinfo; + return storageUserinfo; }); }); beforeEach(() => { - mockStorageUserinfo = mockEmailExpected; + storageUserinfo = EMAIL_EXPECTED; }); it("Reducer should return the initial state", () => { expect(reducer(undefined, { type: undefined })).toEqual({ - user: mockEmailExpected, + user: EMAIL_EXPECTED, }); }); it("Selector should return the initial state", () => { const store = setupStore(); const state = store.getState(); - expect(selectUser(state)).toEqual(mockEmailExpected); + expect(selectUser(state)).toEqual(EMAIL_EXPECTED); }); it("Selector should return the updated value after Login", async () => { const store = setupStore(); await store.dispatch(arcGisLogin()); const state = store.getState(); - expect(selectUser(state)).toEqual(mockEmailExpected); + expect(selectUser(state)).toEqual(EMAIL_EXPECTED); }); it("Selector should return the updated value after Logout", async () => { diff --git a/src/redux/slices/arcgis-auth-slice.ts b/src/redux/slices/arcgis-auth-slice.ts index 7e7f6ea6..14e09917 100644 --- a/src/redux/slices/arcgis-auth-slice.ts +++ b/src/redux/slices/arcgis-auth-slice.ts @@ -4,7 +4,7 @@ import { getAuthenticatedUser, arcGisRequestLogin, arcGisRequestLogout, -} from "../../utils/arcgis-auth"; +} from "../../utils/arcgis"; // Define a type for the slice state export interface ArcGisAuthState { diff --git a/src/redux/slices/arcgis-content-slice.spec.ts b/src/redux/slices/arcgis-content-slice.spec.ts new file mode 100644 index 00000000..3b66de69 --- /dev/null +++ b/src/redux/slices/arcgis-content-slice.spec.ts @@ -0,0 +1,162 @@ +import { setupStore } from "../store"; +import reducer, { + selectArcGisContent, + selectArcGisContentSelected, + selectSortAscending, + selectSortColumn, + selectStatus, + setSortAscending, + setSortColumn, + setArcGisContentSelected, + resetArcGisContentSelected, + getArcGisContent, +} from "./arcgis-content-slice"; + +import { getArcGisUserContent } from "../../utils/arcgis"; + +jest.mock("../../utils/arcgis"); +const getArcGisUserContentMock = + getArcGisUserContent as unknown as jest.Mocked; + +const CONTENT_EXPECTED = [ + { + id: "123", + name: "123.slpk", + url: "https://123.com", + created: 123453, + title: "City-123", + token: "token-https://123.com", + }, + { + id: "789", + name: "789.slpk", + url: "https://789.com", + created: 123457, + title: "City-789", + token: "token-https://789.com", + }, + { + id: "456", + name: "456.slpk", + url: "https://456.com", + created: 123454, + title: "City-456", + token: "token-https://456.com", + }, +]; + +const CONTENT_SORTED_EXPECTED = [ + { + id: "123", + name: "123.slpk", + url: "https://123.com", + created: 123453, + title: "City-123", + token: "token-https://123.com", + }, + { + id: "456", + name: "456.slpk", + url: "https://456.com", + created: 123454, + title: "City-456", + token: "token-https://456.com", + }, + { + id: "789", + name: "789.slpk", + url: "https://789.com", + created: 123457, + title: "City-789", + token: "token-https://789.com", + }, +]; + +const INIT_VALUE_EXPECTED = { + arcGisContent: [], + arcGisContentSelected: "", + sortColumn: null, + sortAscending: true, + status: "idle", +}; + +function sleep(ms) { + return new Promise((resolve) => setTimeout(resolve, ms)); +} + +describe("slice: arcgis-content", () => { + beforeAll(() => { + getArcGisUserContentMock.mockImplementation(async () => { + sleep(10); + return CONTENT_EXPECTED; + }); + }); + + it("Reducer should return the initial state", () => { + expect(reducer(undefined, { type: undefined })).toEqual( + INIT_VALUE_EXPECTED + ); + }); + + it("Selector should return the initial state", () => { + const store = setupStore(); + const state = store.getState(); + expect(selectStatus(state)).toEqual("idle"); + }); + + it("Selector should return 'loading' status", () => { + const store = setupStore(); + /* No await! */ store.dispatch(getArcGisContent()); + const state = store.getState(); + expect(selectStatus(state)).toEqual("loading"); + }); + + it("Selector should return empty string if no content added", () => { + const store = setupStore(); + store.dispatch(setArcGisContentSelected("123")); + const state = store.getState(); + expect(selectArcGisContentSelected(state)).toEqual(""); + }); + + it("Selector should return id of selected item", async () => { + const store = setupStore(); + await store.dispatch(getArcGisContent()); + store.dispatch(setArcGisContentSelected("456")); + const state = store.getState(); + expect(selectArcGisContentSelected(state)).toEqual("456"); + }); + + it("Selector should return empty string if nothing is selected", async () => { + const store = setupStore(); + await store.dispatch(getArcGisContent()); + store.dispatch(setArcGisContentSelected("123")); + store.dispatch(resetArcGisContentSelected()); + const state = store.getState(); + expect(selectArcGisContentSelected(state)).toEqual(""); + }); + + it("Selector should return content received (unsorted)", async () => { + const store = setupStore(); + await store.dispatch(getArcGisContent()); + const state = store.getState(); + expect(selectArcGisContent(state)).toEqual(CONTENT_EXPECTED); + expect(selectStatus(state)).toEqual("idle"); + }); + + it("Selector should return content received (sorted)", async () => { + const store = setupStore(); + store.dispatch(setSortColumn("title")); + store.dispatch(setSortAscending(true)); + + await store.dispatch(getArcGisContent()); + let state = store.getState(); + expect(selectSortColumn(state)).toEqual("title"); + expect(selectSortAscending(state)).toEqual(true); + expect(selectArcGisContent(state)).toEqual(CONTENT_SORTED_EXPECTED); + + store.dispatch(setSortColumn("created")); + store.dispatch(setSortAscending(true)); + state = store.getState(); + expect(selectArcGisContent(state)).toEqual(CONTENT_SORTED_EXPECTED); + }); +}); diff --git a/src/redux/slices/arcgis-content-slice.ts b/src/redux/slices/arcgis-content-slice.ts new file mode 100644 index 00000000..e9f7cf38 --- /dev/null +++ b/src/redux/slices/arcgis-content-slice.ts @@ -0,0 +1,129 @@ +import { createSlice, PayloadAction, createAsyncThunk } from "@reduxjs/toolkit"; +import { IArcGisContent, ArcGisContentColumnName } from "../../types"; +import { RootState } from "../store"; +import { getArcGisUserContent } from "../../utils/arcgis"; + +// Define a type for the slice state +interface ArcGisContentState { + /** Array of user's content items taken from ArcGIS */ + arcGisContent: IArcGisContent[]; + /** Content item selected in UI */ + arcGisContentSelected: string; + /** Column name to sort the list by */ + sortColumn: ArcGisContentColumnName | null; + /** Sort order: 'ascending' - true, 'descending' - false */ + sortAscending: boolean; + /** Content loading status: when in progress - 'loading', otherwise - 'idle' */ + status: "idle" | "loading"; +} + +const initialState: ArcGisContentState = { + arcGisContent: [], + arcGisContentSelected: "", + sortColumn: null, + sortAscending: true, + status: "idle", +}; + +const sortList = (state: ArcGisContentState) => { + const column = state.sortColumn; + if (column) { + state.arcGisContent.sort((a: IArcGisContent, b: IArcGisContent) => { + let ac = a[column]; + let bc = b[column]; + if (ac === undefined || bc === undefined || ac === null || bc === null) { + return 0; + } + if (typeof ac === "string" && typeof bc === "string") { + ac = ac.toLowerCase(); + bc = bc.toLowerCase(); + } + if (ac === bc) { + return 0; + } + const comp = state.sortAscending ? ac > bc : ac < bc; + return comp ? 1 : -1; + }); + } +}; + +const arcGisContentSlice = createSlice({ + name: "arcGisContent", + initialState, + reducers: { + setSortAscending: ( + state: ArcGisContentState, + action: PayloadAction + ) => { + state.sortAscending = action.payload; + sortList(state); + }, + + // Note, sortColumn will never be set to its initial value (null). + // It's done on purpose. We don't support a scenario to get back to the unsorted content list. + setSortColumn: ( + state: ArcGisContentState, + action: PayloadAction + ) => { + state.sortColumn = action.payload; + sortList(state); + }, + + setArcGisContentSelected: ( + state: ArcGisContentState, + action: PayloadAction + ) => { + const item = state.arcGisContent.find( + (item) => item.id === action.payload + ); + if (item) { + state.arcGisContentSelected = action.payload; + } + }, + + resetArcGisContentSelected: (state: ArcGisContentState) => { + state.arcGisContentSelected = ""; + }, + }, + + extraReducers: (builder) => { + builder + .addCase(getArcGisContent.fulfilled, (state, action) => { + state.arcGisContent = [...action.payload]; + sortList(state); + state.status = "idle"; + }) + .addCase(getArcGisContent.pending, (state) => { + state.status = "loading"; + }); + }, +}); + +export const getArcGisContent = createAsyncThunk( + "getArcGisContent", + async (): Promise => { + const response: IArcGisContent[] = await getArcGisUserContent(); + return response; + } +); + +export const selectArcGisContent = (state: RootState): IArcGisContent[] => + state.arcGisContent.arcGisContent; + +export const selectArcGisContentSelected = (state: RootState): string => + state.arcGisContent.arcGisContentSelected; +export const selectSortAscending = (state: RootState): boolean => + state.arcGisContent.sortAscending; +export const selectSortColumn = (state: RootState): ArcGisContentColumnName | null => + state.arcGisContent.sortColumn; +export const selectStatus = (state: RootState): string => + state.arcGisContent.status; + +export const { + setArcGisContentSelected, + resetArcGisContentSelected, + setSortAscending, + setSortColumn, +} = arcGisContentSlice.actions; + +export default arcGisContentSlice.reducer; diff --git a/src/redux/store.ts b/src/redux/store.ts index 4b5b407d..fc89986a 100644 --- a/src/redux/store.ts +++ b/src/redux/store.ts @@ -11,6 +11,7 @@ import i3sStatsSliceReducer from "./slices/i3s-stats-slice"; import baseMapsSliceReducer from "./slices/base-maps-slice"; import symbolizationSliceReducer from "./slices/symbolization-slice"; import arcGisAuthSliceReducer from "./slices/arcgis-auth-slice"; +import arcGisContentSliceReducer from "./slices/arcgis-content-slice"; // Create the root reducer separately so we can extract the RootState type const rootReducer = combineReducers({ @@ -22,6 +23,7 @@ const rootReducer = combineReducers({ symbolization: symbolizationSliceReducer, i3sStats: i3sStatsSliceReducer, arcGisAuth: arcGisAuthSliceReducer, + arcGisContent: arcGisContentSliceReducer, }); export const setupStore = (preloadedState?: PreloadedState) => { diff --git a/src/types.ts b/src/types.ts index 1a44e9f8..c55a1f6f 100644 --- a/src/types.ts +++ b/src/types.ts @@ -367,3 +367,15 @@ export type TilesetMetadata = { hasChildren: boolean; type?: TilesetType; }; + +export interface IArcGisContent { + id: string; + url: string; + name: string; + title: string; + token?: string; + created: number; + createdFormatted: string; +} + +export type ArcGisContentColumnName = keyof IArcGisContent; diff --git a/src/utils/arcgis-auth.spec.ts b/src/utils/arcgis.spec.ts similarity index 51% rename from src/utils/arcgis-auth.spec.ts rename to src/utils/arcgis.spec.ts index 34ebf69d..2a95b573 100644 --- a/src/utils/arcgis-auth.spec.ts +++ b/src/utils/arcgis.spec.ts @@ -2,12 +2,32 @@ import { getAuthenticatedUser, arcGisRequestLogin, arcGisRequestLogout, -} from "./arcgis-auth"; + getArcGisUserContent, +} from "./arcgis"; jest.mock("@esri/arcgis-rest-request"); +jest.mock("@esri/arcgis-rest-portal"); const ARCGIS_REST_USER_INFO = "__ARCGIS_REST_USER_INFO__"; -const mockEmailExpected = "usermail@gmail.com"; +const EMAIL_EXPECTED = "usermail@gmail.com"; +const CONTENT_EXPECTED = [ + { + id: "new-york", + name: "NewYork.slpk", + url: "https://123.com", + created: 123456, + title: "New York", + token: "token-https://123.com", + }, + { + id: "turanga-library", + name: "TurangaLibrary.slpk", + url: "https://456.com", + created: 123457, + title: "Turanga Library", + token: "token-https://456.com", + }, +]; let OLD_ENV = {}; @@ -27,18 +47,24 @@ describe("ArcGIS auth functions", () => { }); it("Should return email of user logged in", () => { - localStorage.setItem(ARCGIS_REST_USER_INFO, mockEmailExpected); + localStorage.setItem(ARCGIS_REST_USER_INFO, EMAIL_EXPECTED); const email = getAuthenticatedUser(); - expect(email).toEqual(mockEmailExpected); + expect(email).toEqual(EMAIL_EXPECTED); }); it("Should request login and return email of user", async () => { const email = await arcGisRequestLogin(); - expect(email).toBe(mockEmailExpected); + expect(email).toBe(EMAIL_EXPECTED); }); it("Should request logout and return empty string", async () => { const email = await arcGisRequestLogout(); expect(email).toBe(""); }); + + it("Should return content with token", async () => { + await arcGisRequestLogin(); + const content = await getArcGisUserContent(); + expect(content).toEqual(CONTENT_EXPECTED); + }); }); diff --git a/src/utils/arcgis-auth.ts b/src/utils/arcgis.ts similarity index 67% rename from src/utils/arcgis-auth.ts rename to src/utils/arcgis.ts index 36d397ca..1f57666c 100644 --- a/src/utils/arcgis-auth.ts +++ b/src/utils/arcgis.ts @@ -1,4 +1,7 @@ import { ArcGISIdentityManager } from "@esri/arcgis-rest-request"; +import { getUserContent, IItem } from "@esri/arcgis-rest-portal"; +import { IArcGisContent } from "../types"; +import { formatTimestamp } from "../utils/format/format-utils"; const ARCGIS_REST_USER_SESSION = "__ARCGIS_REST_USER_SESSION__"; const ARCGIS_REST_USER_INFO = "__ARCGIS_REST_USER_INFO__"; @@ -97,3 +100,49 @@ export const arcGisRequestLogout = async () => { } return await updateSessionInfo(); }; + +class ArcGisContent implements IArcGisContent { + id = ""; + url = ""; + name = ""; + title = ""; + token? = ""; + created = 0; + get createdFormatted(): string { + return formatTimestamp(this.created); + } + + constructor(item: IItem, token: string) { + this.id = item.id; + this.url = item.url || ""; + this.name = item.name || item.title; + this.title = item.title; + this.token = token; + this.created = item.created; + } +} + +/** + * Gets the ArcGIS user's content list. + * @returns The content list containig the necessay info to load the content items. + */ +export const getArcGisUserContent = async (): Promise => { + const contentItems: IArcGisContent[] = []; + const authentication = getArcGisSession(); + if (authentication) { + const content = await getUserContent({ authentication }); + for (const item of content.items) { + if ( + item.url && + item.type === "Scene Service" && + item.typeKeywords && + item.typeKeywords.includes("Hosted Service") + ) { + const token = await authentication.getToken(item.url); + const contentItem: ArcGisContent = new ArcGisContent(item, token); + contentItems.push(contentItem); + } + } + } + return contentItems; +}; diff --git a/src/utils/format/format-utils.spec.ts b/src/utils/format/format-utils.spec.ts index 935f9100..94d83dbb 100644 --- a/src/utils/format/format-utils.spec.ts +++ b/src/utils/format/format-utils.spec.ts @@ -1,4 +1,10 @@ -import { formatBoolean, formatFloatNumber, formatIntValue, formatStringValue } from "./format-utils"; +import { + formatBoolean, + formatFloatNumber, + formatIntValue, + formatStringValue, + formatTimestamp, +} from "./format-utils"; describe("Format Utils", () => { describe("formatStringValue", () => { @@ -54,4 +60,10 @@ describe("Format Utils", () => { expect(result1).toBe("No"); }); }); + + describe("formatTimestamp", () => { + it("Should return date formatted", () => { + expect(formatTimestamp(1704877308897)).toBe("January 10, 2024"); + }); + }); }); diff --git a/src/utils/format/format-utils.ts b/src/utils/format/format-utils.ts index cfeded16..d0a71f64 100644 --- a/src/utils/format/format-utils.ts +++ b/src/utils/format/format-utils.ts @@ -49,3 +49,17 @@ export const formatFloatNumber = (value: number): string => { export const formatBoolean = (value: boolean): string => { return value ? "Yes" : "No"; }; + +/** + * Formats a date according to "en-US" locale. + * @param timestamp - timestamp to convert to string. + * @returns date formatted. + */ +export const formatTimestamp = (timestamp: number): string => { + const formatter = new Intl.DateTimeFormat("en-US", { + month: "long", + day: "2-digit", + year: "numeric", + }); + return formatter.format(timestamp); +} diff --git a/src/utils/testing-utils/e2e-layers-panel.tsx b/src/utils/testing-utils/e2e-layers-panel.tsx index 20c1d604..0ea50430 100644 --- a/src/utils/testing-utils/e2e-layers-panel.tsx +++ b/src/utils/testing-utils/e2e-layers-panel.tsx @@ -110,7 +110,7 @@ export const inserAndDeleteLayer = async ( `${panelId} > :nth-child(4) > :first-child > :nth-child(2) > :first-child` ); await insertButton.click(); - let insertPanel = await page.$(`${panelId} > :nth-child(5)`); + let insertPanel = await page.$(`${panelId} > :nth-child(7)`); // Header const insertPanelHeaderText = await insertPanel.$eval( @@ -156,19 +156,19 @@ export const inserAndDeleteLayer = async ( `${panelId} form.insert-form button[type='submit']` ); await submitInsert.click(); - await page.waitForSelector(`${panelId} > :nth-child(5)`); - const warningPanel = await page.$(`${panelId} > :nth-child(5)`); + await page.waitForSelector(`${panelId} > :nth-child(7)`); + const warningPanel = await page.$(`${panelId} > :nth-child(7)`); const warningText = await warningPanel.$eval( `:first-child > :first-child`, (node) => node.innerText ); expect(warningText).toBe("You are trying to add an existing area to the map"); await expect(page).toClick("button", { text: "Ok" }); - let anyExtraPanel = await page.$(`${panelId} > :nth-child(5)`); + let anyExtraPanel = await page.$(`${panelId} > :nth-child(7)`); expect(anyExtraPanel).toBeNull(); await insertButton.click(); - insertPanel = await page.$(`${panelId} > :nth-child(5)`); + insertPanel = await page.$(`${panelId} > :nth-child(7)`); // Add layer await fillForm(page, `${panelId} form.insert-form`, { @@ -180,7 +180,7 @@ export const inserAndDeleteLayer = async ( `${panelId} form.insert-form button[type='submit']` ); await submitInsert.click(); - anyExtraPanel = await page.$(`${panelId} > :nth-child(5)`); + anyExtraPanel = await page.$(`${panelId} > :nth-child(7)`); expect(anyExtraPanel).toBeNull(); let layers = await page.$$( From 24ad62e67aa1e14802d38b3364a4b76152328d84 Mon Sep 17 00:00:00 2001 From: mspivak-actionengine <118991512+mspivak-actionengine@users.noreply.github.com> Date: Wed, 17 Jan 2024 09:38:44 +0300 Subject: [PATCH 17/40] Update app.tsx Remove duplicated identifiers --- src/app.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/app.tsx b/src/app.tsx index adacfe69..871b625b 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -21,8 +21,6 @@ import { color_brand_secondary_dark, color_accent_primary, color_accent_tertiary, - color_brand_tertiary, - dim_brand_tertinary } from "./constants/colors"; import * as Pages from "./pages"; import { AppThemes, ComparisonMode, Theme } from "./types"; From 9272289506092a9cccd88835ae770c097fcdfecd Mon Sep 17 00:00:00 2001 From: mspivak-actionengine <118991512+mspivak-actionengine@users.noreply.github.com> Date: Wed, 17 Jan 2024 11:33:07 +0300 Subject: [PATCH 18/40] fix(slider): scroll to a new item (#342) --- src/components/slider/slider.tsx | 94 ++++++++++++++++++----------- src/pages/comparison/comparison.tsx | 2 +- src/pages/debug-app/debug-app.tsx | 2 +- src/pages/viewer-app/viewer-app.tsx | 2 +- 4 files changed, 62 insertions(+), 38 deletions(-) diff --git a/src/components/slider/slider.tsx b/src/components/slider/slider.tsx index 49db9d39..a82fd267 100644 --- a/src/components/slider/slider.tsx +++ b/src/components/slider/slider.tsx @@ -1,4 +1,4 @@ -import { useRef } from "react"; +import { useRef, useEffect } from "react"; import styled, { css } from "styled-components"; import ChevronIcon from "../../../public/icons/chevron.svg"; import { SliderListItem } from "./slider-list-item"; @@ -94,9 +94,6 @@ type SliderProps = { onDelete?: (id: string) => void; }; -const BOOKMARKS_OFFSET = 150; -const OFFSET = 54; - export const Slider = ({ data, editingMode, @@ -114,57 +111,84 @@ export const Slider = ({ } }; - const disableLeftArrow = selectedItemId === data[0]?.id || !selectedItemId; - const disableRightArrow = - selectedItemId === data[data.length - 1]?.id || !selectedItemId; - - const isBookmarkSlider = sliderType === SliderType.Bookmarks; - const isPhaseSlider = sliderType === SliderType.Phase; - const isFloorsSlider = sliderType === SliderType.Floors; - - const layout = useAppLayout(); - const handleLeftArrowClick = () => { const currentSelectedIndex = data.findIndex( (item) => item.id === selectedItemId ); - const prevItemId = data[currentSelectedIndex - 1].id; - onSelect(prevItemId); - - sliderItemsListRef?.current?.scrollBy({ - top: isFloorsSlider ? OFFSET : 0, - left: isBookmarkSlider ? -BOOKMARKS_OFFSET : isPhaseSlider ? -OFFSET : 0, - behavior: "smooth", - }); + const prevItemId = data[currentSelectedIndex - 1]?.id; + onSelectHandler(prevItemId); }; const handleRightArrowClick = () => { const currentSelectedIndex = data.findIndex( (item) => item.id === selectedItemId ); - const nextItemId = data[currentSelectedIndex + 1].id; - onSelect(nextItemId); - - sliderItemsListRef?.current?.scrollBy({ - top: isFloorsSlider ? -OFFSET : 0, - left: isBookmarkSlider ? BOOKMARKS_OFFSET : isPhaseSlider ? OFFSET : 0, - behavior: "smooth", - }); + const nextItemId = data[currentSelectedIndex + 1]?.id; + onSelectHandler(nextItemId); }; const onSelectHandler = (id: string): void => { - onSelect(id); + if (id) { + scrollItemIntoView(id); + onSelect(id); + } + }; + + const isItemVisible = (item: HTMLDivElement | undefined): boolean => { + const listElement = sliderItemsListRef?.current; + if (!item || !listElement) { + return false; + } + const listLeft = listElement.offsetLeft; + const listTop = listElement.offsetTop; + const listRight = listLeft + listElement.offsetWidth; + const listBottom = listTop + listElement.offsetHeight; + + const itemLeft = item.offsetLeft - listElement.scrollLeft; + const itemTop = item.offsetTop - listElement.scrollTop; + const itemRight = itemLeft + item.offsetWidth; + const itemBottom = itemTop + item.offsetHeight; + + const isVisible = + itemLeft >= listLeft && + itemRight <= listRight && + itemTop >= listTop && + itemBottom <= listBottom; + return isVisible; + }; + + const scrollItemIntoView = (id: string): void => { + if (!id) { + return; + } const listItem = listItems.current?.find( (item: HTMLDivElement) => item.id === id ); - if (isBookmarkSlider || isPhaseSlider) { - listItem?.scrollIntoView({ behavior: "smooth", inline: "center" }); - } else { - listItem?.scrollIntoView({ behavior: "smooth", block: "center" }); + const isVisible = isItemVisible(listItem); + if (!isVisible) { + if (isBookmarkSlider || isPhaseSlider) { + listItem?.scrollIntoView({ behavior: "smooth", inline: "nearest" }); + } else { + listItem?.scrollIntoView({ behavior: "smooth", block: "nearest" }); + } } }; + useEffect(() => { + scrollItemIntoView(selectedItemId); + }, [selectedItemId]); + + const disableLeftArrow = selectedItemId === data[0]?.id || !selectedItemId; + const disableRightArrow = + selectedItemId === data[data.length - 1]?.id || !selectedItemId; + + const isBookmarkSlider = sliderType === SliderType.Bookmarks; + const isPhaseSlider = sliderType === SliderType.Phase; + const isFloorsSlider = sliderType === SliderType.Floors; + + const layout = useAppLayout(); + return ( <> { const addBookmarkHandler = () => { const newBookmarkId = uuidv4(); - setSelectedBookmarkId(newBookmarkId); makeScreenshot().then((imageUrl) => { setBookmarks((prev) => [ ...prev, @@ -380,6 +379,7 @@ export const Comparison = ({ mode }: ComparisonPageProps) => { activeLayersIdsRightSide: [...activeLayersIdsRightSide], }, ]); + setSelectedBookmarkId(newBookmarkId); }); }; diff --git a/src/pages/debug-app/debug-app.tsx b/src/pages/debug-app/debug-app.tsx index 9bcbe2ee..235978da 100644 --- a/src/pages/debug-app/debug-app.tsx +++ b/src/pages/debug-app/debug-app.tsx @@ -567,7 +567,6 @@ export const DebugApp = () => { const addBookmarkHandler = () => { const newBookmarkId = uuidv4(); - setSelectedBookmarkId(newBookmarkId); makeScreenshot().then((imageUrl) => { setBookmarks((prev) => [ ...prev, @@ -583,6 +582,7 @@ export const DebugApp = () => { activeLayersIdsRightSide: [], }, ]); + setSelectedBookmarkId(newBookmarkId); }); }; diff --git a/src/pages/viewer-app/viewer-app.tsx b/src/pages/viewer-app/viewer-app.tsx index 9c5049dd..c2525e0c 100644 --- a/src/pages/viewer-app/viewer-app.tsx +++ b/src/pages/viewer-app/viewer-app.tsx @@ -437,7 +437,6 @@ export const ViewerApp = () => { const addBookmarkHandler = () => { const newBookmarkId = uuidv4(); - setSelectedBookmarkId(newBookmarkId); makeScreenshot().then((imageUrl) => { setBookmarks((prev) => [ ...prev, @@ -452,6 +451,7 @@ export const ViewerApp = () => { activeLayersIdsRightSide: [], }, ]); + setSelectedBookmarkId(newBookmarkId); }); }; From 160b2f496b73119bb2d085c8ea168637b255364f Mon Sep 17 00:00:00 2001 From: mspivak-actionengine <118991512+mspivak-actionengine@users.noreply.github.com> Date: Mon, 22 Jan 2024 12:27:39 +0300 Subject: [PATCH 19/40] fix(bookmarks-panel): hide Upload button (#341) --- .../bookmarks-panel/bookmarks-panel.spec.tsx | 4 +- .../bookmarks-panel/bookmarks-panel.tsx | 1 - .../upload-panel-item.spec.tsx | 67 ++++++++++++++----- .../bookmarks-panel/upload-panel-item.tsx | 11 +-- .../bookmarks-panel/upload-panel.spec.tsx | 2 - .../bookmarks-panel/upload-panel.tsx | 9 +-- 6 files changed, 60 insertions(+), 34 deletions(-) diff --git a/src/components/bookmarks-panel/bookmarks-panel.spec.tsx b/src/components/bookmarks-panel/bookmarks-panel.spec.tsx index f0040b7b..f71d73ae 100644 --- a/src/components/bookmarks-panel/bookmarks-panel.spec.tsx +++ b/src/components/bookmarks-panel/bookmarks-panel.spec.tsx @@ -177,7 +177,7 @@ describe("BookmarksPanel", () => { userEvent.click(uploadOption); const body = document.getElementsByTagName("body")[0]; const popover = body.childNodes[1]; - const uploadButton = getByText("Upload"); + const uploadButton = getByText("Next"); userEvent.click(uploadButton); expect(popover).toContainHTML(dragAndDropText); }); @@ -207,7 +207,7 @@ describe("BookmarksPanel", () => { userEvent.click(uploadOption); const body = document.getElementsByTagName("body")[0]; const popover = body.childNodes[1]; - const uploadButton = getByText("Upload"); + const uploadButton = getByText("Next"); userEvent.click(uploadButton); const cancelButton = getByText("Cancel"); userEvent.click(cancelButton); diff --git a/src/components/bookmarks-panel/bookmarks-panel.tsx b/src/components/bookmarks-panel/bookmarks-panel.tsx index ca002ba3..54727eaf 100644 --- a/src/components/bookmarks-panel/bookmarks-panel.tsx +++ b/src/components/bookmarks-panel/bookmarks-panel.tsx @@ -257,7 +257,6 @@ export const BookmarksPanel = ({ return ( setPopoverType(PopoverType.none)} - onConfirmWarning={() => console.log("not implemented yet")} onBookmarksUploaded={onBookmarksUploadedHandler} /> ); diff --git a/src/components/bookmarks-panel/upload-panel-item.spec.tsx b/src/components/bookmarks-panel/upload-panel-item.spec.tsx index ce6da753..f04cb91a 100644 --- a/src/components/bookmarks-panel/upload-panel-item.spec.tsx +++ b/src/components/bookmarks-panel/upload-panel-item.spec.tsx @@ -1,3 +1,4 @@ +import { screen } from "@testing-library/react"; import { renderWithTheme } from "../../utils/testing-utils/render-with-theme"; import { UploadPanelItem } from "./upload-panel-item"; import userEvent from "@testing-library/user-event"; @@ -5,34 +6,66 @@ import userEvent from "@testing-library/user-event"; const onCancel = jest.fn(); const onConfirm = jest.fn(); -const callRender = (renderFunc, props = {}) => { - return renderFunc( - - Test text - - ); -}; +describe("UploadPanelItem - Cancel and Confirm buttons", () => { + const callRender = (renderFunc, props = {}) => { + return renderFunc( + + Test text + + ); + }; -describe("UploadPanelItem", () => { it("Should render upload panel item", () => { - const { container, getByText } = callRender(renderWithTheme); + const { container } = callRender(renderWithTheme); expect(container.firstChild).toBeInTheDocument(); - getByText("Test item"); - getByText("Test text"); + expect(screen.queryByText("Test item")).toBeInTheDocument(); + expect(screen.queryByText("Test text")).toBeInTheDocument(); + expect(screen.queryByText("Cancel")).toBeInTheDocument(); + expect(screen.queryByText("Next")).toBeInTheDocument(); }); it("Should cancel or confirm upload", () => { const { getByText } = callRender(renderWithTheme); const cancelButton = getByText("Cancel"); - const uploadButton = getByText("Upload"); + const uploadButton = getByText("Next"); userEvent.click(cancelButton); expect(onCancel).toHaveBeenCalled(); userEvent.click(uploadButton); expect(onConfirm).toHaveBeenCalled(); }); }); + +describe("UploadPanelItem - Cancel only button", () => { + const callRender = (renderFunc, props = {}) => { + return renderFunc( + + Test text + + ); + }; + + it("Should render upload panel item", () => { + const { container } = callRender(renderWithTheme); + expect(container.firstChild).toBeInTheDocument(); + expect(screen.queryByText("Test item")).toBeInTheDocument(); + expect(screen.queryByText("Test text")).toBeInTheDocument(); + expect(screen.queryByText("Cancel")).toBeInTheDocument(); + expect(screen.queryByText("Next")).not.toBeInTheDocument(); + }); + + it("Should cancel or confirm upload", () => { + const { getByText } = callRender(renderWithTheme); + const cancelButton = getByText("Cancel"); + userEvent.click(cancelButton); + expect(onCancel).toHaveBeenCalled(); + }); +}); diff --git a/src/components/bookmarks-panel/upload-panel-item.tsx b/src/components/bookmarks-panel/upload-panel-item.tsx index 8da9682d..1ed83b22 100644 --- a/src/components/bookmarks-panel/upload-panel-item.tsx +++ b/src/components/bookmarks-panel/upload-panel-item.tsx @@ -28,16 +28,17 @@ const Title = styled.div` color: ${({ theme }) => theme.colors.fontColor}; `; -const ButtonsContainer = styled.div` +const ButtonsContainer = styled.div<{ justify: string }>` display: flex; - justify-content: space-between; + flex-direction: row; + justify-content: ${(props) => props.justify}; `; type UploadPanelItemProps = { title?: string; children: React.ReactNode; onCancel: () => void; - onConfirm: () => void; + onConfirm?: () => void; }; export const UploadPanelItem = ({ @@ -53,14 +54,14 @@ export const UploadPanelItem = ({ {title ? title : <WarningIcon />} {children} - + Cancel - Upload + {onConfirm && Next} diff --git a/src/components/bookmarks-panel/upload-panel.spec.tsx b/src/components/bookmarks-panel/upload-panel.spec.tsx index 32017d08..a6eb361b 100644 --- a/src/components/bookmarks-panel/upload-panel.spec.tsx +++ b/src/components/bookmarks-panel/upload-panel.spec.tsx @@ -14,14 +14,12 @@ jest.mock('@hyperjump/json-schema', () => ({ })); const onCancel = jest.fn(); -const onConfirmWarning = jest.fn(); const onBookmarksUploaded = jest.fn(); const callRender = (renderFunc, props = {}) => { return renderFunc( diff --git a/src/components/bookmarks-panel/upload-panel.tsx b/src/components/bookmarks-panel/upload-panel.tsx index 28f93cc0..1aec91ed 100644 --- a/src/components/bookmarks-panel/upload-panel.tsx +++ b/src/components/bookmarks-panel/upload-panel.tsx @@ -64,7 +64,6 @@ const UploadInput = styled.input` type ExistedLayerWarningProps = { onCancel: () => void; - onConfirmWarning: () => void; onBookmarksUploaded: (bookmarks: Bookmark[]) => void; }; @@ -72,7 +71,6 @@ export const dragAndDropText = "Drag and drop you json file here"; export const UploadPanel = ({ onCancel, - onConfirmWarning, onBookmarksUploaded, }: ExistedLayerWarningProps) => { const layout = useAppLayout(); @@ -92,7 +90,7 @@ export const UploadPanel = ({ const validator: Validator = await JsonSchema.validate(schema); result = JSON.parse(event.target.result); const validationResult: Result = validator(result); - if (validationResult.valid) { + if (validationResult.valid) { onBookmarksUploaded(result); } } catch { @@ -132,7 +130,6 @@ export const UploadPanel = ({ or )} - - browse file - + browse file {dragActive && ( Date: Tue, 23 Jan 2024 14:51:18 +0300 Subject: [PATCH 20/40] feat(comparison): download results tooltip (#346) --- .../compare-button/compare-button.spec.tsx | 15 ++- .../compare-button/compare-button.tsx | 95 ++++++++++++++++--- src/pages/comparison/comparison.tsx | 2 +- 3 files changed, 95 insertions(+), 17 deletions(-) diff --git a/src/components/comparison/compare-button/compare-button.spec.tsx b/src/components/comparison/compare-button/compare-button.spec.tsx index a2fea422..f233475c 100644 --- a/src/components/comparison/compare-button/compare-button.spec.tsx +++ b/src/components/comparison/compare-button/compare-button.spec.tsx @@ -82,8 +82,19 @@ describe("CompareButton", () => { expect(compareButton).toBeDisabled(); }); - it("Should show desktop tooltip when button is disabled", () => { - useAppLayoutMock.mockImplementation(() => "destop"); + it.skip("Should show desktop tooltip when button is disabled", () => { + /* + The test is temporarily skipped because of the following issue. + "@testing-library/user-event" of version 13.5.0 doesn't support pointer related events like PoinerEnter. + According to the documentation version 14.5.2 does support these events, + but actually neither PoinerEnter nor PoinerLeave are being fired on "hover". + The same issue is observed if fireEvent.pointerEnter is used. + Note, all userEvent methods (like click) have become async and require await in the new version of the library, + which requires appropriate changes in all the tests using such methods. + It would make sense to try "@testing-library/react" of the latest version, + but the problem is that the support of react of ver.17 (currently used) is dropped. + */ + useAppLayoutMock.mockImplementation(() => "desktop"); const { container, getByText } = callRender(renderWithTheme, { disableButton: true, }); diff --git a/src/components/comparison/compare-button/compare-button.tsx b/src/components/comparison/compare-button/compare-button.tsx index 36befdf4..cc48b739 100644 --- a/src/components/comparison/compare-button/compare-button.tsx +++ b/src/components/comparison/compare-button/compare-button.tsx @@ -1,4 +1,4 @@ -import { useState } from "react"; +import { useState, RefObject, useRef } from "react"; import styled, { css } from "styled-components"; import { CompareButtonMode, Layout, LayoutProps } from "../../../types"; import { Title } from "../../common"; @@ -18,7 +18,7 @@ const Container = styled.div` mobile: "top: 50%", })}; left: ${getCurrentLayoutProperty({ - desktop: "calc(50% - 95px)", + desktop: "calc(50% - 89px)", tablet: "calc(50% - 85px)", mobile: "calc(50% - 85px)", })}; @@ -71,10 +71,26 @@ const Button = styled.button< } `; -const Tooltip = styled.div<{ isMobile: boolean }>` - position: absolute; - top: 70px; - left: calc(50% - 200px); +const WrapperContainer = styled.div<{ + isMobile: boolean | undefined; + centerX: number; + centerY: number; +}>` + position: fixed; + top: calc(${({ centerY }) => centerY}px + 22px); + left: ${({ centerX }) => centerX}px; + transform: translate(-50%, 0); + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + gap: 0; +`; + +const TooltipDiv = styled.div<{ + isMobile: boolean | undefined; +}>` + position: relative; background-color: ${({ theme }) => theme.colors.mainHiglightColor}; border-radius: 8px; padding: 8px; @@ -89,19 +105,16 @@ const Tooltip = styled.div<{ isMobile: boolean }>` ${({ isMobile }) => isMobile && css` - height: 38px; - width: 250px; - left: calc(50% - 130px); - top: 65px; white-space: normal; text-align: center; + max-width: 250px; `} &:before { content: ""; position: absolute; bottom: 95%; - left: calc(50% - 15px); + left: calc(50% - 9px); border: 9px solid transparent; border-bottom-color: ${({ theme }) => theme.colors.mainHiglightColor}; } @@ -122,6 +135,32 @@ type CompareButtonProps = { onDownloadClick: () => void; }; +type TooltipProps = { + refElement: RefObject; + isMobileLayout: boolean; + children: React.ReactNode; +}; + +const Tooltip = ({ refElement, isMobileLayout, children }: TooltipProps) => { + let centerX = 0; + let centerY = 0; + + if (refElement.current) { + const rect = refElement.current.getBoundingClientRect(); + centerX = rect.left + rect.width / 2.0; + centerY = rect.top + rect.height; + } + return ( + + {children} + + ); +}; + export const CompareButton = ({ compareButtonMode, downloadStats, @@ -131,11 +170,13 @@ export const CompareButton = ({ onDownloadClick, }: CompareButtonProps) => { const [isHovering, setIsHovering] = useState(false); + const [isHoveringDownload, setIsHoveringDownload] = useState(false); const layout = useAppLayout(); const isMobileLayout = layout !== Layout.Desktop; - const showTooltip = (isHovering || isMobileLayout) && disableButton; + const refCompare = useRef(null); + const refDownload = useRef(null); const onPointerEnter = () => { setIsHovering(true); @@ -145,6 +186,27 @@ export const CompareButton = ({ setIsHovering(false); }; + const onPointerEnterDownload = () => { + setIsHoveringDownload(true); + }; + + const onPointerLeaveDownload = () => { + setIsHoveringDownload(false); + }; + + let showTooltip = false; + let refElement; + let content; + if ((isHovering || isMobileLayout) && disableButton) { + showTooltip = true; + refElement = refCompare; + content = "You can start comparison when all tiles are fully loaded"; + } else if ((isHoveringDownload || isMobileLayout) && downloadStats) { + showTooltip = true; + refElement = refDownload; + content = "Download comparison results"; + } + return ( )} + {showTooltip && ( - - You can start comparison when all tiles are fully loaded + + {content} )} diff --git a/src/pages/comparison/comparison.tsx b/src/pages/comparison/comparison.tsx index d9f9e960..33a96ce4 100644 --- a/src/pages/comparison/comparison.tsx +++ b/src/pages/comparison/comparison.tsx @@ -292,7 +292,7 @@ export const Comparison = ({ mode }: ComparisonPageProps) => { }; const downloadClickHandler = () => { - downloadJsonFile(comparisonStats, "bookmarks-stats.json"); + downloadJsonFile(comparisonStats, "comparison-results-stats.json"); }; const onBookmarksUploadedHandler = (bookmarks: Bookmark[]) => { From d98072d8b8b0235f66d572ca9f405bb022b8d515 Mon Sep 17 00:00:00 2001 From: mspivak-actionengine <118991512+mspivak-actionengine@users.noreply.github.com> Date: Wed, 24 Jan 2024 14:07:55 +0300 Subject: [PATCH 21/40] feat(bookmark): add wrong-bookmark warning (#345) --- src/components/common.tsx | 29 ++++++++++++++++++++++++----- src/pages/comparison/comparison.tsx | 17 ++++++++++++++--- src/pages/debug-app/debug-app.tsx | 17 ++++++++++++++--- src/pages/viewer-app/viewer-app.tsx | 17 ++++++++++++++--- 4 files changed, 66 insertions(+), 14 deletions(-) diff --git a/src/components/common.tsx b/src/components/common.tsx index 1c566be2..5c04f168 100644 --- a/src/components/common.tsx +++ b/src/components/common.tsx @@ -26,7 +26,10 @@ export const PanelContainer = styled.div` display: flex; flex-direction: column; width: 359px; - background: ${({ theme }) => `${theme.colors.mainCanvasColor}${theme.name === Theme.Dark ? 'e6' : 'ff'}` }; + background: ${({ theme }) => + `${theme.colors.mainCanvasColor}${ + theme.name === Theme.Dark ? "e6" : "ff" + }`}; border-radius: 8px; padding-bottom: 26px; position: relative; @@ -67,7 +70,8 @@ export const PanelHorizontalLine = styled.div<{ left?: number; right?: number; }>` - margin: ${({ top = 24, bottom = 16, left = 16, right = 16 }) => `${top}px ${right}px ${bottom}px ${left}px`}; + margin: ${({ top = 24, bottom = 16, left = 16, right = 16 }) => + `${top}px ${right}px ${bottom}px ${left}px`}; border: 1px solid ${({ theme }) => theme.colors.mainHiglightColorInverted}; border-radius: 1px; background: ${({ theme }) => theme.colors.mainHiglightColorInverted}; @@ -107,7 +111,6 @@ export const RightSideToolsPanelWrapper = styled(LeftSideToolsPanelWrapper)` })}; `; - export const OnlyToolsPanelWrapper = styled(LeftSideToolsPanelWrapper)` left: auto; top: auto; @@ -230,8 +233,13 @@ export const OptionsIcon = styled.div<{ panel: number }>` } `; -export const Title = styled.div<{top?: number; bottom?: number; left?: number }>` - margin: ${({top = 0, bottom = 0, left = 0 }) => `${top}px 0 ${bottom}px ${left}px`}; +export const Title = styled.div<{ + top?: number; + bottom?: number; + left?: number; +}>` + margin: ${({ top = 0, bottom = 0, left = 0 }) => + `${top}px 0 ${bottom}px ${left}px`}; font-style: normal; font-weight: 700; font-size: 16px; @@ -302,3 +310,14 @@ export const TileInfoSectionWrapper = styled.div` width: 100%; margin: 24px 0; `; + +export const CenteredContainer = styled.div` + position: fixed; + left: 0; + top: 0; + width: 100%; + height: 100%; + display: flex; + justify-content: center; + align-items: center; +`; diff --git a/src/pages/comparison/comparison.tsx b/src/pages/comparison/comparison.tsx index 33a96ce4..150409d9 100644 --- a/src/pages/comparison/comparison.tsx +++ b/src/pages/comparison/comparison.tsx @@ -38,6 +38,8 @@ import { deleteBaseMaps, setInitialBaseMaps, } from "../../redux/slices/base-maps-slice"; +import { WarningPanel } from "../../components/layers-panel/warning/warning-panel"; +import { CenteredContainer } from "../../components/common"; type ComparisonPageProps = { mode: ComparisonMode; @@ -132,6 +134,9 @@ export const Comparison = ({ mode }: ComparisonPageProps) => { useState(false); const [buildingExplorerOpenedRight, setBuildingExplorerOpenedRight] = useState(false); + const [wrongBookmarkPageId, setWrongBookmarkPageId] = useState( + null + ); const dispatch = useAppDispatch(); const layout = useAppLayout(); @@ -305,9 +310,7 @@ export const Comparison = ({ mode }: ComparisonPageProps) => { setBookmarks(bookmarks); onSelectBookmarkHandler(bookmarks[0].id, bookmarks); } else { - console.warn( - `Can't add bookmars with ${bookmarksPageId} pageId to the comparison app` - ); + setWrongBookmarkPageId(bookmarksPageId); } }; @@ -551,6 +554,14 @@ export const Comparison = ({ mode }: ComparisonPageProps) => { bottom={layout === Layout.Mobile ? 8 : 16} /> )} + {wrongBookmarkPageId && ( + + setWrongBookmarkPageId(null)} + /> + + )} ); }; diff --git a/src/pages/debug-app/debug-app.tsx b/src/pages/debug-app/debug-app.tsx index 235978da..7ce00021 100644 --- a/src/pages/debug-app/debug-app.tsx +++ b/src/pages/debug-app/debug-app.tsx @@ -49,6 +49,7 @@ import { MapArea, RightSidePanelWrapper, OnlyToolsPanelWrapper, + CenteredContainer, } from "../../components/common"; import { MainToolsPanel } from "../../components/main-tools-panel/main-tools-panel"; import { LayersPanel } from "../../components/layers-panel/layers-panel"; @@ -91,6 +92,7 @@ import { import { setInitialBaseMaps } from "../../redux/slices/base-maps-slice"; import { setFiltersByAttrubute } from "../../redux/slices/symbolization-slice"; import { clearBSLStatisitcsSummary } from "../../redux/slices/i3s-stats-slice"; +import { WarningPanel } from "../../components/layers-panel/warning/warning-panel"; const INITIAL_VIEW_STATE = { main: { @@ -155,6 +157,9 @@ export const DebugApp = () => { useState(false); const [stateUrlViewStateParams, setStateUrlViewStateParams] = useState({}); + const [wrongBookmarkPageId, setWrongBookmarkPageId] = useState( + null + ); const [, setSearchParams] = useSearchParams(); const dispatch = useAppDispatch(); @@ -656,9 +661,7 @@ export const DebugApp = () => { setBookmarks(bookmarks); onSelectBookmarkHandler(bookmarks[0].id, bookmarks); } else { - console.warn( - `Can't add bookmars with ${bookmarksPageId} pageId to the debug app` - ); + setWrongBookmarkPageId(bookmarksPageId); } }; @@ -865,6 +868,14 @@ export const DebugApp = () => { onZoomOut={onZoomOut} onCompassClick={onCompassClick} /> + {wrongBookmarkPageId && ( + + setWrongBookmarkPageId(null)} + /> + + )} ); }; diff --git a/src/pages/viewer-app/viewer-app.tsx b/src/pages/viewer-app/viewer-app.tsx index c2525e0c..67f33de5 100644 --- a/src/pages/viewer-app/viewer-app.tsx +++ b/src/pages/viewer-app/viewer-app.tsx @@ -41,6 +41,7 @@ import { MapArea, RightSidePanelWrapper, OnlyToolsPanelWrapper, + CenteredContainer, } from "../../components/common"; import { MainToolsPanel } from "../../components/main-tools-panel/main-tools-panel"; import { LayersPanel } from "../../components/layers-panel/layers-panel"; @@ -78,6 +79,7 @@ import { setInitialBaseMaps } from "../../redux/slices/base-maps-slice"; import { getBSLStatisticsSummary } from "../../redux/slices/i3s-stats-slice"; import { RootState } from "../../redux/store"; import { useSelector } from "react-redux"; +import { WarningPanel } from "../../components/layers-panel/warning/warning-panel"; const INITIAL_VIEW_STATE = { main: { @@ -134,6 +136,9 @@ export const ViewerApp = () => { const filtersByAttribute = useSelector((state: RootState) => selectFiltersByAttribute(state) ); + const [wrongBookmarkPageId, setWrongBookmarkPageId] = useState( + null + ); const selectedLayerIds = useMemo( () => activeLayers.map((layer) => layer.id), @@ -518,9 +523,7 @@ export const ViewerApp = () => { setBookmarks(bookmarks); onSelectBookmarkHandler(bookmarks[0].id, bookmarks); } else { - console.warn( - `Can't add bookmars with ${bookmarksPageId} pageId to the viewer app` - ); + setWrongBookmarkPageId(bookmarksPageId); } }; @@ -692,6 +695,14 @@ export const ViewerApp = () => { onZoomOut={onZoomOut} onCompassClick={onCompassClick} /> + {wrongBookmarkPageId && ( + + setWrongBookmarkPageId(null)} + /> + + )} ); }; From 9050b259d59a23d0087b1ef3496c57753d9968d5 Mon Sep 17 00:00:00 2001 From: mspivak-actionengine <118991512+mspivak-actionengine@users.noreply.github.com> Date: Wed, 31 Jan 2024 18:30:14 +0300 Subject: [PATCH 22/40] fix(layers): show unsupported layer types in the scene (#347) --- package.json | 10 +-- src/app.tsx | 2 + src/components/layers-panel/layers-panel.tsx | 80 +++++++++++++++----- 3 files changed, 67 insertions(+), 25 deletions(-) diff --git a/package.json b/package.json index 92225483..cee86e65 100644 --- a/package.json +++ b/package.json @@ -27,10 +27,10 @@ "@fortawesome/free-solid-svg-icons": "^5.15.4", "@fortawesome/react-fontawesome": "^0.1.17", "@hyperjump/json-schema": "^0.23.2", - "@loaders.gl/3d-tiles": "^4.0.0-beta.8", - "@loaders.gl/core": "^4.0.0-beta.8", - "@loaders.gl/i3s": "^4.0.0-beta.8", - "@loaders.gl/tiles": "^4.0.0-beta.8", + "@loaders.gl/3d-tiles": "^4.1.0-alpha.11", + "@loaders.gl/core": "^4.1.0-alpha.11", + "@loaders.gl/i3s": "^4.1.0-alpha.11", + "@loaders.gl/tiles": "^4.1.0-alpha.11", "@luma.gl/core": "^8.5.14", "@math.gl/core": "^3.6.0", "@math.gl/proj4": "^3.6.3", @@ -91,7 +91,7 @@ "webpack-dev-server": "^4.7.4" }, "resolutions": { - "@loaders.gl/tiles": "^4.0.0-beta.8" + "@loaders.gl/tiles": "^4.1.0-alpha.11" }, "volta": { "node": "18.18.2", diff --git a/src/app.tsx b/src/app.tsx index 871b625b..047df5c1 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -88,6 +88,7 @@ const THEMES: AppThemes = { switchDisabledBackgroundHovered: dim_canvas_primary, switchCheckedBackground: color_brand_tertiary, switchCheckedBackgroundHovered: dim_brand_tertinary, + bullet: color_canvas_secondary, }, name: Theme.Dark, }, @@ -130,6 +131,7 @@ const THEMES: AppThemes = { switchDisabledBackgroundHovered: color_canvas_secondary_inverted, switchCheckedBackground: color_brand_tertiary, switchCheckedBackgroundHovered: dim_brand_tertinary, + bullet: hilite_canvas_primary, }, name: Theme.Light, }, diff --git a/src/components/layers-panel/layers-panel.tsx b/src/components/layers-panel/layers-panel.tsx index 7093cf56..a98f069a 100644 --- a/src/components/layers-panel/layers-panel.tsx +++ b/src/components/layers-panel/layers-panel.tsx @@ -28,11 +28,10 @@ import { PanelHorizontalLine, Panels, } from "../common"; -import { color_brand_senary } from "../../constants/colors"; import { LayerSettingsPanel } from "./layer-settings-panel"; import { WarningPanel } from "./warning/warning-panel"; import { useClickOutside } from "../../utils/hooks/use-click-outside-hook"; -import { ArcGISWebSceneLoader } from "@loaders.gl/i3s"; +import { ArcGISWebSceneLoader, LayerError } from "@loaders.gl/i3s"; import { ActiveSublayer } from "../../utils/active-sublayer"; import { useAppLayout } from "../../utils/hooks/layout"; import { getTilesetType, convertUrlToRestFormat } from "../../utils/url-utils"; @@ -42,8 +41,8 @@ import { addBaseMap } from "../../redux/slices/base-maps-slice"; const EXISTING_AREA_ERROR = "You are trying to add an existing area to the map"; -const NOT_SUPPORTED_LAYERS_ERROR = - "There are no supported layers in the scene. Supported layers:"; +const LAYERS_ERROR_UNSUPPORTED = "There are unsupported layers in the scene:"; +const LAYERS_ERROR_SUPPORTED = "Supported layer types:"; const NOT_SUPPORTED_CRS_ERROR = "There is no supported CRS system. Only WGS84 is supported."; @@ -116,27 +115,38 @@ const CloseButtonWrapper = styled.div` display: flex; `; -const SupportedLayersList = styled.ul` - margin-top: 28px; +const LayersList = styled.ul` + margin-top: 16px; padding-left: 25px; margin-bottom: 0; + display: flex; + flex-direction: column; + gap: 8px; `; -const SupportedLayerItem = styled.li` +const LayerItem = styled.li` + padding-left: 6px; font-style: normal; - font-weight: 400; + font-weight: 500; font-size: 16px; line-height: 19px; color: ${({ theme }) => theme.colors.fontColor}; - margin-bottom: 13px; &::marker { - color: ${color_brand_senary}; + color: ${({ theme }) => theme.colors.bullet}; } +`; - &:last-child { - margin-bottom: 0px; - } +const TitleWrapper = styled.div` + margin-top: 28px; + margin-left: 32px; + display: flex; + align-items: center; + font-style: normal; + font-weight: 700; + font-size: 16px; + line-height: 19px; + color: ${({ theme }) => theme.colors.fontColor}; `; type LayersPanelProps = { @@ -195,6 +205,7 @@ export const LayersPanel = ({ useState(false); const [warningNode, setWarningNode] = useState(null); const [showAddingSlidesWarning, setShowAddingSlidesWarning] = useState(false); + const [unsupportedLayers, setUnsupportedLayers] = useState([]); useClickOutside([warningNode], () => setShowExistedError(false)); @@ -246,6 +257,18 @@ export const LayersPanel = ({ return layersList; }; + const saveLayerTypes = (layers) => { + const layerTypes: string[] = []; + if (layers) { + for (const layer of layers) { + if (!layerTypes.find((item) => item === layer.layerType)) { + layerTypes.push(layer.layerType); + } + } + } + setUnsupportedLayers(layerTypes); + }; + // TODO Add loader to show webscene loading const handleInsertScene = async (scene: { name: string; @@ -269,6 +292,12 @@ export const LayersPanel = ({ scene.url, ArcGISWebSceneLoader )) as ArcGISWebSceneData; + + if (webScene.unsupportedLayers?.length) { + saveLayerTypes(webScene.unsupportedLayers); + setShowNoSupportedLayersInSceneError(true); + } + const webSceneLayerExamples = prepareLayerExamples(webScene.layers); const newLayer: LayerExample = { @@ -298,12 +327,13 @@ export const LayersPanel = ({ setShowAddingSlidesWarning(true); } - // TODO Check unsupported layers inside webScene to show warning about some layers are not included to the webscene. onLayerInsert(newLayer, bookmarks); } catch (error) { if (error instanceof Error) { switch (error.message) { case "NO_AVAILABLE_SUPPORTED_LAYERS_ERROR": { + const layers = (error as LayerError).details; + saveLayerTypes(layers); setShowSceneInsertPanel(false); setShowNoSupportedLayersInSceneError(true); break; @@ -400,14 +430,24 @@ export const LayersPanel = ({ {showNoSupportedLayersInSceneError && ( setWarningNode(element)}> setShowNoSupportedLayersInSceneError(false)} > - - IntegratedMesh - 3DObjects - Building - + <> + + {unsupportedLayers.map((layer) => { + return {layer}; + })} + + + {LAYERS_ERROR_SUPPORTED} + + + IntegratedMesh + 3DObjects + Building + + )} From af6f33ffd517ba999f9a24f31e2b03f203174621 Mon Sep 17 00:00:00 2001 From: Viktor Belomestnov Date: Tue, 6 Feb 2024 10:26:51 +0100 Subject: [PATCH 23/40] chore: update yarn.lock (#348) --- yarn.lock | 312 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 209 insertions(+), 103 deletions(-) diff --git a/yarn.lock b/yarn.lock index 8e567479..9365150f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1826,6 +1826,50 @@ minimatch "^3.0.4" strip-json-comments "^3.1.1" +"@esri/arcgis-rest-auth@^3.7.0": + version "3.7.0" + resolved "https://registry.yarnpkg.com/@esri/arcgis-rest-auth/-/arcgis-rest-auth-3.7.0.tgz#28c0ea1e5c97771e60a41a91e1916e909b5088eb" + integrity sha512-/FovDS6hR+3TPfXOpTOMbAu7vNAOLmIjK/lxt0w0nQd+8Nnx3u91BoGMr9pRBGzAJBJm9/i2yGljbFaNXegusQ== + dependencies: + "@esri/arcgis-rest-types" "^3.7.0" + tslib "^1.13.0" + +"@esri/arcgis-rest-fetch@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@esri/arcgis-rest-fetch/-/arcgis-rest-fetch-4.0.0.tgz#aa5bf2bedccc168ea52433eb9c56b452b450500d" + integrity sha512-ybsMO2L4cxx0IaIx0jv6/VbXidZmQIiGD3bvPF1/n1Y1ljHIhCvX+ti54cQSfg/HW2+VAVVnt8EPD/omVhNAyg== + dependencies: + node-fetch "^3.0.0" + +"@esri/arcgis-rest-form-data@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@esri/arcgis-rest-form-data/-/arcgis-rest-form-data-4.0.0.tgz#bea44236863348b6433440083f4dd9d4c42497f6" + integrity sha512-cAS9HONIJgseCDdgRCIHBR4CE/OQXZIRP3FoNx/w+XyjVqK6yQiwCeXpYLfHeEZ6GEQqrA9XUBxifWG9UaJyXA== + dependencies: + formdata-node "^4.1.0" + +"@esri/arcgis-rest-portal@^4.4.0": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@esri/arcgis-rest-portal/-/arcgis-rest-portal-4.4.0.tgz#d1b27a2e2fce48ecc5fdc4828e298f42a11e9142" + integrity sha512-eNQ+Ddj1rYu8ttDdP/JkOUpwsfClq0KjT39C4L+Z2fQKFOl8xlIqexYRdM9tG7xNnXj4JLu3sr/JcVlMk6hFbQ== + dependencies: + tslib "^2.3.0" + +"@esri/arcgis-rest-request@^4.2.0": + version "4.2.0" + resolved "https://registry.yarnpkg.com/@esri/arcgis-rest-request/-/arcgis-rest-request-4.2.0.tgz#8080e271851302e555ae7b549139a2d3d49a3ee7" + integrity sha512-2XLy0Ivar3BIr4ehe/5hYottIqiHnC8LDqhMPglufoLcsX9LFOr81X74aPXX0Ad3xVMaSy2HLLVNoNOkhwFGqQ== + dependencies: + "@esri/arcgis-rest-fetch" "^4.0.0" + "@esri/arcgis-rest-form-data" "^4.0.0" + mitt "^3.0.0" + tslib "^2.3.1" + +"@esri/arcgis-rest-types@^3.7.0": + version "3.7.0" + resolved "https://registry.yarnpkg.com/@esri/arcgis-rest-types/-/arcgis-rest-types-3.7.0.tgz#3fa61b95b63e4129b73a499411b368aa7940490b" + integrity sha512-KEgORx0HKHOrV4oMYOwmZ76N89WTNkbKb1z3UYJrOEaKVGRU3jisgQcuTXFqjJJe4ZApGQhxCzNgcaU067qdpA== + "@fortawesome/fontawesome-common-types@^0.2.36": version "0.2.36" resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.36.tgz#b44e52db3b6b20523e0c57ef8c42d315532cb903" @@ -2172,30 +2216,30 @@ "@math.gl/core" "^3.5.1" "@math.gl/geospatial" "^3.5.1" -"@loaders.gl/3d-tiles@^4.0.0-beta.8": - version "4.0.0-beta.8" - resolved "https://registry.yarnpkg.com/@loaders.gl/3d-tiles/-/3d-tiles-4.0.0-beta.8.tgz#51be3cff322cd87d2a3eacd072d3e8faec63e2eb" - integrity sha512-JEIfqFK/AHEq451X1zgx554wBoEkxBtqYrbnlXY0bcjmw1n906u6phcNFsjNgxiFbyakDwB/s1kxYD5a9Ps3Kw== - dependencies: - "@loaders.gl/draco" "4.0.0-beta.8" - "@loaders.gl/gltf" "4.0.0-beta.8" - "@loaders.gl/loader-utils" "4.0.0-beta.8" - "@loaders.gl/math" "4.0.0-beta.8" - "@loaders.gl/tiles" "4.0.0-beta.8" - "@loaders.gl/zip" "4.0.0-beta.8" +"@loaders.gl/3d-tiles@^4.1.0-alpha.11": + version "4.1.0-alpha.11" + resolved "https://registry.yarnpkg.com/@loaders.gl/3d-tiles/-/3d-tiles-4.1.0-alpha.11.tgz#edf0632cb1b8989b41fcf9e8572088d1330866fb" + integrity sha512-8cp+Lh2assMEdh3eIBDwFfr9aNiKpKfemlbeqU5Am29MbKhszOH2+yVy6shMK0/OmQgQ6GvznbMvVU3zriA27g== + dependencies: + "@loaders.gl/draco" "4.1.0-alpha.11" + "@loaders.gl/gltf" "4.1.0-alpha.11" + "@loaders.gl/loader-utils" "4.1.0-alpha.11" + "@loaders.gl/math" "4.1.0-alpha.11" + "@loaders.gl/tiles" "4.1.0-alpha.11" + "@loaders.gl/zip" "4.1.0-alpha.11" "@math.gl/core" "^4.0.0" "@math.gl/geospatial" "^4.0.0" "@probe.gl/log" "^4.0.4" long "^5.2.1" -"@loaders.gl/compression@4.0.0-beta.8": - version "4.0.0-beta.8" - resolved "https://registry.yarnpkg.com/@loaders.gl/compression/-/compression-4.0.0-beta.8.tgz#03258e0e2fe21c0f8012934d44ca7bb10321fa04" - integrity sha512-ieaSv7/d+tAS753DkpitJ/CaffYcAPIz2DPOs04f6n5taaw5H6hK9GP2L6vT6GVnkGvGXgmdYDjTbIg54UuuGg== +"@loaders.gl/compression@4.1.0-alpha.11": + version "4.1.0-alpha.11" + resolved "https://registry.yarnpkg.com/@loaders.gl/compression/-/compression-4.1.0-alpha.11.tgz#72b504b17aa3bc1569519c5c3cf889c12503ceb3" + integrity sha512-IZmUVXFfluGg6NXvIlkuduHLnUD8WvbZZGzsNmRAjlFqTHWlhcLTy9l9CrqlMLWULA3oryWyFSy+2z7IVI3Y0Q== dependencies: "@babel/runtime" "^7.3.1" - "@loaders.gl/loader-utils" "4.0.0-beta.8" - "@loaders.gl/worker-utils" "4.0.0-beta.8" + "@loaders.gl/loader-utils" "4.1.0-alpha.11" + "@loaders.gl/worker-utils" "4.1.0-alpha.11" "@types/brotli" "^1.3.0" "@types/pako" "^1.0.1" fflate "0.7.4" @@ -2218,24 +2262,24 @@ "@probe.gl/log" "^3.5.0" probe.gl "^3.4.0" -"@loaders.gl/core@^4.0.0-beta.8": - version "4.0.0-beta.8" - resolved "https://registry.yarnpkg.com/@loaders.gl/core/-/core-4.0.0-beta.8.tgz#a595927010b993d8eaec86264e68a1c35c2a8c7f" - integrity sha512-s+iKjcvhHq/jsQJi6qDDZtTzANTergV5KY4XsN4W1j5xy+ZbqF1drMIEPzfTAhaL/elifALpm1lX7is9l0rVoA== +"@loaders.gl/core@^4.1.0-alpha.11": + version "4.1.0-alpha.11" + resolved "https://registry.yarnpkg.com/@loaders.gl/core/-/core-4.1.0-alpha.11.tgz#6c20ff8cb1092ef8edaade26fca2450dfac33c99" + integrity sha512-H2CocuchkAz2eQs8jqUiYlTv6P11o+gveIjZjpgVh/NpwXBORL+cwO1+B3WJ5+WKQdePHgFzL1GPbvM4J04Q6A== dependencies: "@babel/runtime" "^7.3.1" - "@loaders.gl/loader-utils" "4.0.0-beta.8" - "@loaders.gl/worker-utils" "4.0.0-beta.8" + "@loaders.gl/loader-utils" "4.1.0-alpha.11" + "@loaders.gl/worker-utils" "4.1.0-alpha.11" "@probe.gl/log" "^4.0.2" -"@loaders.gl/crypto@4.0.0-beta.8": - version "4.0.0-beta.8" - resolved "https://registry.yarnpkg.com/@loaders.gl/crypto/-/crypto-4.0.0-beta.8.tgz#be66af5f832b50ab81cd88c2840ce2316260f6b2" - integrity sha512-2ZnRx8GOsIVLwroP3aC0F7qL2ii0Is1A7o0GaugYJDlBNQlcXDQOCL88JuYTou9o0qzjVVQVkNzbq5jpnI7bpw== +"@loaders.gl/crypto@4.1.0-alpha.11": + version "4.1.0-alpha.11" + resolved "https://registry.yarnpkg.com/@loaders.gl/crypto/-/crypto-4.1.0-alpha.11.tgz#4a5bf79a09b7dfa97ad5a4ae9784c3df1da153da" + integrity sha512-FpUbaeCKei6AfkLZO2nmyQLO6nQO3udk9iZ/icxyNffp2X8sBDEVDu+0Xcm88sfiQ5Ainj41FTotFLxCBZRZ4w== dependencies: "@babel/runtime" "^7.3.1" - "@loaders.gl/loader-utils" "4.0.0-beta.8" - "@loaders.gl/worker-utils" "4.0.0-beta.8" + "@loaders.gl/loader-utils" "4.1.0-alpha.11" + "@loaders.gl/worker-utils" "4.1.0-alpha.11" "@types/crypto-js" "^4.0.2" "@loaders.gl/draco@3.2.12": @@ -2249,15 +2293,15 @@ "@loaders.gl/worker-utils" "3.2.12" draco3d "1.4.1" -"@loaders.gl/draco@4.0.0-beta.8": - version "4.0.0-beta.8" - resolved "https://registry.yarnpkg.com/@loaders.gl/draco/-/draco-4.0.0-beta.8.tgz#a632f87d640251fa919a1a8c0e40ee341efbeb77" - integrity sha512-XLzK9cETOtKPAsjkJvSTTPt3Ej22kCtEy42AN+96TlhhsMSXK1KRPIRaDl9JD6uOV+4g2oXrcINaiURmxmlG8g== +"@loaders.gl/draco@4.1.0-alpha.11": + version "4.1.0-alpha.11" + resolved "https://registry.yarnpkg.com/@loaders.gl/draco/-/draco-4.1.0-alpha.11.tgz#7785934565a9757ccfb81a7ec6f74e80a1340b9d" + integrity sha512-eoAm8NB0nv9pFus7CJ3miUEJkhwI//PKbU+wAduKjKeNJUSSNxDYY8AJPVKHOw1X2NVlfLhQ8hlfbrj0zZljog== dependencies: "@babel/runtime" "^7.3.1" - "@loaders.gl/loader-utils" "4.0.0-beta.8" - "@loaders.gl/schema" "4.0.0-beta.8" - "@loaders.gl/worker-utils" "4.0.0-beta.8" + "@loaders.gl/loader-utils" "4.1.0-alpha.11" + "@loaders.gl/schema" "4.1.0-alpha.11" + "@loaders.gl/worker-utils" "4.1.0-alpha.11" draco3d "1.5.5" "@loaders.gl/gis@3.2.12", "@loaders.gl/gis@^3.2.0": @@ -2281,30 +2325,30 @@ "@loaders.gl/loader-utils" "3.2.12" "@loaders.gl/textures" "3.2.12" -"@loaders.gl/gltf@4.0.0-beta.8": - version "4.0.0-beta.8" - resolved "https://registry.yarnpkg.com/@loaders.gl/gltf/-/gltf-4.0.0-beta.8.tgz#9fe2dd76ce28d183f1b0b80b15b12a92c868211c" - integrity sha512-iMRNVcxBQYxGqGDORYXd1i/dpC//8NHpvAS7ayHaA069TBdYQJ8fQHtOTkgNgWx84TdRboCodidH13NLoZNT+Q== +"@loaders.gl/gltf@4.1.0-alpha.11": + version "4.1.0-alpha.11" + resolved "https://registry.yarnpkg.com/@loaders.gl/gltf/-/gltf-4.1.0-alpha.11.tgz#820bae8be5c17da2be908bca334b8e4d4fb4c4e6" + integrity sha512-f9Z4xKm63fbQNj7Vi1S6vHE2roO+s3u31ifgWhndMgxFt3SYw+mCno2XdfsQuD7TDR1zxIET7sYTbw1shevbxw== dependencies: - "@loaders.gl/draco" "4.0.0-beta.8" - "@loaders.gl/images" "4.0.0-beta.8" - "@loaders.gl/loader-utils" "4.0.0-beta.8" - "@loaders.gl/textures" "4.0.0-beta.8" + "@loaders.gl/draco" "4.1.0-alpha.11" + "@loaders.gl/images" "4.1.0-alpha.11" + "@loaders.gl/loader-utils" "4.1.0-alpha.11" + "@loaders.gl/textures" "4.1.0-alpha.11" "@math.gl/core" "^4.0.0" -"@loaders.gl/i3s@^4.0.0-beta.8": - version "4.0.0-beta.8" - resolved "https://registry.yarnpkg.com/@loaders.gl/i3s/-/i3s-4.0.0-beta.8.tgz#dd130235bac98b7d80e1e9a93e0925903c12e69c" - integrity sha512-0WqxYj5bcKa2JRcZrvVPtgRRH+vxXF0+UV/ViPJjKANVKCkm1pmRhFzhcVoOvkTeBytFRDvZYkIBvV3uIZG9XA== - dependencies: - "@loaders.gl/compression" "4.0.0-beta.8" - "@loaders.gl/crypto" "4.0.0-beta.8" - "@loaders.gl/draco" "4.0.0-beta.8" - "@loaders.gl/images" "4.0.0-beta.8" - "@loaders.gl/loader-utils" "4.0.0-beta.8" - "@loaders.gl/schema" "4.0.0-beta.8" - "@loaders.gl/textures" "4.0.0-beta.8" - "@loaders.gl/tiles" "4.0.0-beta.8" +"@loaders.gl/i3s@^4.1.0-alpha.11": + version "4.1.0-alpha.11" + resolved "https://registry.yarnpkg.com/@loaders.gl/i3s/-/i3s-4.1.0-alpha.11.tgz#d0c98b8d63f6583e4d8a246fa5ae32cbb7aef823" + integrity sha512-ydgUfH7MinvNORYYpHTvDK8M+GIKXFP8XU64Xmroetw9ELN8PsmLBPiQB32RXPYay1PfpP8CltKbiTBp5XUxXw== + dependencies: + "@loaders.gl/compression" "4.1.0-alpha.11" + "@loaders.gl/crypto" "4.1.0-alpha.11" + "@loaders.gl/draco" "4.1.0-alpha.11" + "@loaders.gl/images" "4.1.0-alpha.11" + "@loaders.gl/loader-utils" "4.1.0-alpha.11" + "@loaders.gl/schema" "4.1.0-alpha.11" + "@loaders.gl/textures" "4.1.0-alpha.11" + "@loaders.gl/tiles" "4.1.0-alpha.11" "@math.gl/core" "^4.0.0" "@math.gl/culling" "^4.0.0" "@math.gl/geospatial" "^4.0.0" @@ -2316,12 +2360,12 @@ dependencies: "@loaders.gl/loader-utils" "3.2.12" -"@loaders.gl/images@4.0.0-beta.8": - version "4.0.0-beta.8" - resolved "https://registry.yarnpkg.com/@loaders.gl/images/-/images-4.0.0-beta.8.tgz#d7353978b7af08b630d12afb5769ef452e212220" - integrity sha512-6cxAov9sNfrVDvlQ2c1plm5Z8ME5vR320CWCbdVEE1tHP9Zgt/t8/fJ03xXM7ykqQEPQCs8isfrYCBZKQ9/+mA== +"@loaders.gl/images@4.1.0-alpha.11": + version "4.1.0-alpha.11" + resolved "https://registry.yarnpkg.com/@loaders.gl/images/-/images-4.1.0-alpha.11.tgz#79c2bcddd05291ebcb943bb9d47aedaeecc34e91" + integrity sha512-CLXONwuoFXpeWeXbaRbVgZKkZBErrZ1QWX7KHCWnc/Xa4AeXFjMkwhVWh2vh1KYdsVkrz9KBsfn4YHYmg1SWXA== dependencies: - "@loaders.gl/loader-utils" "4.0.0-beta.8" + "@loaders.gl/loader-utils" "4.1.0-alpha.11" "@loaders.gl/loader-utils@3.2.12", "@loaders.gl/loader-utils@^3.2.0": version "3.2.12" @@ -2332,13 +2376,13 @@ "@loaders.gl/worker-utils" "3.2.12" "@probe.gl/stats" "^3.5.0" -"@loaders.gl/loader-utils@4.0.0-beta.8": - version "4.0.0-beta.8" - resolved "https://registry.yarnpkg.com/@loaders.gl/loader-utils/-/loader-utils-4.0.0-beta.8.tgz#137f1924377242524b462f6f4a00f478591001c7" - integrity sha512-pDU3GVSC/X5F8VExz22PhPBTx58SkMkVUcYIw5UGsv+vIi08MQogRNIMxEzMhb5d6BVt+gHdojjtN45iMRqPmw== +"@loaders.gl/loader-utils@4.1.0-alpha.11": + version "4.1.0-alpha.11" + resolved "https://registry.yarnpkg.com/@loaders.gl/loader-utils/-/loader-utils-4.1.0-alpha.11.tgz#fa2475816334a87bfea5e80d9fbfdc4858e92fce" + integrity sha512-1sDFottMYHKrHqJWPl+hxPFpDn0yG0ykUM6j2tv7oBJNPRuvP3Zbk7EJsJIMCqDpqbt5zabko554ttH2iDo8Sw== dependencies: "@babel/runtime" "^7.3.1" - "@loaders.gl/worker-utils" "4.0.0-beta.8" + "@loaders.gl/worker-utils" "4.1.0-alpha.11" "@probe.gl/stats" "^4.0.2" "@loaders.gl/math@3.2.12": @@ -2350,13 +2394,13 @@ "@loaders.gl/loader-utils" "3.2.12" "@math.gl/core" "^3.5.1" -"@loaders.gl/math@4.0.0-beta.8": - version "4.0.0-beta.8" - resolved "https://registry.yarnpkg.com/@loaders.gl/math/-/math-4.0.0-beta.8.tgz#a17ff2b597121e5e80ea08637b8dc90e9bb7ad50" - integrity sha512-T5PB+9jF9SeQyC42oE/jmyoZfnOvyHyCGIHNdcW4Siea+NCZwF0TOtsQIrkrpXZzP8CsUPaIsNUv31UQzzP7IQ== +"@loaders.gl/math@4.1.0-alpha.11": + version "4.1.0-alpha.11" + resolved "https://registry.yarnpkg.com/@loaders.gl/math/-/math-4.1.0-alpha.11.tgz#7ef41e661936d1a362d6de5ce8cd3de5859a44ce" + integrity sha512-VtR9CPdk5nQmqSMEQENXX4LXIZQA9UgO/yHW06xt9qw+4kWu6yafvU3K1Es6OrK5JWrRpelPIalBP9wvEY+bmw== dependencies: - "@loaders.gl/images" "4.0.0-beta.8" - "@loaders.gl/loader-utils" "4.0.0-beta.8" + "@loaders.gl/images" "4.1.0-alpha.11" + "@loaders.gl/loader-utils" "4.1.0-alpha.11" "@math.gl/core" "^4.0.0" "@loaders.gl/mvt@^3.2.0": @@ -2378,10 +2422,10 @@ "@types/geojson" "^7946.0.7" apache-arrow "^4.0.0" -"@loaders.gl/schema@4.0.0-beta.8": - version "4.0.0-beta.8" - resolved "https://registry.yarnpkg.com/@loaders.gl/schema/-/schema-4.0.0-beta.8.tgz#2e3a0588874a61aa782f931f5ff3eaf59daca389" - integrity sha512-BiiF3p4ZWVneUjcYVZ4gO0PQP8n/NuEDTDXiAgptHhzCfnWVkGoV7ec7Ftc+Nsh4b/QHiKqtnRQn/LTWJ1Smog== +"@loaders.gl/schema@4.1.0-alpha.11": + version "4.1.0-alpha.11" + resolved "https://registry.yarnpkg.com/@loaders.gl/schema/-/schema-4.1.0-alpha.11.tgz#cf2705ae11e57c99c5784d5b8161decfe17d774e" + integrity sha512-6mRbpmnlBDR9H8fwJU3gsk9XOwOeD290vqoIgioZrrFmSw9vKovtFOpAUf+ISAwWhW0z+yeECjhVbCux8O3nfw== dependencies: "@types/geojson" "^7946.0.7" @@ -2407,25 +2451,25 @@ ktx-parse "^0.0.4" texture-compressor "^1.0.2" -"@loaders.gl/textures@4.0.0-beta.8": - version "4.0.0-beta.8" - resolved "https://registry.yarnpkg.com/@loaders.gl/textures/-/textures-4.0.0-beta.8.tgz#778c85495336d3ba5df226842d0b8b739126a318" - integrity sha512-4iBxt6vV2nkp8ng2JaVKyCaOM+ibyRhJT/UrIsV3kQRElKy5d+ndkAUhaz1lp503Vw40zNdgGG5pOjYEq+S7jA== +"@loaders.gl/textures@4.1.0-alpha.11": + version "4.1.0-alpha.11" + resolved "https://registry.yarnpkg.com/@loaders.gl/textures/-/textures-4.1.0-alpha.11.tgz#7984f798b684e6392bd9a6ac1b43d232c24e87f9" + integrity sha512-bds00ZQGIS84c5Z4o9wuoP8bpRhLrSi4h0kU2GqmdHt7KLnQcl9JvylqZV90uaQmTssofC8bX8LLQFavigaaYQ== dependencies: - "@loaders.gl/images" "4.0.0-beta.8" - "@loaders.gl/loader-utils" "4.0.0-beta.8" - "@loaders.gl/schema" "4.0.0-beta.8" - "@loaders.gl/worker-utils" "4.0.0-beta.8" + "@loaders.gl/images" "4.1.0-alpha.11" + "@loaders.gl/loader-utils" "4.1.0-alpha.11" + "@loaders.gl/schema" "4.1.0-alpha.11" + "@loaders.gl/worker-utils" "4.1.0-alpha.11" ktx-parse "^0.0.4" texture-compressor "^1.0.2" -"@loaders.gl/tiles@3.2.12", "@loaders.gl/tiles@4.0.0-beta.8", "@loaders.gl/tiles@^3.2.0", "@loaders.gl/tiles@^4.0.0-beta.8": - version "4.0.0-beta.8" - resolved "https://registry.yarnpkg.com/@loaders.gl/tiles/-/tiles-4.0.0-beta.8.tgz#e7e5437016fef3236083f0a7c284d2720d2624b4" - integrity sha512-pisZklKEQ3uE/W8apACkqbckVT9JzjbOcCbIs+5wdwPf10O+7msnP7s4QHBYVhkN+LB5m/RGWKIytUn7KV/jsA== +"@loaders.gl/tiles@3.2.12", "@loaders.gl/tiles@4.1.0-alpha.11", "@loaders.gl/tiles@^3.2.0", "@loaders.gl/tiles@^4.1.0-alpha.11": + version "4.1.0-alpha.11" + resolved "https://registry.yarnpkg.com/@loaders.gl/tiles/-/tiles-4.1.0-alpha.11.tgz#cce23207c327fa02d224cadc829b36c40db56de1" + integrity sha512-rCS4mnsY0CrNhtCij15zxau/P67BFo/B9xy46ZDRlJ1XPC4HDR5LBP33IAAhD/ClqEYP15eeQRxHyQ6HjsD4DQ== dependencies: - "@loaders.gl/loader-utils" "4.0.0-beta.8" - "@loaders.gl/math" "4.0.0-beta.8" + "@loaders.gl/loader-utils" "4.1.0-alpha.11" + "@loaders.gl/math" "4.1.0-alpha.11" "@math.gl/core" "^4.0.0" "@math.gl/culling" "^4.0.0" "@math.gl/geospatial" "^4.0.0" @@ -2439,21 +2483,21 @@ dependencies: "@babel/runtime" "^7.3.1" -"@loaders.gl/worker-utils@4.0.0-beta.8": - version "4.0.0-beta.8" - resolved "https://registry.yarnpkg.com/@loaders.gl/worker-utils/-/worker-utils-4.0.0-beta.8.tgz#8d5a33b1b8da8215f30bfba8a7f83b5323787caf" - integrity sha512-0sIIUXVPcOXdv+4Rz99FR7iUnKjQpT50c0tvHiapr4b2USqxjJmGAepF3azhXGdiS4RadglCBZLm2xxxZiv0EA== +"@loaders.gl/worker-utils@4.1.0-alpha.11": + version "4.1.0-alpha.11" + resolved "https://registry.yarnpkg.com/@loaders.gl/worker-utils/-/worker-utils-4.1.0-alpha.11.tgz#48916d93afaf0b0d7a521b4dacb73d9b887ed420" + integrity sha512-GbW+d6L2Shfv4z7Pn9pR61U9y3CVu570JQjiEdzbFS+sQOLZBH+LC5eX+i1MBwtiUDvqjSp0Pm0Ch9bToyYosw== dependencies: "@babel/runtime" "^7.3.1" -"@loaders.gl/zip@4.0.0-beta.8": - version "4.0.0-beta.8" - resolved "https://registry.yarnpkg.com/@loaders.gl/zip/-/zip-4.0.0-beta.8.tgz#c5238bd6bec38c9d29d02d5eb81474e7ed2f7ab9" - integrity sha512-aiB3Z7LNTJ9im2W55SvyH2++5qH6VRE1PxdNDwmbj82aEy5o7LSHMQAD2oeqYWePMUWVU5FXh6HKkp3/Tn+K2w== +"@loaders.gl/zip@4.1.0-alpha.11": + version "4.1.0-alpha.11" + resolved "https://registry.yarnpkg.com/@loaders.gl/zip/-/zip-4.1.0-alpha.11.tgz#cd17ec3c7e1e804eeb075b2af9446707ef740dfc" + integrity sha512-OB9nYgm46hZK9zg1dNx/C0tiiW3+axEIPFUFsS/fjLZ1qy88+9Cv3Z7gVWs22+76rmCJLiFvOy7xc462BuhM7Q== dependencies: - "@loaders.gl/compression" "4.0.0-beta.8" - "@loaders.gl/crypto" "4.0.0-beta.8" - "@loaders.gl/loader-utils" "4.0.0-beta.8" + "@loaders.gl/compression" "4.1.0-alpha.11" + "@loaders.gl/crypto" "4.1.0-alpha.11" + "@loaders.gl/loader-utils" "4.1.0-alpha.11" jszip "^3.1.5" md5 "^2.3.0" @@ -4903,6 +4947,11 @@ d3-shape@^3.1.0: dependencies: d3-array "2 - 3" +data-uri-to-buffer@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz#d8feb2b2881e6a4f58c2e08acfd0e2834e26222e" + integrity sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A== + data-urls@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-2.0.0.tgz#156485a72963a970f5d5821aaf642bef2bf2db9b" @@ -5614,6 +5663,14 @@ fd-slicer@~1.1.0: dependencies: pend "~1.2.0" +fetch-blob@^3.1.2, fetch-blob@^3.1.4: + version "3.2.0" + resolved "https://registry.yarnpkg.com/fetch-blob/-/fetch-blob-3.2.0.tgz#f09b8d4bbd45adc6f0c20b7e787e793e309dcce9" + integrity sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ== + dependencies: + node-domexception "^1.0.0" + web-streams-polyfill "^3.0.3" + fflate@0.7.4: version "0.7.4" resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.7.4.tgz#61587e5d958fdabb5a9368a302c25363f4f69f50" @@ -5756,6 +5813,21 @@ form-data@^3.0.0: combined-stream "^1.0.8" mime-types "^2.1.12" +formdata-node@^4.1.0: + version "4.4.1" + resolved "https://registry.yarnpkg.com/formdata-node/-/formdata-node-4.4.1.tgz#23f6a5cb9cb55315912cbec4ff7b0f59bbd191e2" + integrity sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ== + dependencies: + node-domexception "1.0.0" + web-streams-polyfill "4.0.0-beta.3" + +formdata-polyfill@^4.0.10: + version "4.0.10" + resolved "https://registry.yarnpkg.com/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz#24807c31c9d402e002ab3d8c720144ceb8848423" + integrity sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g== + dependencies: + fetch-blob "^3.1.2" + forwarded@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" @@ -7440,6 +7512,11 @@ minimist@^1.2.0, minimist@^1.2.5: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== +mitt@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/mitt/-/mitt-3.0.1.tgz#ea36cf0cc30403601ae074c8f77b7092cdab36d1" + integrity sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw== + mixin-object@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/mixin-object/-/mixin-object-2.0.1.tgz#4fb949441dab182540f1fe035ba60e1947a5e57e" @@ -7559,6 +7636,11 @@ no-case@^3.0.4: lower-case "^2.0.2" tslib "^2.0.3" +node-domexception@1.0.0, node-domexception@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" + integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ== + node-fetch@2.6.7, node-fetch@^2.6.5: version "2.6.7" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" @@ -7566,6 +7648,15 @@ node-fetch@2.6.7, node-fetch@^2.6.5: dependencies: whatwg-url "^5.0.0" +node-fetch@^3.0.0: + version "3.3.2" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-3.3.2.tgz#d1e889bacdf733b4ff3b2b243eb7a12866a0b78b" + integrity sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA== + dependencies: + data-uri-to-buffer "^4.0.0" + fetch-blob "^3.1.4" + formdata-polyfill "^4.0.10" + node-forge@^1.2.0: version "1.2.1" resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.2.1.tgz#82794919071ef2eb5c509293325cec8afd0fd53c" @@ -9335,7 +9426,7 @@ ts-loader@^9.2.6: micromatch "^4.0.0" semver "^7.3.4" -tslib@^1.8.1: +tslib@^1.13.0, tslib@^1.8.1: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== @@ -9345,6 +9436,11 @@ tslib@^2.0.3, tslib@^2.1.0, tslib@^2.2.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01" integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== +tslib@^2.3.0, tslib@^2.3.1: + version "2.6.2" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" + integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== + tsutils@^3.21.0: version "3.21.0" resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" @@ -9586,6 +9682,16 @@ wbuf@^1.1.0, wbuf@^1.7.3: dependencies: minimalistic-assert "^1.0.0" +web-streams-polyfill@4.0.0-beta.3: + version "4.0.0-beta.3" + resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz#2898486b74f5156095e473efe989dcf185047a38" + integrity sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug== + +web-streams-polyfill@^3.0.3: + version "3.3.2" + resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.3.2.tgz#32e26522e05128203a7de59519be3c648004343b" + integrity sha512-3pRGuxRF5gpuZc0W+EpwQRmCD7gRqcDOMt688KmdlDAgAyaB1XlN0zq2njfDNm44XVdIouE7pZ6GzbdyH47uIQ== + webidl-conversions@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" From 3ff95ee39f2b667c66f0f288363fea9c75fb9af8 Mon Sep 17 00:00:00 2001 From: mspivak-actionengine <118991512+mspivak-actionengine@users.noreply.github.com> Date: Mon, 19 Feb 2024 14:19:46 +0300 Subject: [PATCH 24/40] fix(debug-texture): crop uv texture (#351) --- .../deck-gl-wrapper/deck-gl-wrapper.spec.tsx | 16 +- .../deck-gl-wrapper/deck-gl-wrapper.tsx | 8 +- .../debug/texture-selector-utils.spec.ts | 156 +++++++++++++----- src/utils/debug/texture-selector-utils.ts | 90 ++++++++-- 4 files changed, 209 insertions(+), 61 deletions(-) diff --git a/src/components/deck-gl-wrapper/deck-gl-wrapper.spec.tsx b/src/components/deck-gl-wrapper/deck-gl-wrapper.spec.tsx index 479e0216..a7c095b4 100644 --- a/src/components/deck-gl-wrapper/deck-gl-wrapper.spec.tsx +++ b/src/components/deck-gl-wrapper/deck-gl-wrapper.spec.tsx @@ -396,14 +396,14 @@ describe("Deck.gl I3S map component", () => { }); }); - it("Should call Tile3DLayer tileset callbacks", () => { + it("Should call Tile3DLayer tileset callbacks", async () => { const { rerender } = callRender(renderWithProvider); expect(CustomTile3DLayer).toHaveBeenCalled(); const { onTileLoad, onTilesetLoad, onTileUnload } = ( CustomTile3DLayer as any ).mock.lastCall[0]; const tile3d = getTile3d(); - act(() => onTileLoad(tile3d)); + await act(() => onTileLoad(tile3d)); expect(simpleCallbackMock).toHaveBeenCalledTimes(1); // TODO: couldn't mock MapView.ViewportType. expect toThrow instead @@ -418,7 +418,7 @@ describe("Deck.gl I3S map component", () => { callRender(rerender, { onTileLoad: undefined }); const { onTileLoad: onTileLoad2 } = (CustomTile3DLayer as any).mock .lastCall[0]; - act(() => onTileLoad2(tile3d)); + await act(() => onTileLoad2(tile3d)); expect(simpleCallbackMock).toHaveBeenCalledTimes(2); callRender(rerender, { onTileUnload: undefined }); @@ -448,24 +448,24 @@ describe("Deck.gl I3S map component", () => { }); }); - it("Should remove featureIds", () => { + it("Should remove featureIds", async () => { callRender(renderWithProvider, { featurePicking: false }); expect(CustomTile3DLayer).toHaveBeenCalled(); const { onTileLoad } = (CustomTile3DLayer as any).mock.lastCall[0]; const tile3d = getTile3d(); tile3d.content.featureIds = new Uint32Array([10, 20, 30]); - act(() => onTileLoad(tile3d)); + await act(() => onTileLoad(tile3d)); expect(tile3d.content.featureIds).toBeFalsy(); }); - it("Should update debug texture on a tile", () => { + it("Should update debug texture on a tile", async () => { const store = setupStore(); store.dispatch(setDebugOptions({ showUVDebugTexture: false })); const { rerender } = callRender(renderWithProvider, undefined, store); expect(CustomTile3DLayer).toHaveBeenCalled(); const { onTileLoad } = (CustomTile3DLayer as any).mock.lastCall[0]; const tile3d = getTile3d(); - act(() => onTileLoad(tile3d)); + await act(() => onTileLoad(tile3d)); expect(selectOriginalTextureForTile).toHaveBeenCalledWith(tile3d); expect(selectDebugTextureForTile).not.toHaveBeenCalled(); @@ -473,7 +473,7 @@ describe("Deck.gl I3S map component", () => { callRender(rerender, undefined, store); const { onTileLoad: onTileLoadSecond } = (CustomTile3DLayer as any).mock .lastCall[0]; - act(() => onTileLoadSecond(tile3d)); + await act(() => onTileLoadSecond(tile3d)); expect(selectDebugTextureForTile).toHaveBeenCalledWith(tile3d, null); expect(selectOriginalTextureForTile).toHaveBeenCalledTimes(1); }); diff --git a/src/components/deck-gl-wrapper/deck-gl-wrapper.tsx b/src/components/deck-gl-wrapper/deck-gl-wrapper.tsx index a6901a2b..5b4932e1 100644 --- a/src/components/deck-gl-wrapper/deck-gl-wrapper.tsx +++ b/src/components/deck-gl-wrapper/deck-gl-wrapper.tsx @@ -326,9 +326,9 @@ export const DeckGlWrapper = ({ }, [loadTiles]); useEffect(() => { - loadedTilesets.forEach((tileset) => { + loadedTilesets.forEach(async (tileset) => { if (showDebugTexture) { - selectDebugTextureForTileset(tileset, uvDebugTexture); + await selectDebugTextureForTileset(tileset, uvDebugTexture); } else { selectOriginalTextureForTileset(); } @@ -489,13 +489,13 @@ export const DeckGlWrapper = ({ onTilesetLoad(tileset); }; - const onTileLoadHandler = (tile) => { + const onTileLoadHandler = async (tile) => { if (!featurePicking) { // delete featureIds from data to have instance picking instead of feature picking delete tile.content.featureIds; } if (showDebugTextureRef.current) { - selectDebugTextureForTile(tile, uvDebugTextureRef.current); + await selectDebugTextureForTile(tile, uvDebugTextureRef.current); } else { selectOriginalTextureForTile(tile); } diff --git a/src/utils/debug/texture-selector-utils.spec.ts b/src/utils/debug/texture-selector-utils.spec.ts index 9debdafd..355cc37f 100644 --- a/src/utils/debug/texture-selector-utils.spec.ts +++ b/src/utils/debug/texture-selector-utils.spec.ts @@ -4,19 +4,93 @@ import { selectDebugTextureForTile, selectOriginalTextureForTile, } from "./texture-selector-utils"; +import type { Tile3D, Tileset3D } from "@loaders.gl/tiles"; + +const mockDrawImage = jest.fn(); + +Object.defineProperty(window, "createImageBitmap", { + writable: true, + value: jest.fn().mockImplementation(() => ({})), +}); + +Object.defineProperty(window, "ImageBitmap", { + writable: true, + value: jest + .fn() + .mockImplementation((name, width, height) => ({ + name: name, + width: width, + height: height, + })), +}); + +class MyImageBitmap extends ImageBitmap { + name: string; + width: number; + height: number; + constructor(name: string, width: number, height: number) { + super(); + this.name = name; + this.width = width; + this.height = height; + } +} + +const contentTexture: ImageBitmap = new MyImageBitmap("c", 0, 0); +const uvDebugTexture: ImageBitmap = new MyImageBitmap("uv", 0, 0); + +describe("Crop texture", () => { + beforeAll(() => { + HTMLCanvasElement.prototype.getContext = jest.fn().mockReturnValue({ + drawImage: mockDrawImage, + }); + }); + + test("Should crop texture", async () => { + const contentTexture: ImageBitmap = new MyImageBitmap("c", 1, 1); + const uvDebugTexture: ImageBitmap = new MyImageBitmap("uv", 2, 2); + + const tile = { + userData: { + originalTexture: null, + }, + content: { + material: { + pbrMetallicRoughness: { + baseColorTexture: { + texture: { + source: { + image: contentTexture, + }, + }, + }, + }, + texture: uvDebugTexture, + }, + }, + }; + await selectDebugTextureForTile(tile as unknown as Tile3D, uvDebugTexture); + expect(mockDrawImage).toBeCalledTimes(1); + }); +}); describe("Texture Selector Utils - selectDebugTextureForTileset", () => { - test("Should return undefined if no uvDebugTexture", () => { + test("Should return undefined if no uvDebugTexture", async () => { const tileset = {}; const uvDebugTexture = null; - const result = selectDebugTextureForTileset(tileset, uvDebugTexture); + const result = await selectDebugTextureForTileset( + tileset as unknown as Tileset3D, + uvDebugTexture + ); expect(result).toBeUndefined(); }); - test("Should return undefined if no uvDebugTexture", () => { + test("Should return undefined if no uvDebugTexture", async () => { const tileset = { tiles: [{ userData: {} }] }; - const uvDebugTexture = "Test texture"; - selectDebugTextureForTileset(tileset, uvDebugTexture); + await selectDebugTextureForTileset( + tileset as unknown as Tileset3D, + uvDebugTexture + ); }); }); @@ -27,21 +101,26 @@ describe("Texture Selector Utils - selectOriginalTextureForTileset", () => { }); describe("Texture Selector Utils - selectDebugTextureForTile", () => { - test("Should return undefined if no uvDebugTexture", () => { + test("Should return undefined if no uvDebugTexture", async () => { const tile = { userData: {} }; const uvDebugTexture = null; - const result = selectDebugTextureForTile(tile, uvDebugTexture); + const result = await selectDebugTextureForTile( + tile as unknown as Tile3D, + uvDebugTexture + ); expect(result).toBeUndefined(); }); - test("Should return undefined if originalTexture exists", () => { + test("Should return undefined if originalTexture exists", async () => { const tile = { userData: { originalTexture: "Test texture" } }; - const uvDebugTexture = "Test texture"; - const result = selectDebugTextureForTile(tile, uvDebugTexture); + const result = await selectDebugTextureForTile( + tile as unknown as Tile3D, + uvDebugTexture + ); expect(result).toBeUndefined(); }); - test("Should return undefined if material exists but baseColorTexture is not", () => { + test("Should return undefined if material exists but baseColorTexture is not", async () => { const tile = { userData: {}, content: { @@ -52,12 +131,14 @@ describe("Texture Selector Utils - selectDebugTextureForTile", () => { }, }, }; - const uvDebugTexture = "Test texture"; - const result = selectDebugTextureForTile(tile, uvDebugTexture); + const result = await selectDebugTextureForTile( + tile as unknown as Tile3D, + uvDebugTexture + ); expect(result).toBeUndefined(); }); - test("Should add original texture to userData and apply debug texture", () => { + test("Should add original texture to userData and apply debug texture", async () => { const tile = { userData: { originalTexture: null, @@ -68,25 +149,24 @@ describe("Texture Selector Utils - selectDebugTextureForTile", () => { baseColorTexture: { texture: { source: { - image: "Testing Image", + image: contentTexture, }, }, }, }, - texture: "Test texture", + texture: uvDebugTexture, }, }, }; - const uvDebugTexture = "Test texture"; - selectDebugTextureForTile(tile, uvDebugTexture); - expect(tile.userData.originalTexture).toStrictEqual("Testing Image"); + await selectDebugTextureForTile(tile as unknown as Tile3D, uvDebugTexture); + expect(tile.userData.originalTexture).toStrictEqual(contentTexture); expect( tile.content.material.pbrMetallicRoughness.baseColorTexture.texture.source .image - ).toStrictEqual("Test texture"); + ).toStrictEqual(uvDebugTexture); }); - test("Should skip adding original texture to userData if already exist and apply debug texture", () => { + test("Should skip adding original texture to userData if already exist and apply debug texture", async () => { const tile = { userData: { originalTexture: { @@ -95,12 +175,12 @@ describe("Texture Selector Utils - selectDebugTextureForTile", () => { baseColorTexture: { texture: { source: { - image: "Testing Image", + image: contentTexture, }, }, }, }, - texture: "Test texture", + texture: uvDebugTexture, }, }, }, @@ -110,41 +190,39 @@ describe("Texture Selector Utils - selectDebugTextureForTile", () => { baseColorTexture: { texture: { source: { - image: "Testing Image", + image: contentTexture, }, }, }, }, - texture: "Test texture", + texture: uvDebugTexture, }, }, }; - const uvDebugTexture = "Test texture"; - selectDebugTextureForTile(tile, uvDebugTexture); + await selectDebugTextureForTile(tile as unknown as Tile3D, uvDebugTexture); expect( tile.userData.originalTexture.material.pbrMetallicRoughness .baseColorTexture.texture.source.image - ).toStrictEqual("Testing Image"); + ).toStrictEqual(contentTexture); expect( tile.content.material.pbrMetallicRoughness.baseColorTexture.texture.source .image - ).toStrictEqual("Test texture"); + ).toStrictEqual(uvDebugTexture); }); - test("Should add original texture to userData and apply debug texture if no material", () => { + test("Should add original texture to userData and apply debug texture if no material", async () => { const tile = { userData: { originalTexture: null, }, content: { material: null, - texture: "Test texture", + texture: contentTexture, }, }; - const uvDebugTexture = "uvDebugTexture"; - selectDebugTextureForTile(tile, uvDebugTexture); - expect(tile.userData.originalTexture).toStrictEqual("Test texture"); - expect(tile.content.texture).toStrictEqual("uvDebugTexture"); + await selectDebugTextureForTile(tile as unknown as Tile3D, uvDebugTexture); + expect(tile.userData.originalTexture).toStrictEqual(contentTexture); + expect(tile.content.texture).toStrictEqual(uvDebugTexture); }); }); @@ -159,7 +237,7 @@ describe("Texture Selector Utils - selectOriginalTextureForTile", () => { texture: "Test texture", }, }; - const result = selectOriginalTextureForTile(tile); + const result = selectOriginalTextureForTile(tile as unknown as Tile3D); expect(result).toBeUndefined(); }); @@ -178,7 +256,7 @@ describe("Texture Selector Utils - selectOriginalTextureForTile", () => { texture: "Test texture", }, }; - const result = selectOriginalTextureForTile(tile); + const result = selectOriginalTextureForTile(tile as unknown as Tile3D); expect(result).toBeUndefined(); }); @@ -202,7 +280,7 @@ describe("Texture Selector Utils - selectOriginalTextureForTile", () => { }, }, }; - selectOriginalTextureForTile(tile); + selectOriginalTextureForTile(tile as unknown as Tile3D); expect( tile.content.material.pbrMetallicRoughness.baseColorTexture.texture.source .image @@ -220,7 +298,7 @@ describe("Texture Selector Utils - selectOriginalTextureForTile", () => { texture: "Test texture", }, }; - selectOriginalTextureForTile(tile); + selectOriginalTextureForTile(tile as unknown as Tile3D); expect(tile.content.texture).toStrictEqual("Original Texture"); expect(tile.userData.originalTexture).toBeUndefined(); }); diff --git a/src/utils/debug/texture-selector-utils.ts b/src/utils/debug/texture-selector-utils.ts index 964bbcfb..7494c56b 100644 --- a/src/utils/debug/texture-selector-utils.ts +++ b/src/utils/debug/texture-selector-utils.ts @@ -1,18 +1,28 @@ +import type { Tile3D, Tileset3D } from "@loaders.gl/tiles"; + // TODO Need to separate multiple export functions from file and split logic for better testing // The tiles list in the tileset mutates continually. // We need to store tiles when we replace texture -const tiles = {}; +const tiles: Record = {}; -export function selectDebugTextureForTileset(tileset, uvDebugTexture) { +/** + * Replaces original textures in the tileset with uvDebug texture + * @param tileset Tileset where textures should be replaced + * @param uvDebugTexture uvDebug texture + */ +export async function selectDebugTextureForTileset( + tileset: Tileset3D, + uvDebugTexture: ImageBitmap | null +) { if (!uvDebugTexture) { return; } for (const tile of tileset.tiles) { - selectDebugTextureForTile(tile, uvDebugTexture); + await selectDebugTextureForTile(tile as Tile3D, uvDebugTexture); } for (const tileId in tiles) { - selectDebugTextureForTile(tiles[tileId], uvDebugTexture); + await selectDebugTextureForTile(tiles[tileId], uvDebugTexture); } } @@ -22,7 +32,50 @@ export function selectOriginalTextureForTileset() { } } -export function selectDebugTextureForTile(tile, uvDebugTexture) { +/** + * Crops the texture with the specified width and height + * @param texture - Texture to crop + * @param width - width of the cropped texture + * @param height - height of the cropped texture + * @returns cropped texture + */ +const cropTexture = async ( + texture: ImageBitmap, + width: number, + height: number +) => { + if (!width || !height) { + return texture; + } + const bitmap = await createImageBitmap(texture); + + const coeffWidth = texture.width / width; + const coeffHeight = texture.height / height; + const coeff = coeffWidth < coeffHeight ? coeffWidth : coeffHeight; + const sw = width * coeff; + const sh = height * coeff; + + const canvas = document.createElement("canvas"); + canvas.width = sw; + canvas.height = sh; + const ctx = canvas.getContext("2d"); + if (!ctx) { + return null; + } + + ctx.drawImage(bitmap, 0, 0, sw, sh); + return canvas; +}; + +/** + * Replaces original textures in the tile with uvDebug texture + * @param tile - Tile where textures should be replaced + * @param uvDebugTexture uvDebug texture + */ +export async function selectDebugTextureForTile( + tile: Tile3D, + uvDebugTexture: ImageBitmap | null +) { tiles[tile.id] = tile; if (!uvDebugTexture) { return; @@ -31,7 +84,6 @@ export function selectDebugTextureForTile(tile, uvDebugTexture) { if (material) { if ( !( - material && material.pbrMetallicRoughness && material.pbrMetallicRoughness.baseColorTexture ) @@ -42,18 +94,37 @@ export function selectDebugTextureForTile(tile, uvDebugTexture) { tile.userData.originalTexture = material.pbrMetallicRoughness.baseColorTexture.texture.source.image; } + const width = tile.userData.originalTexture.width; + const height = tile.userData.originalTexture.height; + const uvDebugTextureCropped = await cropTexture( + uvDebugTexture, + width, + height + ); material.pbrMetallicRoughness.baseColorTexture.texture.source.image = - uvDebugTexture; + uvDebugTextureCropped; tile.content.material = { ...tile.content.material }; } else if (texture) { if (!tile.userData.originalTexture) { tile.userData.originalTexture = texture; } - tile.content.texture = uvDebugTexture; + + const width = texture.width; + const height = texture.height; + const uvDebugTextureCropped = await cropTexture( + uvDebugTexture, + width, + height + ); + tile.content.texture = uvDebugTextureCropped; } } -export function selectOriginalTextureForTile(tile) { +/** + * Replaces uvDebug texture in the tile back with original ones + * @param tile - Tile where textures should be replaced + */ +export function selectOriginalTextureForTile(tile: Tile3D) { tiles[tile.id] = tile; const { content, @@ -66,7 +137,6 @@ export function selectOriginalTextureForTile(tile) { if (material) { if ( !( - material && material.pbrMetallicRoughness && material.pbrMetallicRoughness.baseColorTexture ) From 78e30e7d0579093be7344cc19725905b187ffecb Mon Sep 17 00:00:00 2001 From: mspivak-actionengine <118991512+mspivak-actionengine@users.noreply.github.com> Date: Mon, 19 Feb 2024 14:23:50 +0300 Subject: [PATCH 25/40] use new terrain texture source (#353) --- src/components/deck-gl-wrapper/deck-gl-wrapper.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/deck-gl-wrapper/deck-gl-wrapper.tsx b/src/components/deck-gl-wrapper/deck-gl-wrapper.tsx index 5b4932e1..7948adcc 100644 --- a/src/components/deck-gl-wrapper/deck-gl-wrapper.tsx +++ b/src/components/deck-gl-wrapper/deck-gl-wrapper.tsx @@ -82,8 +82,8 @@ const INITIAL_VIEW_STATE = { // https://github.com/tilezen/joerd/blob/master/docs/use-service.md#additional-amazon-s3-endpoints const MAPZEN_TERRAIN_IMAGES = `https://s3.amazonaws.com/elevation-tiles-prod/terrarium/{z}/{x}/{y}.png`; -const ARCGIS_STREET_MAP_SURFACE_IMAGES = - "https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}"; +const TERRAIN_TEXTURE = "https://tile.openstreetmap.org/{z}/{x}/{y}.png"; + const MAPZEN_ELEVATION_DECODE_PARAMETERS = { rScaler: 256, gScaler: 1, @@ -707,7 +707,7 @@ export const DeckGlWrapper = ({ maxZoom: TERRAIN_LAYER_MAX_ZOOM, elevationDecoder: MAPZEN_ELEVATION_DECODE_PARAMETERS, elevationData: MAPZEN_TERRAIN_IMAGES, - texture: ARCGIS_STREET_MAP_SURFACE_IMAGES, + texture: TERRAIN_TEXTURE, onTileLoad: (tile) => onTerrainTileLoad(tile), color: [255, 255, 255], }); From b163c806a33a767d10ba7e12a58b08b803785591 Mon Sep 17 00:00:00 2001 From: mspivak-actionengine <118991512+mspivak-actionengine@users.noreply.github.com> Date: Mon, 19 Feb 2024 15:36:01 +0300 Subject: [PATCH 26/40] fix(tileset-example): fix tileset version (#354) --- .../layers-panel/list-item-wrapper/list-item-wrapper.spec.tsx | 2 +- src/constants/i3s-examples.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/layers-panel/list-item-wrapper/list-item-wrapper.spec.tsx b/src/components/layers-panel/list-item-wrapper/list-item-wrapper.spec.tsx index 0a8e2142..02690fff 100644 --- a/src/components/layers-panel/list-item-wrapper/list-item-wrapper.spec.tsx +++ b/src/components/layers-panel/list-item-wrapper/list-item-wrapper.spec.tsx @@ -19,7 +19,7 @@ describe("List Item Wrapper", () => { onClick={onChange} optionsContent={
{"Hello world"}
} > - San Francisco v1.6 + San Francisco v1.8 ); const optionsIcon = document.querySelector("#test-id"); diff --git a/src/constants/i3s-examples.ts b/src/constants/i3s-examples.ts index 3a4e2ea5..fb630cbc 100644 --- a/src/constants/i3s-examples.ts +++ b/src/constants/i3s-examples.ts @@ -15,8 +15,8 @@ export const INITIAL_EXAMPLE: LayerExample = { export const EXAMPLES: LayerExample[] = [ { - id: "san-francisco-v1_6", - name: "San Francisco v1.6", + id: "san-francisco-v1_8", + name: "San Francisco v1.8", url: "https://tiles.arcgis.com/tiles/z2tnIkrLQ2BRzr6P/arcgis/rest/services/SanFrancisco_Bldgs/SceneServer/layers/0", type: TilesetType.I3S, mapInfo: 'https://www.arcgis.com/home/item.html?id=d3344ba99c3f4efaa909ccfbcc052ed5' From 2e313fa16246c72a60e22d462a83e496cf90a589 Mon Sep 17 00:00:00 2001 From: mspivak-actionengine <118991512+mspivak-actionengine@users.noreply.github.com> Date: Tue, 20 Feb 2024 12:12:25 +0300 Subject: [PATCH 27/40] feat(tile-inspector): show original texture (#349) --- src/components/modal-dialog/modal-dialog.tsx | 33 +- .../texture-section.spec.tsx | 30 ++ .../tile-details-panel/texture-section.tsx | 140 ++++++++ .../tile-details-panel/tile-details-panel.tsx | 4 +- src/utils/debug/texture-render-utils.spec.ts | 31 ++ src/utils/debug/texture-render-utils.ts | 324 ++++++++++++++++++ 6 files changed, 549 insertions(+), 13 deletions(-) create mode 100644 src/components/tile-details-panel/texture-section.spec.tsx create mode 100644 src/components/tile-details-panel/texture-section.tsx create mode 100644 src/utils/debug/texture-render-utils.spec.ts create mode 100644 src/utils/debug/texture-render-utils.ts diff --git a/src/components/modal-dialog/modal-dialog.tsx b/src/components/modal-dialog/modal-dialog.tsx index c25df8d8..cffc26cb 100644 --- a/src/components/modal-dialog/modal-dialog.tsx +++ b/src/components/modal-dialog/modal-dialog.tsx @@ -79,7 +79,7 @@ const ButtonsContainer = styled.div` display: flex; flex-direction: row; justify-content: ${(props) => props.justify}; - margin: 32px; + margin: 32px 32px 0 32px; column-gap: 18px; { > * { @@ -88,6 +88,10 @@ const ButtonsContainer = styled.div` } `; +const AfterButtonsPlaceholder = styled.div` + margin: 0 32px 32px 32px; +`; + type LogoutPanelProps = { title: string; children: JSX.Element | JSX.Element[]; @@ -125,17 +129,22 @@ export const ModalDialog = ({ {title} {children} - - {cancelButtonText && ( - - {cancelButtonText} - - )} - {okButtonText} - + {(cancelButtonText || okButtonText) && ( + + {cancelButtonText && ( + + {cancelButtonText} + + )} + {okButtonText && ( + {okButtonText} + )} + + )} +
diff --git a/src/components/tile-details-panel/texture-section.spec.tsx b/src/components/tile-details-panel/texture-section.spec.tsx new file mode 100644 index 00000000..bf869e41 --- /dev/null +++ b/src/components/tile-details-panel/texture-section.spec.tsx @@ -0,0 +1,30 @@ +import { renderWithTheme } from "../../utils/testing-utils/render-with-theme"; +import { TextureSection } from "./texture-section"; +import { getTile3d } from "../../test/tile-stub"; +import { screen } from "@testing-library/react"; +import userEvent from "@testing-library/user-event"; + +let tile3d; +beforeEach(() => { + tile3d = getTile3d(); +}); + +const callRender = (renderFunc, props = {}) => { + return renderFunc(); +}; + +describe("Texture Section", () => { + it("Should render texture section", async () => { + const { container } = callRender(renderWithTheme); + expect(container.firstChild).toBeInTheDocument(); + + const texturePanel = await screen.findByText("Texture:"); + expect(texturePanel).toBeInTheDocument(); + + const texture = texturePanel?.nextSibling as Element; + texture && userEvent.click(texture); + + const texturePreview = await screen.findByText("Preview texture"); + expect(texturePreview).toBeInTheDocument(); + }); +}); diff --git a/src/components/tile-details-panel/texture-section.tsx b/src/components/tile-details-panel/texture-section.tsx new file mode 100644 index 00000000..60122200 --- /dev/null +++ b/src/components/tile-details-panel/texture-section.tsx @@ -0,0 +1,140 @@ +import styled from "styled-components"; +import { Title, TileInfoSectionWrapper } from "../common"; +import { useEffect, useState } from "react"; +import { Tile3D } from "@loaders.gl/tiles"; +import { ModalDialog } from "../modal-dialog/modal-dialog"; + +import { + drawCompressedTexture, + drawBitmapTexture, +} from "../../utils/debug/texture-render-utils"; + +type Size = { + width: number; + height: number; +}; + +const TextureContainer = styled.div` + display: flex; + justify-content: center; + align-items: top; + border-radius: 4px; + margin-right: 16px; + cursor: pointer; +`; + +const TextureButton = styled.button<{ + image: string; + width: number; + height: number; +}>` + height: ${({ height }) => `${height}px`}; + width: ${({ width }) => `${width}px`}; + position: relative; + margin: 0; + border: 0; + background-image: ${({ image }) => `${image}`}; + background-repeat: no-repeat; + cursor: inherit; +`; + +const SIZE = 149; +const PREVIEW_SIZE = 592; + +type TextureSectionProps = { + tile: Tile3D; +}; + +export const TextureSection = ({ tile }: TextureSectionProps) => { + const [texture, setTexture] = useState(""); + const [previewTexture, setPreviewTexture] = useState(""); + const [showPreviewTexture, setShowPreviewTexture] = useState(false); + + const [size, setSize] = useState({ + width: SIZE, + height: SIZE, + }); + const [previewSize, setPreviewSize] = useState({ + width: PREVIEW_SIZE, + height: PREVIEW_SIZE, + }); + + const contentImage = + tile.content?.material?.pbrMetallicRoughness?.baseColorTexture?.texture + ?.source?.image; + const originalTexture = tile.userData?.originalTexture; + const image = originalTexture || contentImage; + + useEffect(() => { + if (image) { + if (image.compressed) { + drawCompressedTexture(image, SIZE).then((result) => { + const { url, width, height } = result; + setSize({ width, height }); + setTexture(url); + }); + } else { + drawBitmapTexture(image, SIZE).then((result) => { + const { url, width, height } = result; + setSize({ width: width, height: height }); + setTexture(url); + }); + } + } + }, [image]); + + const onClickHandler = () => { + if (image) { + if (image.compressed) { + drawCompressedTexture(image, PREVIEW_SIZE).then((result) => { + const { url, width, height } = result; + setPreviewSize({ width: width, height: height }); + setPreviewTexture(url); + }); + } else { + drawBitmapTexture(image, PREVIEW_SIZE).then((result) => { + const { url, width, height } = result; + setPreviewSize({ width: width, height: height }); + setPreviewTexture(url); + }); + } + } + + setShowPreviewTexture(true); + }; + + return ( + <> + + Texture: + + + + + + {showPreviewTexture && ( + { + setShowPreviewTexture(false); + }} + onCancel={() => { + setShowPreviewTexture(false); + }} + > + + + )} + + ); +}; diff --git a/src/components/tile-details-panel/tile-details-panel.tsx b/src/components/tile-details-panel/tile-details-panel.tsx index f4dc7aa6..24f959af 100644 --- a/src/components/tile-details-panel/tile-details-panel.tsx +++ b/src/components/tile-details-panel/tile-details-panel.tsx @@ -24,6 +24,7 @@ import { formatStringValue, } from "../../utils/format/format-utils"; import { getBoundingType } from "../../utils/debug/bounding-volume"; +import { TextureSection } from "./texture-section"; enum ActiveTileInfoPanel { TileDetailsPanel, @@ -162,7 +163,7 @@ export const TileDetailsPanel = ({ lodMetricType, lodMetricValue, screenSpaceError, - depth + depth, } = tile; const childrenInfo = getChildrenInfo(tileChildren); @@ -411,6 +412,7 @@ export const TileDetailsPanel = ({ {children} + ({})), +}); + +Object.defineProperty(window, "ImageBitmap", { + writable: true, + value: jest.fn().mockImplementation((name) => ({ name: name })), +}); + +describe("Texture Selector Utils - selectDebugTextureForTileset", () => { + beforeAll(() => { + HTMLCanvasElement.prototype.getContext = jest.fn().mockReturnValue({ + drawImage: mockDrawImage, + }); + HTMLCanvasElement.prototype.toDataURL = jest.fn().mockReturnValue({}); + }); + + test("Should return new width and height of bitmap image", async () => { + const { width, height } = await drawBitmapTexture( + { width: 64, height: 128 } as ImageData, + 512 + ); + expect(width).toBe(256); + expect(height).toBe(512); + }); +}); diff --git a/src/utils/debug/texture-render-utils.ts b/src/utils/debug/texture-render-utils.ts new file mode 100644 index 00000000..c2ecd86b --- /dev/null +++ b/src/utils/debug/texture-render-utils.ts @@ -0,0 +1,324 @@ +import { + getSupportedGPUTextureFormats, + GL_EXTENSIONS_CONSTANTS, +} from "@loaders.gl/textures"; + +import type { TextureLevel } from "@loaders.gl/schema"; +import { Texture2D, instrumentGLContext, Program } from "@luma.gl/core"; + +const { + COMPRESSED_RGB_S3TC_DXT1_EXT, + COMPRESSED_RGBA_S3TC_DXT1_EXT, + COMPRESSED_RGBA_S3TC_DXT3_EXT, + COMPRESSED_RGBA_S3TC_DXT5_EXT, + COMPRESSED_RGB_PVRTC_4BPPV1_IMG, + COMPRESSED_RGBA_PVRTC_4BPPV1_IMG, + COMPRESSED_RGB_PVRTC_2BPPV1_IMG, + COMPRESSED_RGBA_PVRTC_2BPPV1_IMG, + COMPRESSED_RGB_ATC_WEBGL, + COMPRESSED_RGBA_ATC_EXPLICIT_ALPHA_WEBGL, + COMPRESSED_RGBA_ATC_INTERPOLATED_ALPHA_WEBGL, + COMPRESSED_RGB_ETC1_WEBGL, + COMPRESSED_RGBA_ASTC_4X4_KHR, + COMPRESSED_RGBA_ASTC_5X4_KHR, + COMPRESSED_RGBA_ASTC_5X5_KHR, + COMPRESSED_RGBA_ASTC_6X5_KHR, + COMPRESSED_RGBA_ASTC_6X6_KHR, + COMPRESSED_RGBA_ASTC_8X5_KHR, + COMPRESSED_RGBA_ASTC_8X6_KHR, + COMPRESSED_RGBA_ASTC_8X8_KHR, + COMPRESSED_RGBA_ASTC_10X5_KHR, + COMPRESSED_RGBA_ASTC_10X6_KHR, + COMPRESSED_RGBA_ASTC_10X8_KHR, + COMPRESSED_RGBA_ASTC_10X10_KHR, + COMPRESSED_RGBA_ASTC_12X10_KHR, + COMPRESSED_RGBA_ASTC_12X12_KHR, + COMPRESSED_SRGB8_ALPHA8_ASTC_4X4_KHR, + COMPRESSED_SRGB8_ALPHA8_ASTC_5X4_KHR, + COMPRESSED_SRGB8_ALPHA8_ASTC_5X5_KHR, + COMPRESSED_SRGB8_ALPHA8_ASTC_6X5_KHR, + COMPRESSED_SRGB8_ALPHA8_ASTC_6X6_KHR, + COMPRESSED_SRGB8_ALPHA8_ASTC_8X5_KHR, + COMPRESSED_SRGB8_ALPHA8_ASTC_8X6_KHR, + COMPRESSED_SRGB8_ALPHA8_ASTC_8X8_KHR, + COMPRESSED_SRGB8_ALPHA8_ASTC_10X5_KHR, + COMPRESSED_SRGB8_ALPHA8_ASTC_10X6_KHR, + COMPRESSED_SRGB8_ALPHA8_ASTC_10X8_KHR, + COMPRESSED_SRGB8_ALPHA8_ASTC_10X10_KHR, + COMPRESSED_SRGB8_ALPHA8_ASTC_12X10_KHR, + COMPRESSED_SRGB8_ALPHA8_ASTC_12X12_KHR, + COMPRESSED_R11_EAC, + COMPRESSED_RG11_EAC, + COMPRESSED_SIGNED_RG11_EAC, + COMPRESSED_RGB8_ETC2, + COMPRESSED_RGBA8_ETC2_EAC, + COMPRESSED_SRGB8_ETC2, + COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, + COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, + COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, + COMPRESSED_RED_RGTC1_EXT, + COMPRESSED_SIGNED_RED_RGTC1_EXT, + COMPRESSED_RED_GREEN_RGTC2_EXT, + COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT, + COMPRESSED_SRGB_S3TC_DXT1_EXT, + COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, + COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, + COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, +} = GL_EXTENSIONS_CONSTANTS; + +// eslint-disable-next-line complexity +const isFormatSupported = ( + gl: WebGLRenderingContext, + format: number | undefined +) => { + if (typeof format !== "number") { + throw new Error("Invalid internal format of compressed texture"); + } + const supportedFormats = getSupportedGPUTextureFormats(gl); + + switch (format) { + case COMPRESSED_RGB_S3TC_DXT1_EXT: + case COMPRESSED_RGBA_S3TC_DXT3_EXT: + case COMPRESSED_RGBA_S3TC_DXT5_EXT: + case COMPRESSED_RGBA_S3TC_DXT1_EXT: + return supportedFormats.has("dxt"); + + case COMPRESSED_RGB_PVRTC_4BPPV1_IMG: + case COMPRESSED_RGBA_PVRTC_4BPPV1_IMG: + case COMPRESSED_RGB_PVRTC_2BPPV1_IMG: + case COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: + return supportedFormats.has("pvrtc"); + + case COMPRESSED_RGB_ATC_WEBGL: + case COMPRESSED_RGBA_ATC_EXPLICIT_ALPHA_WEBGL: + case COMPRESSED_RGBA_ATC_INTERPOLATED_ALPHA_WEBGL: + return supportedFormats.has("atc"); + + case COMPRESSED_RGB_ETC1_WEBGL: + return supportedFormats.has("etc1"); + + case COMPRESSED_RGBA_ASTC_4X4_KHR: + case COMPRESSED_RGBA_ASTC_5X4_KHR: + case COMPRESSED_RGBA_ASTC_5X5_KHR: + case COMPRESSED_RGBA_ASTC_6X5_KHR: + case COMPRESSED_RGBA_ASTC_6X6_KHR: + case COMPRESSED_RGBA_ASTC_8X5_KHR: + case COMPRESSED_RGBA_ASTC_8X6_KHR: + case COMPRESSED_RGBA_ASTC_8X8_KHR: + case COMPRESSED_RGBA_ASTC_10X5_KHR: + case COMPRESSED_RGBA_ASTC_10X6_KHR: + case COMPRESSED_RGBA_ASTC_10X8_KHR: + case COMPRESSED_RGBA_ASTC_10X10_KHR: + case COMPRESSED_RGBA_ASTC_12X10_KHR: + case COMPRESSED_RGBA_ASTC_12X12_KHR: + case COMPRESSED_SRGB8_ALPHA8_ASTC_4X4_KHR: + case COMPRESSED_SRGB8_ALPHA8_ASTC_5X4_KHR: + case COMPRESSED_SRGB8_ALPHA8_ASTC_5X5_KHR: + case COMPRESSED_SRGB8_ALPHA8_ASTC_6X5_KHR: + case COMPRESSED_SRGB8_ALPHA8_ASTC_6X6_KHR: + case COMPRESSED_SRGB8_ALPHA8_ASTC_8X5_KHR: + case COMPRESSED_SRGB8_ALPHA8_ASTC_8X6_KHR: + case COMPRESSED_SRGB8_ALPHA8_ASTC_8X8_KHR: + case COMPRESSED_SRGB8_ALPHA8_ASTC_10X5_KHR: + case COMPRESSED_SRGB8_ALPHA8_ASTC_10X6_KHR: + case COMPRESSED_SRGB8_ALPHA8_ASTC_10X8_KHR: + case COMPRESSED_SRGB8_ALPHA8_ASTC_10X10_KHR: + case COMPRESSED_SRGB8_ALPHA8_ASTC_12X10_KHR: + case COMPRESSED_SRGB8_ALPHA8_ASTC_12X12_KHR: + return supportedFormats.has("astc"); + + case COMPRESSED_R11_EAC: + case COMPRESSED_RG11_EAC: + case COMPRESSED_SIGNED_RG11_EAC: + case COMPRESSED_RGB8_ETC2: + case COMPRESSED_RGBA8_ETC2_EAC: + case COMPRESSED_SRGB8_ETC2: + case COMPRESSED_SRGB8_ALPHA8_ETC2_EAC: + case COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2: + case COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2: + return supportedFormats.has("etc2"); + + case COMPRESSED_RED_RGTC1_EXT: + case COMPRESSED_SIGNED_RED_RGTC1_EXT: + case COMPRESSED_RED_GREEN_RGTC2_EXT: + case COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT: + return supportedFormats.has("rgtc"); + + case COMPRESSED_SRGB_S3TC_DXT1_EXT: + case COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: + case COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: + case COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: + return supportedFormats.has("dxt-srgb"); + default: + return false; + } +}; + +/** + * Creates Texture2D from the images provided + * @param gl - GL context + * @param images - compressed images used to create Texture2D + * @returns texture handle + */ +const createCompressedTexture2D = ( + gl: WebGLRenderingContext, + images: unknown[] +): WebGLTexture => { + const texture = new Texture2D(gl, { + data: images, + compressed: true, + mipmaps: false, + parameters: { + [gl.TEXTURE_MAG_FILTER]: gl.LINEAR, + [gl.TEXTURE_MIN_FILTER]: + images.length > 1 ? gl.LINEAR_MIPMAP_NEAREST : gl.LINEAR, + [gl.TEXTURE_WRAP_S]: gl.CLAMP_TO_EDGE, + [gl.TEXTURE_WRAP_T]: gl.CLAMP_TO_EDGE, + }, + }); + + return texture.handle; +}; + +/** + * Renders the images provided + * @param gl - GL context + * @param program - GL program + * @param images - compressed images to render + */ +const renderCompressedTexture = ( + gl: WebGLRenderingContext, + program: WebGLProgram, + images: TextureLevel[] +) => { + // We take the first image because it has main properties of compressed image. + const { format } = images[0]; + + if (!isFormatSupported(gl, format)) { + throw new Error(`Texture format ${format} not supported by this GPU`); + } + + const texture = createCompressedTexture2D(gl, images); + + gl.bindTexture(gl.TEXTURE_2D, texture); + gl.useProgram(program); + gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); +}; + +const createAndFillBufferObject = (gl: WebGLRenderingContext, program: any) => { + const data = new Float32Array([-1, -1, -1, 1, 1, -1, 1, 1]); + const positionArrayLocation = + program.configuration.attributeInfosByName.position.location; + const bufferId = gl.createBuffer(); + + if (!bufferId) { + console.error("Failed to create the buffer object"); // eslint-disable-line + } + + gl.bindBuffer(gl.ARRAY_BUFFER, bufferId); + gl.enableVertexAttribArray(positionArrayLocation); + gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW); + gl.vertexAttribPointer(positionArrayLocation, 2, gl.FLOAT, false, 0, 0); +}; + +// TEXTURE SHADERS + +const vs = ` +precision highp float; + +attribute vec2 position; +varying vec2 uv; + +void main() { + gl_Position = vec4(position, 0.0, 1.0); + uv = vec2(position.x * .5, -position.y * .5) + vec2(.5, .5); +} +`; + +const fs = ` +precision highp float; + +uniform sampler2D tex; +varying vec2 uv; + +void main() { + gl_FragColor = vec4(texture2D(tex, uv).rgb, 1.); +} +`; + +/** + * Draws and rescales the image provided + * @param image - image to draw + * @param size - size of the image drawn + * @returns texture drawn and its size + */ +export const drawBitmapTexture = async ( + image: ImageData | HTMLCanvasElement, + size: number +): Promise<{ url: string; width: number; height: number }> => { + const bitmap = await createImageBitmap(image); + + const canvas = document.createElement("canvas"); + const ctx = canvas.getContext("2d"); + if (!ctx) { + throw new Error("No 2d context"); + } + const imageWidth = image.width; + const imageHeight = image.height; + + canvas.width = imageWidth; + canvas.height = imageHeight; + + const imageSizeMax = imageWidth > imageHeight ? imageWidth : imageHeight; + const coeff = imageSizeMax / size; + const areaWidth = imageWidth / coeff; + const areaHeight = imageHeight / coeff; + + // Position the image on the canvas (0, 0), and specify width and height of the image (areaWidth, areaHeight) + ctx.drawImage(bitmap, 0, 0, areaWidth, areaHeight); + + return { + url: canvas.toDataURL("image/png"), + width: areaWidth, + height: areaHeight, + }; +}; + +/** + * Draws and rescales the compressed image provided + * @param data - object containing the compressed image + * @param size - size of the image drawn + * @returns texture drawn and its size + */ +export const drawCompressedTexture = async ( + data: { + compressed: boolean; + mipmaps: boolean; + width: number; + height: number; + data: TextureLevel[]; + }, + size: number +): Promise<{ url: string; width: number; height: number }> => { + const canvas = document.createElement("canvas"); + const gl = canvas.getContext("webgl"); + instrumentGLContext(gl); + if (!gl) { + throw new Error("No webgl context"); + } + + const program = new Program(gl, { vs, fs }); + createAndFillBufferObject(gl, program); + + const images = [data.data[0]]; // The first image only + const imageWidth = data.width; + const imageHeight = data.height; + + canvas.width = imageWidth; + canvas.height = imageHeight; + + gl.viewport(0, 0, imageWidth, imageHeight); + renderCompressedTexture(gl, program.handle, images); + + return await drawBitmapTexture(canvas, size); +}; From 21bf82d46158537b788e350269ef5d4573ac3909 Mon Sep 17 00:00:00 2001 From: mspivak-actionengine <118991512+mspivak-actionengine@users.noreply.github.com> Date: Tue, 20 Feb 2024 12:24:48 +0300 Subject: [PATCH 28/40] fix(attribution): show terrain texture attribution (#355) --- .../deck-gl-wrapper/deck-gl-wrapper.tsx | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/components/deck-gl-wrapper/deck-gl-wrapper.tsx b/src/components/deck-gl-wrapper/deck-gl-wrapper.tsx index 7948adcc..49c58abe 100644 --- a/src/components/deck-gl-wrapper/deck-gl-wrapper.tsx +++ b/src/components/deck-gl-wrapper/deck-gl-wrapper.tsx @@ -65,6 +65,25 @@ import { } from "../../redux/slices/base-maps-slice"; import { colorizeTile } from "../../utils/colorize-tile"; import { filterTile } from "../../utils/tiles-filtering/filter-tile"; +import styled from "styled-components"; + +const WrapperAttributionContainer = styled.div` + position: fixed; + left: 0; + top: 0; + width: 100%; + height: 100%; + display: flex; + justify-content: end; + align-items: end; +`; + +const AttributionContainer = styled.div` + position: absolute; + display: flex; + flex-direction: column; + margin: 8px; +`; const TRANSITION_DURAITON = 4000; const INITIAL_VIEW_STATE = { @@ -805,6 +824,19 @@ export const DeckGlWrapper = ({ /> )} + {showTerrain && ( + + +
+ © + + OpenStreetMap + {" "} + contributors +
+
+
+ )} ); }; From e4d59eb99869f6b578a744b7b048f8478c4fd9fa Mon Sep 17 00:00:00 2001 From: mspivak-actionengine <118991512+mspivak-actionengine@users.noreply.github.com> Date: Thu, 29 Feb 2024 14:32:03 +0300 Subject: [PATCH 29/40] fix(minimap): disable minimap for ArcGIS base map (#357) --- src/components/debug-panel/debug-panel.tsx | 7 ++ .../toogle-switch/toggle-switch.tsx | 64 +++++++++++++------ src/constants/colors.ts | 1 + src/pages/debug-app/debug-app.tsx | 2 +- 4 files changed, 55 insertions(+), 19 deletions(-) diff --git a/src/components/debug-panel/debug-panel.tsx b/src/components/debug-panel/debug-panel.tsx index ef6ca86e..9674012e 100644 --- a/src/components/debug-panel/debug-panel.tsx +++ b/src/components/debug-panel/debug-panel.tsx @@ -24,6 +24,7 @@ import { setDebugOptions, selectDebugOptions, } from "../../redux/slices/debug-options-slice"; +import { selectSelectedBaseMapId } from "../../redux/slices/base-maps-slice"; const CloseButtonWrapper = styled.div` position: absolute; @@ -64,6 +65,11 @@ export const DebugPanel = ({ onClose }: DebugPanelProps) => { const layout = useAppLayout(); const dispatch = useAppDispatch(); const debugOptions = useAppSelector(selectDebugOptions); + const selectedBaseMapId = useAppSelector(selectSelectedBaseMapId); + const minimapDisabled = selectedBaseMapId === "ArcGis"; + if (minimapDisabled && debugOptions.minimap) { + dispatch(setDebugOptions({ minimap: false })); + } return ( @@ -84,6 +90,7 @@ export const DebugPanel = ({ onClose }: DebugPanelProps) => { dispatch(setDebugOptions({ minimap: !debugOptions.minimap })) } diff --git a/src/components/toogle-switch/toggle-switch.tsx b/src/components/toogle-switch/toggle-switch.tsx index 23892695..6cec8ed7 100644 --- a/src/components/toogle-switch/toggle-switch.tsx +++ b/src/components/toogle-switch/toggle-switch.tsx @@ -1,5 +1,8 @@ -import styled from "styled-components"; -import { color_canvas_primary_inverted } from "../../constants/colors"; +import styled, { css } from "styled-components"; +import { + color_canvas_primary_inverted, + dim_canvas_tertiary, +} from "../../constants/colors"; const Switch = styled.div` position: relative; @@ -17,12 +20,17 @@ const Input = styled.input` const Label = styled.label<{ title?: string; htmlFor?: string; + disabled: boolean; }>` font-size: 6px; width: 28px; height: 18px; border-radius: 8px; - cursor: pointer; + ${({ disabled }) => + !disabled && + css` + cursor: pointer; + `} ${Input} { opacity: 0; width: 0; @@ -30,9 +38,8 @@ const Label = styled.label<{ } `; -const Slider = styled.span` +const Slider = styled.span<{ disabled: boolean }>` position: absolute; - cursor: pointer; top: 1px; left: 0; right: 0; @@ -54,16 +61,25 @@ const Slider = styled.span` transition: 0.4s; border-radius: 8px; } - &:hover { - background-color: ${({ theme }) => - theme.colors.switchDisabledBackgroundHovered}; - } + ${({ disabled }) => + !disabled && + css` + &:hover { + background-color: ${({ theme }) => + theme.colors.switchDisabledBackgroundHovered}; + } + `} ${Input}:checked + & { background: ${({ theme }) => theme.colors.switchCheckedBackground}; - &:hover { - background: ${({ theme }) => theme.colors.switchCheckedBackgroundHovered}; - } + ${({ disabled }) => + !disabled && + css` + &:hover { + background: ${({ theme }) => + theme.colors.switchCheckedBackgroundHovered}; + } + `} } ${Input}:checked + &::before { @@ -71,30 +87,42 @@ const Slider = styled.span` -ms-transform: translateX(11px); transform: translateX(11px); } + + ${Input}:disabled + &::before { + background-color: ${dim_canvas_tertiary}; + } `; -/** - * TODO: Add types to component - */ +type ToggleSwitchProps = { + checked: boolean; + onChange: () => void; + name?: string; + id?: string; + title?: string; + disabled?: boolean; +}; + export const ToggleSwitch = ({ checked, onChange, name = "", id = "", title = "", -}) => { + disabled = false, +}: ToggleSwitchProps) => { return ( - ); diff --git a/src/constants/colors.ts b/src/constants/colors.ts index 4aa283a4..205dc470 100644 --- a/src/constants/colors.ts +++ b/src/constants/colors.ts @@ -29,6 +29,7 @@ export const color_accent_tertiary = "#FDCECE"; export const dim_canvas_primary = "#616678"; export const dim_canvas_secondary = "#CDCFD6"; +export const dim_canvas_tertiary = "#808080"; export const COLORS_BY_ATTRIBUTE: { min: { diff --git a/src/pages/debug-app/debug-app.tsx b/src/pages/debug-app/debug-app.tsx index b64c081f..b32f1cb3 100644 --- a/src/pages/debug-app/debug-app.tsx +++ b/src/pages/debug-app/debug-app.tsx @@ -236,7 +236,7 @@ export const DebugApp = () => { setColoredTilesMap({}); setSelectedTile(null); dispatch(resetDebugOptions()); - dispatch(setDebugOptions({ minimap: true })); + dispatch(setDebugOptions({ minimap: !(selectedBaseMapId === "ArcGis") })); dispatch(clearBSLStatisitcsSummary()); dispatch(setFiltersByAttrubute({ filter: null })); }, [activeLayers, buildingExplorerOpened]); From dbd3241136206e8f3190b723086f734e19560e6f Mon Sep 17 00:00:00 2001 From: Michael Spivak <118991512+mspivak-actionengine@users.noreply.github.com> Date: Thu, 7 Mar 2024 18:36:29 +0300 Subject: [PATCH 30/40] feat(texture): support selecting textures (#356) --- public/images/uvTexture1.png | Bin 0 -> 973954 bytes public/images/uvTexture1.thumb.png | Bin 0 -> 9751 bytes public/images/uvTexture2.png | Bin 0 -> 192122 bytes public/images/uvTexture2.thumb.png | Bin 0 -> 7030 bytes public/images/uvTexture3.png | Bin 0 -> 218560 bytes public/images/uvTexture3.thumb.png | Bin 0 -> 8234 bytes public/images/uvTexture4.png | Bin 0 -> 149799 bytes public/images/uvTexture4.thumb.png | Bin 0 -> 7431 bytes public/images/uvTexture5.png | Bin 0 -> 425475 bytes public/images/uvTexture5.thumb.png | Bin 0 -> 10380 bytes src/app.tsx | 2 +- .../bookmarks-panel/bookmarks-panel.spec.tsx | 3 +- .../bookmarks-panel/bookmarks-panel.tsx | 23 ++- .../unsaved-bookmark-warning.tsx | 2 +- .../bookmarks-panel/upload-panel.spec.tsx | 86 ---------- src/components/debug-panel/debug-panel.tsx | 86 ++++++++++ .../deck-gl-wrapper/deck-gl-wrapper.spec.tsx | 7 +- .../deck-gl-wrapper/deck-gl-wrapper.tsx | 26 ++- .../icon-list-panel/icon-list-panel.tsx | 87 ++++++++++ .../upload-panel-item.spec.tsx | 6 +- .../upload-panel-item.tsx | 2 +- .../upload-panel/upload-panel.spec.tsx | 121 ++++++++++++++ .../upload-panel.tsx | 88 +++++----- src/redux/slices/icon-list-slice.spec.ts | 96 +++++++++++ src/redux/slices/icon-list-slice.ts | 152 ++++++++++++++++++ .../slices/uv-debug-texture-slice.spec.ts | 16 +- src/redux/slices/uv-debug-texture-slice.ts | 51 +++--- src/redux/store.ts | 4 +- src/types.ts | 32 ++++ src/utils/bookmarks-utils.spec.ts | 20 +++ src/utils/bookmarks-utils.ts | 36 ++++- src/utils/debug/texture-render-utils.spec.ts | 2 +- src/utils/debug/texture-render-utils.ts | 33 ++-- 33 files changed, 777 insertions(+), 204 deletions(-) create mode 100644 public/images/uvTexture1.png create mode 100644 public/images/uvTexture1.thumb.png create mode 100644 public/images/uvTexture2.png create mode 100644 public/images/uvTexture2.thumb.png create mode 100644 public/images/uvTexture3.png create mode 100644 public/images/uvTexture3.thumb.png create mode 100644 public/images/uvTexture4.png create mode 100644 public/images/uvTexture4.thumb.png create mode 100644 public/images/uvTexture5.png create mode 100644 public/images/uvTexture5.thumb.png delete mode 100644 src/components/bookmarks-panel/upload-panel.spec.tsx create mode 100644 src/components/icon-list-panel/icon-list-panel.tsx rename src/components/{bookmarks-panel => upload-panel}/upload-panel-item.spec.tsx (95%) rename src/components/{bookmarks-panel => upload-panel}/upload-panel-item.tsx (99%) create mode 100644 src/components/upload-panel/upload-panel.spec.tsx rename src/components/{bookmarks-panel => upload-panel}/upload-panel.tsx (66%) create mode 100644 src/redux/slices/icon-list-slice.spec.ts create mode 100644 src/redux/slices/icon-list-slice.ts diff --git a/public/images/uvTexture1.png b/public/images/uvTexture1.png new file mode 100644 index 0000000000000000000000000000000000000000..ffbb2a7369638183d043ff92c8759499921eb8c0 GIT binary patch literal 973954 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�H(xDvqmPh z8>E@4b^e8*K1?p-4#S+QhMhVyNB6Wxhv(c(WALzG*N0%vj)T+8ALubQB??@otFAcr zayLif#omhVZ~QMVeToomLX5ZeO1f))%Q#1hy`$2_#W6|mf>!ul7mh7dYdp)f+3bhs zV1uKEsF}JQ&QvHs)ba7WGwOep2~2NZ4yy!MXt8G_;WlQ(RvD^pprj^90{JaBAsE`!HDhc~@z=OY<{MqGb^6;S zys;#eG8t*>>x<=q>VTLW7MY< zo?)X1KHbshQFxYmlI?kS_h8zGgPpyzKs)|Ne?Ks*yp4liVN`wps70v?{|jTDO3n$5 z#Q0-<)VZzs`FYF3);Jo8rR}{DlMm7T5}G?CVZ)5mJ*c!J3eiI|iQP7h8(7)f@EwJl zFi}`x1WoOE0Qo%fp0FZX;?X%HuRh@|(Jo4+jB8mV7h8t_g>ZkLBDAY!_!R-lC-E6D zo)0cOXhh;54W2wUjoyJ3&U0Ei-QP9r_+OW*d_4SnC-fvnZ)`o<0pGv5AWsC_6e(3QG=Ly$XT~a?ig}A5}eZAV<$PaR40LZ{% zlGx@1lK7eZBV)K`^nG{WO|!^W&Sl_V)nfURfj4W0nVXtZ?5ZS^(rVSOC0;UB0I1J= zvT3XazU*qe(EZ8jt3H38WZW(b@^>#DTL!|y<D$~!@0;u^xKLo=KUZ=oT&QWDbXCnUtC?1yRimVt^@b#l|X z_4+LFBRbS`uD`S^F;|U0J)?`$xFjfTd>(k2hnIGGj-AF)I@c-&0zPW}aeOxh1#k*6 zy+50xz4*?>PbNyljnv@9UGUD?pTOlrXw+MKX98pC zlC~TVSz@Kq{ZVemCTL4uMMB2qf@09cP&s>y{5^-0`VyyX;Et3S*rU%b1jcgQzwWZ4 zg)X;U51)e-pG?d4ca_$?&XIi6Vj$_xnEe^m^~Kpn1yUj%SpyK`$<8JoF(^Dk3!yCm z=Tid83#h9-5(k*MZKL8+=3El4hXOtyoiVo^oph3|=~CwYM4eP_J+Nte$=au&DMO0> zhM#-<3j$k{YX)J{f%UA_SBvZ9A2sldxVnssif`tWGF0iw8-HrH3~kzIX*wz5Bh0XC zx5F>|zaS{zIW5E(gKrBs40TJQcz(es^s$q91>c=I?&5g%FO*WvYxcRNnk zCQjo#QQFtj77fn?`YQxotPk~#U?06VGzVn=Y2Pp8g6B-I7gf%WR{a`gHTo*zMz}8> zSFF=@7NR=nY2EQ1ZKi);V735f0rwBxV^E*j?E+$PhcObgr5>K4t3JPKpEm=+9q)Rm z^UXM_WmnSuXh8ZGG2dr~qfQ+Sags^if9YJ4g_CHZlc)+x!clfk=Y{9w$;)~9&^awf zC#SSzPK$`nmt6k9$yjdaHq?=TNW;bh^NtfuL2Q1z;S}E35kH35vuO*7dmFrhiPnr| zdA9f0tXTyHTrD8+fxQ-eT~W+LXrPMizxf45mR1-5<2}A3bC{MnXf*T zAc+15-6>D}Go-s_iP z_Ba{|A|XWA^Dy=QB<_1m;DxV5`RJID1NkF$?i4s529XqFI$;=`VG(@J=W?YjS|E^3 zLE8)}m86d59j^_>2Aw5oepOdUds220Hvca7u)Yl2v@g5#(u&Hph|HV9-%s!Vn{i`z z`D(7#vwEeZj!53|o#D2PbHrG`?0`#)>422m1~1w5o^Eh~h}hu#whnUrS7Xjqis{{y zpLeA#Kd1ohsbnS=KMAvo@a63Xg5ZX&zMG?}839%$r&ik-IaNMJ!`@*zz6JM)4K8P@ z3-V=mH*8JomB6eqlhp;J_j5j#h(Helt8}DD=MOOnT&6mBZ_#Qn-Rt;}ZM;EwCG4~m zaAkc+^48T(f!BJd-L>T?c>bQi0-x3}ylz6AL)kRmYSz3j_XMb2XwbxeYPA^1?j2+? z|3jLdOpi6wh>d~TF$=0_cslGFNXg{e;^I6617`Pqu__e*vwCA^$n$zCwQ#&4LVwDtihnAZi|W#54js ziXSf++1K!h>4SNJaX8K5t(ANKF{Ig$9o_)*Ih_g>VZ?kSF*U#>Ad3xWN+)(5` zZe2P*uf>zXMI~T3TA(B6#tD)K^qP@K?>u%os4PqF(8Tb!E85aH`3i zhmGDj`pJ#R6`9<0fUBc%|Dx0FQW9lXmEyD?tsvdwXMW?U_j{gM?U5~Sw2#!WtgP(b z78YVl2gjKjn6lZ(NJ~aXk2S8;H93HX@dnfFp}QqL0|;2a9ZUZGW0UzKhU7w*6Kc%o?VDX)h%IAs`~H5WA>2GRvp4&11ZRyG4T25Uc*swhWRkoW#viaL z+tcyO@j|U=qN7u`4>&u+jRL)h6-ZJ|n@++~kE} z$t|9zeg@oZ%GrGU`+wA80rc2_w<{TgDH@!5Q=bcvS!H}?mD2PiT(EO8KJJ7?R!6l( zHL1gfB7k&w%8GkvU9I~3z*Bopj^)0v4jHIy3%?stl|hC}ld9W@w}2Dg?pg5r{MVFK z>>A#!8^Hi(lar(U0Pp@0Bu61l`L3vVqmo3DiUzSIgv}oX;+Zulqp$$XGuF2+SDN6N z7L&VNYuTS|p7IdrR!X=3@ICb*+VtULyV|Ln;PMue{`u};8rIM#xsmx~H>gmLT*~vc zK?7ir*0>H2TEBH;k5>+o94wI+BvB&YY|&8Km^ zJ9O2>-6J`siX*_Sm1N;KhpH;)@8uRpEpcFepcwGn$nte9@{`%?aYBKIP!BVr6E~Wd zvusdmf6P7m*Y3p4fu1C$&{V?S6O9!&SE5ZkMgSfB2<>LuXL7G*dC+K7`ZZzieAJw? zD{(Qn@&YdDBZmjwFtX)9#yGsT8t{Sn8dP23qusAe=#j057QsoOgV%_`0(QVFd=P=T z13HOi%S$zOyT5J-a}(nsXKZ!yZm>J8n%K>E<$WkwJl1@j_rciBWZe)&s*(jbX-@VD zL2ELBQy$p_j}fGnvUJqM{7CYXZ?Zj~r#?rySJF`c)|~b82hvWf9^udezyKxbsH5!_ z-8+=sC-*^A@mj^6a8P|)+`EujZVYl}Q z8XE$NLAOr}ApxgcdI^2L-|@klzaK?NnWH5FDdyLG$>9;aaijAF!10i;37YoL&(3nB zfHeEtNV;MwjL(KvU(gu8b<@+;weNaOypyn0c-ZHf+C+Eevi<=&;&8?~UEcoq5$~~2 zUse2GU@DQh7}@n*T4VL7t`0|dri*cvabR1-Vi>l1wQ zA}>aBg7TGIPVKqmH5dG zrRcuSU{+DizYd{31Lp%2z${D08N2T(O-IHqd|Cx}t;c>>`*XDxF7agY)-tjM&emrk z=vaF518?F)Ce)P)^&2CM+MC0W${=^0Jq&@{)B;2+0`}ISX_XDc(Kc7ZWqj}H*`Zqph7`cX( zSV7O8?f*pP<)F%Yai-i0Nf^n!oAIRpKteT}oBs)$K`m!(j~=Loevm`)dW@&a+&$qn zLzGO6>ig!5fhS=@M)iw*PpFHJOlCrpr+_MiiyUH!T#oaHoUCp~4i^qZ z$IFx13xokM`No}ws8ezA{vrWoI#Xb`Uh5C?%#g@F0l|_Vv9WDN)ye2KsDB#D*LJu2 ziJ-09Hfx1&>(^JL-g}C#1-EgYf^dKC6T~6+Y0A|UX=95#8}a%R#At~*)%;MEB&&FS zC2iMw-{4h}-XOTAxz9?Wcropq)?l@)mEZ{}wrMhA!k(@yMO+M||c%-3b;`uaJ??u4tyHvk=dd4;x)r#hP3 z*P%m#YGTyy*k6v&ETsZE6oB=q!{LY4TzhXFPrWGNDx}3Fb1WY3nwHNg?AciGZR8)tiO{e{M z{p-nefsv~}^amX?Q^4$wu-@0d+sZKMmBVNx7m0Haw)4r(5U|=FWAvA5PEav1mn)IaI;KlJwFgCE{ z+x&L7fSe6WEs0U82MUGiMs#>ow-!M``*_DwH2t!}MM5jfb-K#PI!00?jKPpOmfVaz zNmM1_SXmriHNI&BBbAQV>&jpS&Ud=^rXwPa$(ccdni&uYBvBhZSkk|320Sf zX{KSj9G36$Tg;Q{X6`K8(4)wM$;2XVvRT}%1c-aj!}e9%fl=uK2`PycFgde8`xvl! z=gd?{r1k#>crILa2a0e;pSALF&xO~_A4|*XjF{^&T)I(S0<-WS)F*8w(B?=fQf0}0 z!ymsd!4RBV8Y9klSj(C8&Cdf#Zrit9SmFje7a+6PC^?mYr7UU?00nFEY1fL`wig=% zqdRy)TmM9Tg^>1t7Le_JSZTTb1Xi;zqE(}{(!NW~PfT-tZq5V~6M-4y#91<-hnu){ z3dcm1q=dqVp8D~6QO!+mveq0>N$&0WX)Zsv{Wg~Yr-*J=muH5rs+?JS)`NQS9$>?O zqRLkXlOFEB@xs!Eh;0wB70@-&CkjisV0v}mRIRP?K zo2glj_0EMCch?cVaT^&(-GC*$ArvnnJTtH-b5b&MPSf>YaXQ^#8jtHZUR` zq7=^&0D68kv~h5uboGB+0RI?>yOjEJ11}O_A966k<|IKtEFOK$(NxSTU7VhO)S@=A zpYkCxpuv$y}LBgYz_^r5-lB{WHPR}xxc|38l6hCG}KBiPlc0rE5z;r<$v|m`l7^Rw;A_9wy|1_fOQ$U8 zm@%{v`9l%b?Lf|Js!MUJWj+fo<-~n+IFQGDmW_*6TU$dINzPJa*e+u5M8PB^KHgKS zi7a+*^ftAk8M`Z%O_dWO2s$Y!7(Mn3+clb%_idL2rF2VrR#YuQ?%PLPejJdG@Vf8i z@uhPKyt8+fV(i-k)L5ALQ?`e!8J^?Ik9LPVETxLj@AH{m$VqxUD(%mN*7*w-zx*=g znW@>0bMydVdF(>JrK#5^L;_bx;46JvaCnotCC})T+cwh>P@S&w!3!0H(3;U~C{`Bq z%>O$+(jg1}G|^Q3vdemX$dFm=!Q||`UC0o99ktAox?I1m4Yvn~|D4G4jXwSJe^Y84 zMm~6kcFTfBmfku5$DlnDec#=yvWS{oY6%%J(_St2nyRSpV7x|v1m}NC@_t~hQ<=ai zarQwJOj7JpzRCAqBcEEdHi%>CEv~x>j`EK}beS!w8BkrZyu9C(z-dzGU@t6wZwM3T zO@}~z*DO)!<2Auf22@Z*BI>eMR_G+#B5WGWekBPEtZ9he5w&WzOJ*pX}W%Z@#Rm z#hVg6L>te{hdLB+KrixvS;03Gya6iqQ)QypQN)X>n{1$AhM{8jo`rTrMcYy74;c=; z7Z2$sUVnOVz03<(L|h$e^ZRfK8MORCB*>o7j4OpWjQcyj;KxDqKA+ul2ao&x$vJ%d z|8e!!VNpI&|FBB8fOJZVEZwbyAR!^K#{XJ(+e9oEKy=TrjGsf$K&!cKRbjvtNU-~HQ=bokcznN4H35gi4yss-z+7}0i zdp~5&Sb7r-Gv2TV2)xQ1t#l{GSa8{EkYaJi=gD>DuzK!*@yyWe;bz5;BYyS~PK)wz z4?!4>YuEPo_g6(F#GF`%6Hm-WM^%9^QCerg-*r{*LyB}L|EZx4sDJk2rF&L>3u&=S zec;xkPJE!n?9LO5#NFJL$9Ih|G|DVh8{O(q6d%JeUXy-mD0QyQ%%PMm0hVON>4q z0(-20X((2JJS(@@@X82Y|G5%5kj9J)|2GK_m=qqaw;qw)Q%)}N{_;0kh!~a}2|f!i z7sp!RoMqeb2NdZ;t_NpazDh2Zw`V~-qM4~XmVAidtpU)2$RS+G;Af)a0t))cDj*jIOqhPF9YeG}w?|7rCb zu=2YKHygh>uVOkmIlW|Gn1Co+*2`|&x0EL)CO+9F5j!-UZ*CnOdIGkeR6*_iI~Vo>PrU79_6&H} z{z=0`oaWMT8-Mn;xx}sXc@D|TyY$$bsnHeVA?5IxcOy#`a;#PCc6|HSk^f4Al-pz9 zK=N{x_`-T?A$=e@IjOCEc}@h}LdkUOKn>h+A78A?BF9Ewkw3|Lm%K3;)+ zwI|wk(4wVMg9z{;YIBHZsN}_oRaQ`#;_G3(<)-7Yu#gs-$d;xzsNVVEW%`!`|@ z%>lSrwJU->q<^3fQ|Rl*C~57gud=7g6uz7|dATz|4W?#6sl>~we+5=X^qR1JU3%uTm$12R4|t+3sLAB2T3(kY(hfb2Uw!mzaK(s!yXQmgOG#vSFP7 zVtlGk8C*`#+f?9J>3&~isgg2*ThrV01A{=RNZO7utx1j7y>ppGDZX_8GGxhAg2el_ zD+VOR@JFG7hQTN_4_Wb+fMXoAEjn#Ao@H^ZZMbL+!1b#G7vwA_EZb02(wb0IcJqULqc6fwLEZ`^cJsBMYDjS zh=Gv9f)@0nnUXRwBaIY{bH<&>3nwAT+2qMJgzoSA`6TqB?V zbCK-w%yb3i0rbqTV#%7Y0?auaWM#Y2tt~Ee_8zLL%9UfL?MH0C)_&EUGGjO$y;eytBrCMoP{7{cfvh0h3vXFwhQn{J4 zw_(7&EGeK=2Cn4`Tk8Vb1~n%bUG-&{ps1r}~Y}ty1 zi$;)V%cUZ~zp5klg{6^F0^2e24b8B7z1pAm?!n7+{TGfI339TVPwT5lF2lMGpd76o zW#C`Ah6f`x25PSmHPmA@^$ti3m&7M0a#?bQgWB;gDG{?Zfx(1`6(RALk)7jS4cVWe zwr;QhG2DCO8>P}y`v$sa)bDQmNyNRQOV|9-PxXroO;H>n4Y`JK`cq-g%if#(KDW3wfF9f+?Y?o;Z&SukHFw|V>ah#fhYn*wX&(+j(QcUy6Q z-+sT>8dHw$UoFr4)r#Ho<;<;K-~xghinjQtMxjaa?a{sBgD)3dxN!|p_FOs02DJ|Z zNQW6t?<|hkH%o0}-F=^&Hf7s70e6Vh#a}LGHuXv~ON?LPSQC2Rhas6=y)^w8Z6*^x zQBG|8a?YC|F+3)IeIkTzQx*yPB;Spk?WxV5&5=FOLPpm{uB*d!XU>=%18T0%QWx=p z{0=23lenZ$d`PUqx9BA1Zif=H=q=jl##@rAcjBJi*EEv31TQBNd9b08l>v=rQYU;O z(-T>!pnY{GHzz}U4s*gJdx_7xfMUo$bRn;-fG%-^AMbB3*k5FJZuZ%hLJ&r`&6pl}U!K`(L8J zMbKFn8d@6|21Dz%og3+c)l2tdEFt;{XyT`phVV zpwzD$NqO#?z};+7M?&YKG|Lx^pSzQP5i6JSUCCW}O^>$eb-~4rY_Kl=Xs?^zOdk0} z9Wnb{R*ezfJ(}VDVwF_fUvZw|HIBC3+?@FXCE#?re|{*jf~%X?;if9kNAXLcb;B>w zyI!8-={~=-s6&jUc2rt(-o+n$S6<^}t{hbQuJ35YHdrHk&UH!lCadR+X~;yn1kN=E zNmApXdxHqKK&eN>#GAj(MJFh3n^UkS?5BQRBMe6>^`N}+V=G0mLY>I6Cd}^A)&=K! z)41^&aG=yLRASM#)u^*KQe`=B#wv3xGOx`F22JMbt+c8kHVuzH=a>>`pMwfQk2_0IJZDGS2e5iI}y zwWe9z9e*gwM_cZCoN^skvm_wJOs!?|k`nrM@gn1qQQS@>G@*3u{)Z1Svhe50{e8MJ zX=OQ+@wXo7hm{$L4U?1mgNgd=E0cCs3^~q+sRY4M#WpelZ8kK&?_tmcg)`ePm`}7Y zQJ)CIeK-cE z%MrAN9s1qlAg|~@-IcLNA7a$`tKS;$&bwzr^bLMg2?M{Mz6+}Fv?+C;^ljHti{>fL z``w;RzEt3pU!j>*l|wT7`u!6M+>>lBdCuYpIvUh{!wB9{5e+GmJ6={gCe4%S?`vEsR9uO%Ibtbs-{Y6 zb>t(Pl|imIVRv^k2#fCD=geAU*j_YcQ zkXc`KSNtTBf@!H0i_72|i6#*mg5{AayGu_yw~3T~WQA2BcScMI&(cHGSMIQA8PSW< z^UE6pwQTRZMs;c!4LNua3UuN3ZVUtxNw12NoVH6s;_Q|Xb}Lykn8Vo_MM%EQW z7iQrZSp~e0t83b}&5HG|DU=|$i=<{1$V);g$*;kGF=oCZ3{(lprhn-QI%(UZT7v{M z)x)J0M8nI7&X3PfpZB5;4{G>iB+k=l)CkT|s?*`4!zaQIRx-r*jL zaIxz3%Ant%2^QnXb;!GvdR5OST3168OuqMH2|Gw7BOn0uZal@I;sLZ#IyQH;+FGd0 zR9T;hfdJ@8M>JxCu87{`T-b}+tlV|60w(Imo!$ztPabWMnjcjmk9Lqp9a8^9O1R0X zRXzS7WJC3M+h>Kw5Y6ZzbnGE;Rcj#PShlWrv`haIaP+S9A(0Tm`@<~sw0B*;i}D zqwFdyKR5lbFii?~o>sE-Vl_pjgdZ)Q8*k$_TlSQGKKdQ&4cO<)Q##bwXG^3Mhl)tT z33(b75ur&YXxf44&~m2j69`{^cYC@hyIKZ3A1Q+4Fk7qALjU4L;ahGU%4M=vN3&Q) z9HDvFI9|x+XueXM;(q9FGW_Z47cYkK$GrkOKdgN(=hi^S&jSjoz|^Ass*8kset({k zRCrxFYah&XcBSjhyQr2c(Cv`=(wNavbVSx&bQJ`&WBMd>3&@8}HG7K`dF-10U6kl| zzIBVZU88r{9iht1Vky@Ic-%T`JI-}>ab#F*&FqPGMbLDp2%UFLZuIK@v<*XkI&nVM zIaoP~1cv|YiGJ(CUzwot8T*a}D)&~$H$??^;pc2bwqQ9v>03@= zxT^&QOBOnHXe}E`^-%-5Scb2=#6pikoBLT8OiI+=_Z|}2<-03(8r{r? zr0ka789W}aovQJs5)*Q`AP*OK8CIU!$jfc<%(rn)Hp1S*j~P_6 zpVBrptRW(;J#?dm|RrkxM<8{Y>w^|Ik#!h|39FfH$ms zDwSNA;j3hw`|~$x=w;<3G-VdkGbKPOBZU~^lv}Ao1(!NaIuqjhoTU;AlwSkVuSl3* zgmw)&igy#)L^AO1vH<1v(nFGln9&W+uy(nc8~bT(_{=Q@WbYKDv{9a_K$|2TEoo>y zh6;NxS5pkBO;Bl)GAqK+%_&x&BX=h@!}va&uS)hQ^_PaBW*^K#U$^R-Z^9>@`CDom z^iA(C$Y}o10NB*EV3^(W&Nh6o(rp@Da<(PbKV46;g>~XaUE3s-#bSxkb<0HzM!x6S zpHMxMlWS*Kn=<6?SYW)dDAC1Wan|9f8udNAAtTolVL%JKW&6`XgVbnnOK1b`$;`qs zF`IK#ixcB=aBOh{zcCnW30H#i9CI+AuUgffej*$rx`a8S5RKHeBsOa+qKAYp!+o#g zi?T+(aC393VL6y>2LLa*-$v1ndw5Yp&5kL6UX6Sb?TgPy2~&Uq)bBvo{q3M0tJyR{ zxvB8i*}J{JgTCbH>;lyXa;If)VKGm=A$}4q4)A2|B9enEZ~xrf3RyYz_Zm5AiK>YS zKdv=CtzwFWhfmj=bqn;E+S5swWdcumIZ4DwS|0sm6$Vjeo~!@S+y=?J!rJAhE;CI9 z9h%m)QM=ew-PjrJypq*GqFzADLn@`X}} zKs=SVTXuJP-BViH*Dd)Oo5t+wlG=(NdY>sxZ(+ZDiSLq!#OxF!s4)9`ZtF~qQ{lc8 zWCWy{49;Q^5aceb$hjW6$zE3H=Dl%Y=M?je4+~?YX5-BD+<>~<%{kjw%IY=1FKFiG zidZMgxwl(5WHIWV_pYeE-9sxZDk$D&T9c3ZSY03g&CqA6!lAvU$24;FO3d5EWypv! zyfbxEuvPX_|3!mZkzyw-y?7L?7|u3b6;4A{I^ZR>+Ne-^Fp`@3*V`mPa(zw3HP|?3 zM)!rtk19=Vbt9+1+~9DwODLHby#9@@G-Cr?33w$+&Z;%l+Ll{g8;99KLpv*~vRzb3 zj)(bc(^SRnjJXXRQBUOL#X2n2htPqf$itB#CjcwFQcXRlLNi`VT^$-2mfJ}Un(nNn znPgD{D=^g=EvC*o?#m?!;2wB8O6LUF5L+x)4>}hYhcT|nzYqh`2fi8FHNMehkYQ*z zxmq|K)dig`pvqzVrLxG@vl1z(dPc`#snf$b0jUBJp2F`0z2`p#Lm|zWQTVMyBntLD z1b^P{TTElQLBgV8l|`#!6MIvxDp5VL&uKP&Z-=(rT&PVZJ~r<>7Z#;f(tJ_F-0cd> zrDiM3LT;M4C+u3yN7+v@g;Ree`-@C+5o7t=A9iXc~@ibIH7Ozg@OK zv*ft=sF=uTS_$tLENo^kRDdF41XGI^IFHgF)30hE+;$l*8x+KQv)_bOSo9Y*>(E{R z&v5sqiz`MIfqFGoYnn|r#D(FIfjuJ6D}Li=s zffqX0q&r1wOJ==Q2D!4;P398#LmIV79S)p|W|}u=Ym2%xe5A4NM)~B~iiG=1_aH76 zEBv$CkW?27YfUB(W(jFSc0Y%MkpS=TuW*eSt%|fs-FF(=>aC@FV)bD4p4xHSvVm(N zicZ65CiRWQpI_t@wb|n2RSpv~#B(clrv^KFv1>~VeeEj)<(ww7n6^PB^|uqWe|&T| zXMu)a*;UjMGSkc0?!GPQ;RWndwMUc|Hguhaw{e9U+Ib&xdLzccKFj)Zf;K^YeCuo5-C?n6u9u|_$R>Y^mpR3j| z6||hKj@!VFmD#90=j=n!yu;x-p$lw|@=8N$>e{VR?)DphI0#j{tH5&8{ejGFN@me-|aKk7Y$ z#%BeaBJ*|GZfo%#i4@V-V5E+kGa6r?@2zfZ2#FbH110dzd*2+Mvp`MjhvQkOm?~qB zfLsQjQ%`?`YdoR3SKi*D7jrJE@6|LhW}7_9c!Odhacwe)ZqgYUJVhllu31zaD3#O+ zeLQxTZUt<`y~SU1!d)~`RSBXu;1w$7A{reFjvj}1tpA28I^GiuVt_i81|^y-6JXq%l)oBR@d*x{|&wv{VV@*D4qv!Oz+*^J(JLV zoF$#Ab>$KrpCv9a>pRycPmeg6QSw5mviU=olqlgNF=W5;~9_X@9P?ZP*q57 zDs`W8hD50_oZsJUNR8Lotz&;{y=z-(o=3$$@%35^8q7>DR2OnNdA*5XQu)Wbg z-{`24KkfDH@wNoXXyAcNU)AgS7-^n8wz;l*{n1AUr7iU;poZObgkd1869qjmY)#0F z;+wfKAxaxjy4+6!1+faej>3NHS5t5)RJX5BF-Qr>pJMm*7gvb$cO=WGEIDNj zEDaPZ_iX#D2JW(mT$@BE<)JqysZsz`^O<@>HPZwdf@FPnqfl*e9pv=;2&+$bX>Bqb@i7uCY-Zx0UExq z%-HfIzB~|aDeH(1C!)6xwaxr3Hn^bhnm(xByy3MxKS&lX%m(Ee)R8~sl;xwoqaGlI zQb}#9hF3i{@$=sdlk&9@=F;DMj3Vs@fl8%@wx@0Q0vZ=)A2#fNMC@T$J30x_@6w?f z-e#Azk1R?9IK71RR3!_~{BkBD-Dbwfzxv$B^>tWsc>Hs@pVj8f<10Z|9&8EYSB2n= zq=AkCJWzhQ8kY#N;e4}d&(@l51@PiM+3=b7=Ir67PsamJ(a8gG#Ob;npFh?}?kSx; z7GQA<5X4s^Pkn4+;I}zN;^2_<@+k0ecDcBarC>A#7$7Vg)c9GYX@_!uUWy(#arbnT zq>TnFZu05{sH&@6Ly@sjg91&-b1 z;9`>fXM?x#yH`FCAaL&XvTdK9+8_RYpzQiKm=(%~4pRgdCQ`?5ql8&VRTH=afcO!+ z)<{D*stok(O-^tz%fN>Oo28_yr%XF)P&~Qo} zyfU(7f_c4;%@c_Nh^9$f7yb|h2nNfU#Gd-4g58@>_DhB7wTLr(&!>y@Ox1GkzHQ&P z;cyANnR-+);gkPzA!b=J1M$><5}}UKlL<-@Ow>136MS?k$-<02S)$vHqtg)0j8FN? zC61*YMt<`_M3dUuJM{JRqx!c#MtL1ejWxEO%c?pTUT;5nJ{nRJak4bzZz4* z4LT1#7wywcU&}A*|0ev|W=Q2D8xMHEd0TjRl_;R{@lrq+!-EuknROhU#I@{>$I4y~ zPr8T#Fu;R0`1}nW#!R=Ne{=yUGj6t?YcH!hSn-WVU5E`7aUCp0EC4wEDWYN(OBB#{ ze5GYc5rce0oRPYuVfs2IC1xJO8=LOZHi|uhZpmT~F8YtaDH$s+ z(~XU%{zgprWAoO3N|l5^2W&6qFm44Tt=*ZkD1VwTvRR5TGX3Z!N&Vu(e<17loC3z# z9^-&xT-jw4AZUQ|$VjmmmJ+3%>`JlE~Oyu++^LD#vE^ma-7%9t9*&+B%M44&&OG zDbqYu3i?8R^%gixeosYi%JO1ws=`bm6zz!nBWrm4C(oUdx_FbEl3UGZi$8)5)}^Q! z?>B}rtyX`>xQMz>)#!i{R~_x*3G)$k(POV)ti8Q*Q>barpFr4uUvwf zt=Y={($w5rRL)`FjE1oUi74W>kAwCX4MI3C%pBgaRA1sh)gtQ(QwBXe{>)XOJ${jqUp?{XpNR1 zm@&VuX%aGa19Mg^VNu$5&GZ2wJN%?<&pp5B8pxU*Nu#Qqk>K2UzZ~DmyNvahO8$wO zT}?Mg#^Y@+DkryZ5xQ@^R)a?2I-)!HF{CW1(ntx>f?a0{B7|qvp4ESnwv(jLNKq9?khy9D~y=iR^mb3;YWp~ zP0p>5OB798!-#k>`V%M+9i~6TRlR3k^eWBwn?^GKy};SLz)8Gk@vlAA13HWAgUvD_D29$ZR!0eomooK!5*=F(&ze|8HSrm3ggl4kdT;pSkSb_ zj(H3Wy{E@??$sW16(V_h+Rphs-Ogea2G_t?23b^M8%(Zz?$Yb|3t6(8!66(;=u>KJ zR>MrP8M$A{W_bRPh5JVEW+r+|T(&Q6O@dtiC!SOlNW+HL)?yh3*X?U75ePPO_>vSl z>7o+53^NiBv;d_~eN3hdzG2L|0tYOS!9IgS-Uj?Ow_()g*{ftIG*9KRW}*7OBU_dHl5nmwG1@DJk;%d3}ffb^FYc}h6bUlrW(8aea9 ze#;Y zB7ZkY%Hv}x2x$ymI|n2iT8SvKU4mA8QIu?@<3CDS)pJQApQk?VRsl?5` zXiA|-c@e8j&O=?wv9gvt{pl|YjP~}g=SjX$b;GxI(2AMS>b=NNLbaAZBCKlAg&F?a z@|TH0(Xi}Cnr>kmvYQX&jA8t=jLE?vt%~aQY}0&I(=A*2brC%h`z>)okhG$zG)uz8 zLk22bP|8wSo7eJM@K?1bA`wpGScKKFG+i2J&oyWgFMP{rIp zDwpLB=y)}ARW5Ck@Ok4>nZ`sJo{G;g2elyK4Iy$T7-Wl*@O0zEjSFHmH^Q@7o7y7()0~@ z9Y`BXzv(L8>D$hYeUpY0qlE{(gX9)}g%27=JT*Mjp_n*_l49ZowwD@4giL(we|^Xf zd#bR5)l>IMS^tHoy3+ZsvitqK3drf=c%4eL&jftR)4X}JNj$1ee4{lOEeVAKArov! z=gUwUV8)84l=MQu2lpGDKRNrego$tI={@_7^X<+)(LP?cDv@i}Y^z-U7kFdPou?}G znS8o!fZk4VHd6dg-ci7~mn*pW@%EL1%EbBR0tLL zM#i<((OBJI>KT;V1S{h6Nf5L04!E8T&p{z*iTr65VtP9H(-sTN$9t}?PgKc}O_R$X z2c4A59!sWWhX{Qdw@}FBDD1QM1~aZv#Zn?Vyl069#kot0Pb_Z0!L*@HUdrgx3Bk-O zeQ#RQgkRzJPLw`aBWQjJp-YJapW9jdrP}DCL@=RehZwK)aGB(#mDw%M6O(VHKEZv8 z^t&p2d`?$8g*LW8-6kWXo=y#4s#_I zL*~KVHmh#)n+S4su8nb;)U-M>d5=qY-r-OZkIXIjL%&joVMmkfFPchZo5;lz_s{y)yz^w;*cMUKnK8tB_Z}c))l?p_zmlPB=d1O}bVF+i@ z@#~zcuoGB>L98arT}>ZlBeE*LjPzD&?W%cLkou>2Eq^&`br3$ybI!*>$_3|Oteweq zJ}Z-xjKq;p6ml^mE0GG4^SpMiWDZ;qd@l>$C3|?i?Y|hyZd~%PJjxMR zaP3G$y-9lKW)Dc+;PZHQ0;Z*r_-qB-T-dGQjEdN{t;maQ7pjkrR(KT=A7rPsCoq5h z$c)^y};^Q~gFmHC8x5&^|Sv7sio;vt6Ga-|dcGOA02%b!icJ9JVhQ6lLl z^GSme@qaSt{d^yXZ}2;oQgdG=_LHZ6uey2FI1?6ImncK`x8n`(tSBj}RXp2T|4U43&d41p-g_d?8B2-lAd0yFY zN0X+jledxHYZV$z5f7eEa=`lhsy_AG7c0nYBdhDz^bCP$&?{-7Bq%|AS|KySSR#B8 z01_oP`A9!~ja|X-F}_YxdG&ZAcMx-)UR!klHgPLmDGpR$bMCGg^>z0Pg?fVT(eeqb z{g9@N&ihGm*cX&HCv&)w78lw{srcQ>FzyoIMLG3DobV3NyCmi7=gWHiZS~YRc6cT< z*^W=dC26!WKHA@T-&NLofuixr2lzz$mP-!hMAHOx+mJN@jc;Jw49KD6a@0Uue+W!6 zYM@R4)gy2UH6%6ar7AcEkx`e@!~5ZvwT3G!rR1X|&9*YQxtckmXz4d?i&IH^WBJ}nKJtwEQLjs;C$>bC$;l&4Bo$7(^RsD zI!Ty!9}N%tvX=Q{E?;$P$2`R!E7N(HO~!3?L^VJeCr_YYyc_XDwC^G&11Gp7MauS zh&+@#6FgN<+is zdeM3h+9vcgc4sBWcxJe|MPZzVGfc2Re43=67d#2@%!K@${g=It&u;b=wj4LjjVlx= z-^ip$#faHcDy2?!6E(USZ&S^jmNJ*S0rb}sg)0AikDh)tAN&8=YPbBT1v!FGa|IA#4OGf5j zs+dtE4S(7A{sHt2?w9c&60w~$Y`5oDfr6jWxMpU?0Ba7`-`-%U|*S^%8R`({9oPjNWPLAopACeJ- z5okE}HukC~IxZIbj?;Cns&QSb_*fE1>z}04K>ivCTk}s#{1^*pKy}N}_^8`o$lk_6 z^<)xkWU@HQmGaw}i%w;H5KZX{N=nkPRCMeUVXFivB2=zG5XZV``arp0zBq~yh+JDh zmAp!?EsqC+0z2erJm-cJ^ni1fXFw;;j2`9a4M|^W!|t{I*!nHL1QF7@bg+`P61%$4 zXUk^Ntx`ucJX*{R0LpJ4#7ewJ})*mqk2YdYt!j zll(9-fH>>{-uvI9Ir~;B;5ndoXD0g@a|A@cJpZz&!C8-!D&;qCxy%z_YX_VwsTAI* z6u*f47v}Jw5g4~;O=re>*#!5Pvo3Jc5Qy)ad=2YP(kq-*TkVJE*@b6SrH?zlZRP6n8a2;--BBsKxhA^cDRYlDyY!mk zK!63AkKU4W5_<4C?{Ic-yDo1jaTCG+wmmTycZIIpZkpE!XfTX{y;mmH#V}6T6-iZa zm&qCk|Jx}VcIWT^WE>K)C$AfXZ;{q)ImWV=2Hz`&Dq%xgqJKmN)eDmgM)=Pe@RpWG zM^Z?}JB{%!Ev8nxT-8=xaj+qWwlRd|&0pJ5&+$a~GdGwwds__kC3Oe$a!Q~?Ir^{6 z1^pu{a)XuX4zu951*;$0a8e}ebR8G*$WTae2IvX?_+MT-XMAlXzuTm#C2`FRUvmyw z8Bp|@nFaAW8K7I(nbI|!|6|3q32OPBgW}|BO3se$ob3A*)ZT?_aaE5Cw;;}pwUsJb z{N{fjF?fusdlMnNZ%KZy6Vo@xZcZV(Zo=Dj8>C{#nkas)dkcGZ!#bRUqN~gtmB|-@ z(ZhlKEW~@t-`pA1Eqjp_a$ zx@;b0`%1zcHU1{{^d2gY9dGV>*KePPnt4Kdg#~H;3~v4BNU3Z$o=V!!!tA)$BCAk? zUsTgNzmE^eGwuh31?_|9n*YOBb@NMW@sFn$F68I*t5CIHR41ho7E>`i%6?GlMF;;O zXR3cuA(g9ot!mynw6e5sa_HB9*6;hb7fegV8x%Seooh$D+h;HQ4?h3FQFa{Bj@Jby zcvk0Rd4eInUX1_4 z-gJ`{`1xONTIn-yKs@kB|AA);S@=!t50TW7MbK{1T_cU*vwmJ60{mSIsVcuH&8Dfu zy3@d=#37Oqt{~_rkm1#jfH#T59;5gG_Bk?*bDppHiUWrbE^?>g*_qX=6#*h2lR>^1 z=are$e#sB>FOL5I`LwiRNtJ!(TLR^ExBbwUL(`pb$}T9e~1~DP7su`&pK*<+Q$oY6!5@AiLwK3YSW5|Pys$OmDqlnZWe&w6nu0& z$mla`u!;fH`H8t2#5s{e2u)qm0TEaSLBp7NzUBsV#^qnoUju+|02~^*ILMdlu%Mm1 zT70MPK{D@!y^+V@t8+?osj7SD4*~zLxoOhVBS0qnuq`0qt_yG(*TG+`R<2C;90=}h z9y7taI8~)$nNQ$&J1ZSLuTG=(#;BLXb-P7ysFaMcPgz>#dVl2yxr z67RG$OqmKnKWi*n?uTys1Azhl57aP=K+8>5miz!Ziy`%a_~D7bPPxNys{5Z>MSt!q z@{h#ezu)^Wx=WZo(*c7E2Ulk2uGg$Ah2G2|b%3t_oQtrogWoG`tz47z3z(G@&vkK~ z?ON9t7RkdsDHYy)E-_^Hhm>|7DI@HRLq>AUSotiCLa6R}TcW4Okm+K{Ru6$`ysrEK z2j^`HckBMb;-+tCb){YYdGpj5l15jY8M#JDWCfH@|B%pA(3nAO^6|?BjcCJsbE>9B z|CgX~(4P|^&{r5O#B#s5>&hf!?}OQZYWbn^&s4FX4ME!dZJEiMlcdMs(FYD@pp~xs z&_PqBzaHjC@k@!eo1GwU-njQQUn5jfj6DthjvQb?-o11s-Nx{I0>A_o zXF`sj1-AEdzYvG?1;+LOHono#G1aY+w)!`&$DO~Z4#ccyk{8`G+A<6250&#R2z63h zP?7c)$eR*D91bXHnvBlJDr54NgE-?|ZPSI2D2u+C?vDo;)4NtlmAC4Eg^`&lh@)XC z?PbF8mz8OD{+h~+Q0Pw8l~kV+!5ChEiZGBV(;aqUNqbpru^VXqKTsl+tsVlU(o^xU zPoO#l?T# za~~-!GE}nms^wB|OM+)J6*vL#1hsL2j205x$n=-2e1#i)a0v45kSCR*j&N;nRotuE z{}OCxkvm$TcKKTk8rPt!XSI^+By$2k5|{sg|l?#?(UbVw&y zwDyor{zXTYV*^$=D;k1qLA;l=ZL9rDoW8;x7OYO^ztIB%h8EeuKkhxJ}0%!3f3+h_0hll(u6F-3g1Az&nHagn0rO{WZLqzRrv) zw^(HR9&v>QOB48cx-e0;#5pOy2=KTjVj;Mid#vxCW~z7LJ=oHx?Cr9Z)wS z=a;SR?YMLCF>zn+V+kfyAjaZ#W~S4JK8O9xZ`&O!XUMh1)*JnI8(mj4MK3ZwJUk;{wiQ#J&H$;dcnfsZP70ScRFM8Lv(Kp0oYH#=Y z_3LfE2+N>0uCh2=7dwWSHGyb}^Q4#4tZ-DIKw8j(@Ui{uTs>(gJhBf6YL`w}q;WIX z(R?G1#l8WDzm#j?de*^APicQX1UP;RK)h{uV;(0vdY+$_X-1p~CA?jCQX$9(2V|y9m68PX@K=62oE?N;)z|j#$(@wh+b|7;mU=RGVNKc`D?; zMQ-&_l-SePFar7t`nl~Hjh$($qu1vrH_AbaH(sHLCaU+m>;CZz*WGFZuNSBE%~j6=8!*1yCSoO0{f#}oeeYUjxW}j54PpVXGDChNS(G4Eu31Q z@Wy3q**4jy3bYHdCy0YVlS^I~nB>ts@;1IfVXI{vR}24&(~KbYCt%xVDNiD_Vj(Uw zozDb|9#^E`01Q)=R5iGgn}hI||GvnJUkq3!ROa`Cdf;aYwmI8=5;Ds8rw}arr+G$& z8~ri1;ngkXcN$h@ur#L3;1*T-US~c8)hXeN9Go@(#xhQxe5BvU1Am9oWQ%k$z2Uu) z7W6>otrqi%K@d-yNIxO5)wN)w65>RBC758(x{ok!QHgvnw%V6%V}n0}un-qhm7;eM zO9_?c_g{{j3f_%*sR}3EFIzXG_Dkvg>G405FN3}nDXuqER$me(LfK5W^k8K)kEwZ_ zwg?!>-_Dk~J8fOaXGFYDv=g97J+H22iB^{#gNYopw01=gZ1g&y9GLCrStYP7s$pwI zqU(@C@Kck{Yua;~PMd(3&ZOb-D&zhX1L(85^$D_yj~QO2(j2mi`Kc$DaU}7ja=+Js zz2J5-NmoPVtS?IP^)8b|uTb^VsO0$3@c3R$mhZlMpvH!px4M#-(}Zys*e8$Q&H`S4 z2Um$dlUtOJ6_OcLgBiBt`FT}udV6MiCtiDB>xxqRbYqe>}C=yz%0vWIr$Ltf%1 z#jn|tJ(5>8xN7%*orBakp9$@RSn+6f5lOPGB?@8Z%(kToEtviNz~O(;HtI|70!f$M zT2{JX)?!cIXd}W8j!q(Xs~a)A!n@H3YckXqHs#$5s=@dleZHjV9I(mgO4k7GAiNx3 zSCg#w`$k9Z4Cp%S3C1LDywmvp2|@ESp`Wi7KUQaRlq=!uY%3OUcff?p6y{hgOwW1i zJg*gG1NrCmjn`oQ{?rrN9l?~UQ(*q$Kzd;Og1&^N%dk*w*2A)L5}8PP*h2mbJxmml z0*Dp3Ekp?cGT}@Cbw322*Hdad$3d@Xgg_h7qCNfl^#>iKaK~v*@wkm*y+bA1`4$S5 z5OlwXwpGB*ZLiYDfZQx4M98&w+*(rnF-||qfwiZ{pbyA4(89RRCyD=}PH(Fv`+gXR z7IE$pN+2+R5B>H4(3#xqWgDT)7QWXaw-n&r6hQa3>uZ}H6UVmvTp>sDGs9FLCP zaESdu?h@>}i^Tyyu0Y(u(Yp=UYY8cG5~f^$aQkC;HGp18FYG*Xc0n|O&Sbx6L2sMC zL)QK(2fea3Mu;M3_GIDz6DPAk&u>dq#KE4*?2EL-{1T1?wPqWpP9Mmo;l~tq zc=`JWRMPEXT3VU_EsJ7ndHJx)tcH z#>Yr@kG`q+QumXXxt52%e0n38ol7!s-3$n4@OF@XT0t^ z+spv1Z)_BTsWA`=q=CIhPYmT2pT9r6r%%yGVmKS0GgvD^!p^Qz0L9As$z3vild4mY z3=RAm>pN#8M1@?RaNDtYGaVZrQ7@J@4>C0Q8Ka7r&46yLQPB|d)>{2~Dz$-Viy7PU z%Zk;6#BeTJ44w_VrT^-3kIuZ6prRx}|3uSNF6(-f;pIb-{hv|YA-8Nii;^i}5)jMw z#ms13cRnN+BiTrJ94Fu1aresMo?>}rsw45Jw2USKwBGmEU2N+X64dc^#lYl~fqp|p zgL%G_Sz>VG{FR7acreFqKf@n>-SaN=t$6$({ zcVk8qWnlILdbZPL$K2vU1eWK3^S=_Rj#(vVOJRILeUX*(mD^T}osSnb+`UINgl}6H z;h!UBMVTKw6;VtI@W8x&eX6pDAMsTi%f?wZVjf_EW&xPw2v`5K_&^$+U*uGV5|4cP zn?Q3pV<`3_mNWao)~P_+1K(WU*rHo7B76Wz=uMDDrtK6B>Z>Bg_xgl&zO?Sn7MT=$ zKZlCVwZ%Nj5d)VMU(S3Ka#C*D&CF?%g_>wSo(mdz+Gr5F&!!sTb88)fPnxi-RdNnJ zmwVr9>tFuQw{-VPf*WUI-4lxvmb;IP%TTFN*`sOx3ow@HiT7_4MUpglw3S;34n=_U ze3%O4%mNqo&pnN4m=nd>;Jw9|qS)1>o(wU?!&_Q;doZYdR_84*@tm5KC5O?c7%$3s zJ79N2*>|@}gc6xgQ}Gc>97q1Z8Gu$3qYn5RBbie^DM0&>(RCyRmOHCQJO}M=tI%_* z)uG9^uwS2GzIW%hLHej|?gNG|fb7-v(-PFfIIvsgdmzBCb9fU0UBfpGQ)u)N4GX-X6E^Xy^wo*l?TGj@L zL5uXzVB4XI4S!HFspeLvda4sB;!;1ALn|BDJH@;%PdUI}UllAyzUuo!;9}VM7#@Dk z0Tha>7aS6vbEo?>oji}3dgPfN)^=E*&~TzHaqt;`Tgyb*5h`wVN_M7vR*5f2Y z8!Mw(L~+4LNWcmSFu+aah<_`!m(u=_?LR+Oif$1M@h2*JctjFJtuR6_TV6AT77RE$=0pRc6TXIXxt$%kbK(m2^< zpWGP)<_;yV3^Y%7$YyEArp#M|blslTw>&?A-3QY>002@(vc0vd==#LVDfC*Z>Ze4T zg}-v$_X3%0t3v#p^CoOhVqMAq1q3i<*YH6PE+g@rvvCBlO=YBf`fOPyEfBg4cm}=q zu$-_D%23^0vQ7>)rRQ<8TDrQ%I+wQvIL0070}GggrxXaP`sP0IX5-?DjwGgi zLI|G2p^yxm6H12OAP|;yVW2@QjdROd78-uDp8YD=QICjCA4wGXOgvqsU5(p*Y2#y9 z1y<;W>Tvv&QB-MZcfQit4;dWX&`vttA4#QJH-GBvqGI2Nty@!w_Uh!Cq^EWdMafBQ zWEn-te;`vM?{sSkhfw4Qa~JFn0HwxG)H+YCUGjcZQVlH+t!>K7$P0>o*0zIh?7AOO zyxk*9XZh~fwZ8iijCm{tBDrFU2+`rYc^sXA*%>}V#v7@U=$0lb8I3a$6f752HkTSA ze#90eTAO)NxIH;Nt$k1n^0ChnVNVYtP}L|t+Bj(aynA`fQHV*z~QMn;-pkc znQ+NJgau3L4I5n6ZoV{1xF|Z(P)izrPJ^pp!1R)a7=#9uUUOVTsuz(ncC+e?<;qh= zFso_fzyOTIXaoxc2+`I$9?2_Xu@vuK@>#FF-EJ1Sh$NYa=6Dwq=j9;(%+GU5xhQb3 zUe_k{i)I)s^9|WVf)4yc9a~al9mu0ykX|tPvsAniZT=0I;4G?;lWobcB-ke%82X)o z%qLt2oSfPe7Fjh6AaIVgYZK+MgX4vv!ny9$r|LW=%m4$0rD>Hd?jd_iS6AKg3<>`5 znRRx}kn-uaD=F`}*2qkND{)x%d_(y<&c=+hYqr>qp=FQ`AcP;j2r8>D%S2 z9N0s|WuwA;s0{a=2VN^U&uIS71P|%_;ev$d^}p^Xay$1s-siwX0@ogtdK^Sfc|{eM zcI6k2p(H8(kpIsH2YeYgkW&wS_nF-%FaPk_UUog`wWdV^RddrAZj|AIrnNm4VW5%H zg+YY0>+6_jdA5{vK=qAv0ZOp>R%o!^s}KPy3Rq7 z@XcY1>`~;4Q8pn}cmrEwV{H)Wl0m8s8yxkVH6-#?xxgcj2{ z!j{`N_mmlByN-toRN&&B@|pMTtCP?66#FE**ea2l@N9Ej%=3pH0KPRQgoP82x>i(^ zPGnln8F3**>U_3jk-s^#9-PMSX7T}}XE%YXKW7GWs%oVey!2_KPs;Fx)g)y&lLaCn zOg>V^Xcb=)%+pmxjPB$X zvdMQ{l^oAed3BAc16%~-z}_$c?xS&x{L86HCm&2`!#lM7J)(vX&1m?#L-AL~v2j9m z3@@aiF~TEz^@@q`_wA`i*|?6(i7I}pdM`+~f;|-y%uP|PCwjs-PC&dq2rF6ygtaXK zPyjaZqW@_I7;a~x>LDFIfCDM9+Y3B!l1@+?C93vL`di`RDNV-7a5lRucN!=KY~fBTCPc_s(UTSm;Y zO>R)@52FD$hfTlxznh=9Ew|ARJoLNX%xDIRfV@(xvk&U0*@Vgkx6D7#=j-fj%Y{~{ z01`xXC|nVuRpMB<326lJl$g8UxU{U!JjntaM^|&h{6~^EIr-M1-L;t)M8n~P*bBM} z37|x>5jF}&HRV8QKe59jRg%thA)Ev(9{Ms2X)lFeuQdIA;e{c|J!Knn34<)ygY0FGRqQWS5DX79fZ@+- zRIZ`fpMk61;_0(Toye7iYn~R&-P}`FU^u439wg_#92Z?DcqWRi>4^iYo-IJ8mXw~l zchy+#0%POgRO%#F!rz{+nQk}N(uaXaZ2~^ZyC9_Ax66J(nCQJCarQ*tj`x3Y zY;_cSBFL8YD4;siqNsYRW5TPms>V?tT^}ENKlq2S!?m=t=d%7dYUIFh1P|!!Eyx!2 zXudWxwMftUwG)7}N&RDpS)bSY_UWy`JZOK-W$pv&rQYL;^~=E(`a!uz=$xS(Doxh>=f2Ae7&TU~vE&7p%dPs>U(GY;N&-4j6s)g#i--ft|u*W>;3B%M_z=Z_)t-$~w+z2RdD zTQ{kZ0QjcLD1EzijupYMyXw_o;kLJ#mkW|gC*Ooklg{MR(mNq>V(BB#Jc6okN6YV! z$b|w@TnUCTrmV`xS%rrdONW7er3HM1yfeeYOqjZozTX&i_B8UsXgQorqzk!HBJaj^ z2oeeiwAU|+R*R{fd=rmIvjLMC8Cp0;^W2(&X&LM)F)0h$k*4hL7&^ zz~=_dEX1eFwzkVwWdx@dt~tFN@S-sHWPNkr?^+?4^doqO50T9aZ?%7xp>_EdG&n^o zmTqjR`RAzpe+V?WL=9}T&BCfa3oN}xFG$6rw}{X$ZP#=;TQB)G=gJs{&S&oV7abeD z{RbGPj$ZD;wn}e%Kv!$$mnM&Us9)4bU@v~VcyJeVU^e&<}?>=wtp$bkO=E z1W-dUgYZ#YnXO1@$^$t+LnS8Wvx?N6 zrirJW&|d6}fLRpZ+>P|H*3{M@}N%^5QZMv0|sXpoie4s^*T7=18 zy`-bw6iQBe5_jts<(0{Ekv}xiBR#(0Qp7BhQg_mGekbZbV0Amcw6C%Yd}}yallY%r zSR&DNz5`~Q?SC08ljIPNKYr<37z}L&1t}vCZ3 z8Ys8iI+w%u$z#jA6J6ciza4&FF=fYW_i5eOrgprnvmC^)eAR4V@%PU_>Wjg! zU%Tjvrey;G3>)08yA#OMCz3rkyU}evC#M&QfC6_&H4YX&#h@XmeNYf$w{*|Ev$GS} z65vM3Z%qhReHhJ{uCY;j2tj&y$3GLHd0@IozvO%WMk4(i2V%3Glgqj6edCSds~jIW zITi&fls%B1jB0=Nz>TDYalJ<{xOdAhH5EHHc3#WL`OMQ}cIJj|ZEfCx4ngOO7i+Z~(XnD9aC6XH7E&p`b@^ z>f(N+{_aS83S1bRdc#Qe!g}68YWUiwB)C@HUD088n*6hcy0)G0zy>f0x5tEg_P+jL zl&=6RDeqC>ZVzf}-FRhyvz=CcNx#;f>S?ct-4PrOmwgfk`R+RJ@cLSRQf?rB(p2&0 z*=X8S4nOC$@d)3Go-!|gL97r3!wfKg@p4-4&IHWclQgv-I1bkyHMJ;5|LrH-3IXg{rIl{n?s#7M#dy9Z& zX{_Py85(C*m!(wO0#W!ytXZ(asWjq5I@gXtdQr3B-c2KC0mkzzGj6(Hk-!+ry5jp5 z$VNr-P+=?1J^C_b8Zee*Y@)8BEv(CEvQDQZY=^URO$1m_Us+E_g&o*MG1_(5^vu*| zQ#$#usQ%-(p5{Yn$_VkE%$k>8+MPeXtFvZQMcJ3qGRVPZ-?>MRixnCBb_O(-i@%q| z4-8P{^!<^tEX_;}Apg6OIY1AVRsxOCQ>EYG*mEffmL_5U@KEDGvU=)6zw3l)e%qyS)>HFB3!8sT#C&M5{@n)oQsRW@$gBlbpYqi<> z?pK4>=hfj9hSJ=mtCiA+ONBVDYLflw#L_K$t!kD$v zZP15e`am?c%HX>SnI@tn$=k^U-=H9+xG%W?I5y@hXWcsN&j0VQ|!H?U92ksGG8 zpL8|$&`K=tb9V{bg-$!Ing*mp7Y+UkY5#W?06F-K*f)sidYiRF^V=EJYoeR^;T;v7ykN!k4C0i#hvw77 zsy-g?Sb4+BqA#daqb~J;fSaxo11&D!ffzFM)W2sJzWB&ng*h=X3)uD;ov7d zJ5!JcHgq%OD-96Fl@a=d2fx}ctY4N2V{vLvs2(&c?n*M*Jdoq#6?qzL^+Z`In1j2j z^qJE`WR*|5;|H)XQosPwUl9RKs)ZRcnEe^aY#=n?3jOvGZCG-!#T%WkbYEBZff{yN zQMpF=U;pGXXMJjbNT(jIrtq8NF{-IDLg4n1`6^jxZFk2M3F|7L`Rt0&7YV0WS(3Z@ zPi4IyTzpPLa&RQzojq2YEO-I$J!w_l#qiaAF6A;hwP@^4z~1qwdKgI<)pBwqygP$uSE_tFiCc3k-+cENr6#&>Dxd$}n#=6T%E7?S zZ}fTm#eb-0WY;4mR=ek|?xsLW5f;C8y7+E3L&Qw9)cpac3V*eO3g$v=-C)A80I zF2-Dy+X@vP47Xo+w0C#)%H?wO=SzN42KLtz ztz)K=NF8pJh)2hONqaSgl&i>Sw1dKww~)_ZozX|rS@@Rq8Btz_&mM1`;0rLouc%n` z{u5#3;ryG8i=LAzttfq1z2wbH{)=07f9GRlg^>w;XW~}y?#k$mmNnz;A)gqc=$ehs z#f^(yh=e%qk#Mf_g?1zOCZ#H3pQ$O4Qg1KfEpq`m!#xemv2oWb=R+&GIUHgxC-%#p z6B(wV?Vc0OgoA3f!23|+gnsk& zr3k2lcI!KXNlq!+QjS_OtcLvPl!XmPPc*n$a=y)OV#}VR8^&lB=Yv9 zkQlCSeW}eG?8612(b9+<0fbM=eqIm_3jIR%RK|zxq4RWkO^oShU}eTn>F>?zSr`q{ z`bxP$TgU^6r)$epxVGuJNli(46?I7uV>B&KmI(F#yXDbMD#;R}z&;{~>C1h7+jP${ z;gqq&Tn=^(OYp8Gqt^K%*~()9L{;~6V=B2aS09Vp29 zt(QWbp}uHWk_2LA#^5qI==XfMiE?{}Ok^eyZpYdab860aMm({DNFg{m8AH>ZqKh6~ z1;97!DqF{*#q3F({%(zzIO9KLkR71e&VaU3?J}oY$DPKJmE9+_0Fl1`-2jllIGV{0 zMagPo_gQ>MoT^3&wUq%1e^vwAp6kt(?^L@Or}zAQf=`r_@>SZY#sPI<+V7a=9UPm3 znUv#M`Mn=@=E|I$D5aKrfUmiZlo9enPx~jSR$Jc^kbO{ikI%uy=hgOb1R8zjX^m*` z!z|TQD&3H9V;xb2tVGrO!|QiDsvdr_P53(m^Wd7mXm3d`=iHIE4~G!Ias1qmA|jLb z^Dmzo<#sb1!}zDY9ijOu9l=;9=4le-D-ul4gB(-D{|7UPLAfxPcplU9MRF`88ZFPh z4153R7U%Rw)50Hx`82ZC^s+~^0vy}KN2&yDT+dHRh58vbV3{=R%g`QP0i~PrD-9a9 zJ1~EzsxdjS_XFfTrW?plG&Afd?x)rXKrk=zlcHb?}u=_d6#Z|%gbk39CFpLdwN7kUS|<+`kZ4@=Yn z!|yuhfSf!EqvbhOT#N*tB|FWpbB3owF0-ybV61znHzLh`h!>!5Z@At>#zNJU9 z+<`R2}Q_CUvqYIWjHOl7I>Iu+n6h!5dciSp%ZnyCY$@;4AFHTEP;_lDl3zW6$&tdmm^bo@q7LWS;(#TzM>8sfQrt z$E$#hewKY>rEErH>p63h{i{7_E5kB?&_8L$GBAM)8kB-Y-TZ}Mt{@sVn%Q8dKq=G! z*CJ}lkl*G%nX+P%vk1q>fqg_PR$GT~1pdH zLaABbN!*+y&kgCti3?|hO5tiyDRKT|#sZs$^6W)n@}llDznRCVD4N`9i0$@E9plY+ zSK+!1@oUFv*53}y_tuO!an!=k_cVF(*ccUUI+c>Ey!CR(Kz+cchGhLtJ(?ZrR$Tui zW40CghO!%DYEP}J`^Cs!zLvL5i1re^Hvj@Tuf}raugD4=tNa`l*MbBhdNrKBTz>>B zy??eZA7snB0v)lNUD9ocS;I)wy_e)P;;Cbvr+)aESUzZPptMTd{VLUcQnva+MJnxE z7P{u!!ld|Rxh6m#_iTT~*Oqs#)RW%x%8=jsA37+!z3UXMmU{^_-GYyj-X5{M?7iqc zKjzGB1}@b_I^(%oVO0X>CEtn-;j^`HA zT$divaIX=KHNP%lLSa>#3U>Vo}jZjo$+k9>CLzkiaxM*K*pf2o-o*~=cKd^r|?mq;FpK~ z5p(3@l5d2A)NySwcWQ#Ql7tpmz)`7cnL~N!<_&-+#FN)aqo5*vTKki1QJ~>={kaUa zOhM6nXR$AIVAel&-ApBFnM=DulFQ;6u!~RSlL+~dpCvq1@zJFhPL$n1&)F{rL+n~s zob_>d)ZKy+qH`1_@?9~zqw3L2IuES`q9@#b81L1i%j4hf{TXQtJ=-dzijORd?JB`s+mDoOew<~&xP8UXU|9G1g z?9D2JJKo9iPbp)Cw_kP@Uy_`H6f2Zot=^iPO11F9!2y|F+vWyPN&a8_d9&Wo6m%;o0a;Aid$Rz^a(t@JYI3zU22sK$0IdRHRZSbuD6z82>(Je&Q9wZ{9fT z)SOcj)JFzXM>lkeJZ`_yX(0HisIHlfQi-EE?Z75Kxmm$jb|P$R9M-xb-)MB#jmj+) zlz?dXi|h)wT7iA9CP5Mg9E9+eK_qA%EB}QYj{ex9 z!C%`L363W+i15mET;~8D$G_foPf`uOhzA-#o>_mtx(kPl2GqK~z>cL_ONv`%X72n8 z6V-w>k)3%StijF!dEQH66Iyd|a9w$}l!Sh^K%{iC5P9=g8o@n97fxmfH+lL5?IC}x z;RD#o=yI;CZw%iZ*y2ra)a1f`!6vmJ8QDLsf4%uGJY5rwnXtJg;kP2OrIWc{`vV@C z7IRn2XxDO}0PWnWH_G{IzE03yKF;MWXXK;liD$hh#C};G@wN=|4l%#ak69A@XPIqo zu^xNJg>5>h)BdCxI>?}l@M(^FhJ0^%^S!da|Go&L?i}^zAGLWl5Dqs7=NWP$FWP5L@ST&9{*Rskz0DWXi(z^E@Pt@en?$5aI&;pv)5 zn{~m0@3vMt(38Dl9|OlEYpKG)Ar=A9CV)l#bMw*mr|fRL(H~Q*B_4F0x8Hc+3RTFG zP;Pw5M%Rlxug*~PB*ApB%=%*=2+C=9XE7jDeXYlwt2JeMUVS|&Ma@sw36B0;NK_n@ zGm*jSns*Go+E@;C5*8{d{dHc-6oGT26hA~ib+E2X?-HRV+=64 zumG48&jwunW*>Ha?$0zW5K^t9r$@4ZzBAd^k$e}yt|eP!rx1oJ8{GsTeX~m}BiV(9 zK>M0XqGS+0)(953BJ8l$U=5mk>%VH53wnbDDHxQK2cIMxwtEUO; zs&Bu^-B_J=q9~T{`nfR+nOJ2eGy7x%@5bw@&P}evh@nZvy>=I3-#^nUz2(51X}>o| zTL&ZkYAE0(Ux_<<8%Ic~lWe?YrMD$8)fO41da?eKK=O#ZT=#bvr#*&|u`)Mbx^vyx zVr&AyQ%jee_UDXgYwtam#&dQH7lKqAgBOj3Di}$29b1yA6}vKgW^4fg@EfCZgQb69 zq{KBe1?j}deS!<2NC6|D_M39MMz$AR!_BU}tCs!P zl8ZIV_VC`>45mA#4}`M8Y5_3fD2&!Kn$Ir#j#NQS=24)+(?D(osMRIpn$F1h*@UP> zw>*Rpe%*azK3uXAE??CsHFlHj2G`9USkLigvIsx+8M+myg3yv^%pnuCz#QJfmhUJG7~ozBFMeK(?3V6%dYg`gg#8>-kjtx_<`KlTb zlPj6aD>+0Mg{2dR+-u2(c9$Jyzf|+66|Ie10!X1GWx2!0Tki559=0AGZxKwps7g9? zc`Zh7pGpJMq4$51NS*Cyv+T!KGoW!2Jwr4mVroSJmq2eB!5fO(8GrKd<~Pd4pz}ik zfkYElgl;_i$7Cp`)n-W`T^>?;giiXGB`Y76kKeD2@^BY64o9OUaa-)*zr?`Z2mL70 z0JRQ;zQnEE9Ug$O{xhyMybf)sddSU;xFYl#I^ku&*dYG4yIyX54qI;OMi{&NbIMz_gfCv z9;9Ywelftg7nczk0%UJjDkpCD)-NbOi6GC+>>Z)XQ$StqulI0j=~xzkn?)67pA6R^ ze?F*vznC_E(Q66jw{GJo0T~*G8?D$0cf_2-ZjM@cR9NnVO$jI_1@Vl*f(E-8I3aI; z2_r>z74A`3r)uXXO{d<2vW;%>Sf0#eV@ut)RY}hgTg0Z z_M|b*k|OR4P2D@=EL3E8WK#hL#a)6ok2v3OW96R=DR!W)7K{-WHsu3Eu(ovi`I!dZ z2eKL#&+aZGg!`x({}%5OL2z>WYTmDM|sy^C@Ee8)y;<;0wvYP*>4ZflRV zFH9?#p8>1E4J2vl(yMakla?;eD~Lp zxV5Hg*BAV;RI*vH9!AWaii86cKWRWQEb*aa-0oEgs649cGLO5PIf{OMTisYuO2ftC zuH5pc^xvHPVUwu{XKId1-XCwY+;FHl`B&`BOyu)*5|*7;ey8@+2EL1~R0+5QT0V3g zy=dssIk%m<=N9C}4{~+VOG8gAKIu76vOLr#w}?w}g*!8J?iLw8i6@e|V`U8P)*qRs z9#fqWnJrQYzr?k8ohv!LPH=bwns#UQAR6PchsZBv^*i!NNB?s*9^}1UsBVGAEi|~( zlhHSaJgBNXCYw-4pYp|LaiWeOu9lQOeVr+4_aBwLN!f3&203|<)>OpYwJC=)CtT}( zJq#NwI-G@BozgsX&q?-8zL3C_5meW*t+Ua3K$dM4{9-rbc@UFRTfZMVZ;3bi3$Ovf zWK2a~U%^ZHz>XHzTO}gUcl=1V?e)aFQ@}4=UOWW_oY|Ro6Rdx?xQhUSV_QbGF4ohC z{kL!If@UP>Qr)&rgEC^Zlm_d_I1OA;3gSU+_^Ztn=p%GJmyhUZX+qkjJqESR<~=?- zaDS0k`kvuab*@w@1}cb_$6}@)mBfNN$FS(&pU2Lv=tvh17{@3IZ`^CjAc7sF{`5#= zOO__zkNpEyJU1$TxyxJy#n+|>`}2#|SMjz#DCWYw_#F}GG$SaV{gE>e&K^|n*Zx8i zr)M`r&R=!elC1FW+AHkm7s0u%a64$vhS__T9;#`zE|kc3Rkz4A4U8YkVBzChMtukn z7Qbl|FC)VC0=iIQENRd~3TMEJ$6v;6GrI4Kv$GueEQp?69=|^4lrkp8b_?-l7w-mw z%yrrThZQ^z1ew9^Odz6oLf%rQ2Z&Ap)g~ruFBg0@Xk?h^MFgnSxh5B({Swap$3q#9 zboY?b8I9wSl=;v~#Oj#GcnpUV(&5$!e0y_&3@ zU!&~fBKVr)Nceti{ko4()SYzke(A0Cx80&4@lo@hEWfXw?R#~D2xO=l?uY8eG*VEM z$#>DEp)Fcym}QGhHV8cL(?l2H4(GKJC#A!ri5!UcoC=+}MgP4U@_YZ1^51ptko?c; zWNC$+@5p-M@yjPkA*?yNQwBJSYvixUm$3?_Hc($Ds+@rrilEcoRGLwM8LL`;W8On% z3t}+yeC4M03phJg-k9<($dj=r(n$>L&B_}(j=#1TSwn6R3@SB-b4)gk>3xmh6Z+}U)mB*H`EOz%>IW6!xNqb$@|dYGqmLvP#~dT%B#JK-~4{MvM2 zb>htYU<;X!ag{0BoOn z;Gsk&nW=UllGHSSIYIgGS2k}H=yL8yU{e7~Qyj>9FtYrJ1L6!+x0~@5^PZZQ4(QU0 z$QAQ-u20&fbAHDMMas|*aV7Fd(QS=JTXl;`^_N1sA_yDDgHSi!6U7V(uCOcr z{_`06Wb#(n7P|J&WTjsGwa15LV>&YiId`#6Q-gnmH$;Y*ahV0RDl~LEz(&y+Xm3gJ zZcUK&cX9rAjzNvBQS_;UU%sBbMz3EY&xG&BzkwnCZu38qH5_SqvH3`c#1@?*L9||) zD`<^CJx45gAW>_-(_ESZL#jqT5Ki}>Njr98>)P@`Q4X|$w#(=@6KpoukER82g8Q{e znk3S7CsTg3M!|G=3L6K*;k}2=OGU+7ZILj5Ki9WGdNJYT?;I{C;!e_Sy-6_ik(3;O z(qQ9ax$~*Yq=Aiy#hEltUrEAd9p*q+3W-tEHv0r@B=)IWXx{16vX#3M()uy_Om0(G zt2%M3H32>Rx~$+7T9hd-np-uNC_LxOS+=Mle-U{7kpyR*%Lau-I86#eU9t6v7;WFp zg!CUjaU?8ky66W=F;aC~^blU4J85a8w?tE|7OU!mG-#+Y)thyCj&s!Sn**vzA^HwBGyY zd8V#IR2eS+wIxqxhsWSW=?)sF=A)3xhG0qJ?)_RdH^$^(!`M9LXD#V*C*3Xu;! zP$eIHq11Oaupas&-Ta_own$7mU6-UOe$&wGsTJ6Pjx$QhHH}(mP3q(Rx4WqD*G`$L z8-kVLyOGuZF=WpJC4;{`CBF5!O$Y1GLl0CJx%m-c;kh({+!1qR!Y+JJ@|^$Ee9C2o zc8fgJN`AcIPe+8;;~B1ii(@=Z=BN=?y&$p@w@BG}){;wYCPGxpo>}5;(1EVAGPgzW zHDE1=`%mx4@LxvLSv4BM25ucWPG`qVAanOx)GCus`P#Dfb(hxT83;ZquzNy!teO2j zG-S8VD#>S$>H$F+ao&nWOZs8*d2ORxwH`txuG>~WMCr5r#pR)?F)$Rcp%&`w!%pNCqY2HHoKLqGWTz2sY|CQ zJV1GDfa+bed9h!OUM~J?Uu_>h68JauxcJRf6Bxxg;}UQ8c})<_31L+G-~8;#;uFJJ z*-nX1Rhp0;m{H-WF-`a9UA-db55f3^$`&*4_^|)EZBTP znQC+0YK>a1NBryM<;>l7+hMqQ7RI zglXNF>`Zjr+6hTuvw1hOq26Omah7Z$DVt%4>l9hQgHqhW{aa{d;y~JWwacA(Lj7@{ zHV>U&eO`L|He@J)1g{N^mz{T7CI`rzJD2`=sakWZbGUamXzMln_rNi6B&P-}Xs_$$ zfE+3m9F>o(Xh|LryMv;Ai_QQHHL}A6lOM)VleB8iobhWtk9>#1n!?zdAaJ}~iF+Mh zBN(f>%;m39tS|EPWxe^KN)xIsE3YA_Kfd3SdH8GJ?Fp^ax@QGwCn1qRaYl!&zQ?YI zfo`tkFr(|<7|lpa8tix%pi)r+8wwh97JIP`+_TX`ZE$dKyaCxb>lA@_j-{ogdA0=c zS}a<9+7Nr+zG?`Vd-5R9j*ABcUjzx?q!XQL!!%4m?QpRU*}-a33HiJF3J6C?%>u6QZF}AMApkWe;bXSG|7- z`U)>;q-^mH&w0RieLZz!esV;IE83zIi;ft7r2%M*JIqBLU`is?2qklUu#1`ZX&-CG zN7}RI@YcMz`rTVfFN!7_LKDeKnN8*v#&Q?LQEE0nx8Ob5C z`YE_M=qPj5Km-d0Fhx%Pnuv5chOV}Z1t8w!Xg7#ktdW;?PF?M*ODg`%Ury0g`4K6x ztp7GoX4{MZ*WnrlE&4^4TCobGn5!OV1ZQGL)mqxUy_+uZzz>6SH~(VMabhCpIfP&- zhAY~$C4FRB|EZ4ed+%G)3?5j>b&;ZA+}*xQc@o$AyBNtv8@{lIT6U}skM(aD%stsq zxx0M}e@+THpnCzj1#R8CBTEk^d7J+cLuj9fe9pR`rMg900xEot;W}slZ$0#~VHMQt z;&ukQZp;GDm1O(5CVIvnX~KXNbM{8f7u_Q)yF2y|_Ew5vzeYVBwldpy#uguf%g%^1 zb$QNJO01^B32zm^Sx~Yh4>EmDtMR4j<&`*p#!B}JDd^pIQzgs`|9hLqDpzl%O0pNW zE>Egr$2x)x@&!fmrSR}26VD;m0hWhr#Kf%%>OU%4s_J*5F!kYU83VX$a>;H1;G->K zX-Q{@19uhI*Ie2q3{L;~8wXErl)>ilJ(7(kg%3`)%dgeDo&YBVYM89g9m$EA!%~RM zy+KY+c=c80GC!}e{|ways>tfES$e@36L(+y+A=^C53Urm$3qEKNC_U4K&k0w;E*h-q{!Tci(u9 zfoV6PVjc>4v*vIEj%&BFrHqjA4R7*X?GGZTo|@zwj3ZrI%c(2|e9vH$mR*1vp^=(? zavM0focu0<3b068`?(Cq{|wK%#3F}3__uS^AW8Ql?RJY&`2P_KL5+5PTZgp!-}-x% zsMG0zN4{%41s_M_UVA{4lWNgQ9b?2F1*LYs7^1d zAk;b!8PyQ-!WBp71QC()p(zYPUvKszoC>;_kMOTcu6AhdNQeJk`E5RU`hM@ul0%2E zti;4C4a_Gl@!Q7(S(C4urGVhjAeS5eq><_qNxgR?FPDtXK2h!-PgB0Lj6|mTJ&*@4 zvg!K)Y0oxTX7~KOnM`UBceh|1j$&&DYWVgGmkpJol{~tZxRx=>TE#vdl#gayC?lL2h{=rO-{(nJ*_`fC^#Uppy|SG?Eg$v2r-UsM->vZOT@gC|35oy`VUk5Mga zRXo2N>SKZbha9d5aWyMwHYFQ1=>Z;J{*Ol;t{7a5f{tQ0ea*O^FQ4dzv+xToK|6Rc z+EHJ0)1vg8F$xp(;_mNsyh`F2Ag>okBd8Iyy?F5v&_a>~ll2wrD<7#B z+3k>TH;no38wK^jHm$%)S0zkDJa!2k=rM3&Os!{g$|Axt%-; zf0glWo?in<#u0xl`qh!~9CHa|Cbcy~i28vNln4?};8?+LgaOY|0U!=64{@KAX8hhk z`r1sr->yS@!qI=A7f-d`$^v=jjZ4~Ksf>5iY6l#NAXGQ4e+;__Y>v2AH*T??t(~1|gv7BxF|2_E_H37yE|2g2PZMchZd8RGoKyoQMEK{5 zn?li-2iaISh=!rFqd;cTZJzITD5y3b*6Zd9RoKEKsj5A>dhy9tne^16Eol)Ri^bbsV`D%Zrp$do=Y` z;-oNltoy~74#Kd#wq{{YfFsD60nh}43Z<&A_*jk#;V^QM`wtxcG;2#ATi$=;?*;ZNj<)#VkPp7F;pm3+ zQG2ky&T)F2KM%l!E9{owv_dYyq5B`bfa*?IQD=x|2>oFC;w(mO-nmha-B}QcV3CH+cvT=-!>6a$WQ?p5@lA1zA=@6`#jaqyu(&PhQmhb`{yPCW^jy~lVIW-`Sc7@-(MyS96)UK z)lPQ!Q-CcsJ(>fE9yqAKX`88&8Y%!}(O#iF)^?yV( zGyU_fn#X;G%j3`ph6ifR8EQ`hGE{i@T4L)HhRfUDU!t_$0ZDwvTN8r;H~_->s$XOE z@?Or_q9UWo9qn8>6Yv3hcCvNQu&ks0IoV@YpnhZtG)p12&dH7YeZ*rs4g_ zozw#ZZlsvCRII+wnFE{jmJ0>XHIwB<&)H8(+PAvTa&*@A(pcho)!s`j?vhpiE`i_h zP)b-GugDf7x88A1%0Tn~C+G6lIWo9QjU1Xad7q?-G1~77;b&v@Gs~6~e6*fbVm~{- zPtxExNk}X2we-IUyf^qP5Z0&oHEEK&vXG70VxFOBZ-aCI&X$p4*9RZn6t{8)*|~pY zZphDUayCzzBb%(SX>!L$e-!45+|#dFlX8j8Ha$!eyyNzYVI>gH@@EK^<#y05S@(!6>V#|`q?y}&=X`(Ex`5QT8{PQ zy-4%7&B^%a*||7DJpR(T&bdY6!l7u*f99V_SUD1-Jj{4#_Pb7knau>0hN57g_iKKn^(T^_?=l_mc#EVvGF#SimUowXvysBDFZ(uVCXjH?l^y zqjY6o?^Hn4YB2>bb3d6BEOw&WeM z#J$FWoBk~~-l+)*&^7*B=spW33Y*qvOkoEN?E_0*>FVi>jY6EYy8OBqk=>u!6Qi)-7gR$j;15odR!oZbw*eb61=Uo-{o6fOWVVOr}Y0r_R_!On@XD7jOqvg?3g5$NMjm zA6uw&o+~V)ZGb9Siuz;X3F}R+AAVG9hRh8(d4Z6MGZRk>BwkRB;NkX4M#er-F9=(n zN}GLJ0Io&25tn2p()bxGmXUBwT!JkpCM58X4DzTos$GuhR>WIwxBUWQWyQ%Pzkp4? z->Z@$ZDGrWK+;OL(qXzuCdu!>SJ+hY+clLpLJFw95kzWnFY^wJ7dX(|fsA1k@_al^ zFg@f+mrgqe<2Q~}yAH|qTY6a_VN`Us00H^cPI@B%Oshuxs%DA(YKSNpaYa-)z21z18s@pY!~a^tyn?*;B0Dyn-eXY6mm z5tx)Jio=erpZ-^-=jrr^-&YVNvm@yHeD__u*w-kh31?(R2fm2i`*sYVR=~ShZot8^0gPyqePPT)dK}TEYWuH~0pO4d&!> zvsieiFa2b_eT=OyCsIbX{NfDe4OmxqW?jYULTio2k79u(D0Gn8AvsT4{TkR#YU_`^ zBsR(5p@luHyeYksM>dkx?-&G69FgE`WvTyDGKf^-)>(=5ruR3nCVbIZIr9SyQ57g0 z%>zI>fQf;Og`^WB(s{&3wB+yAmHgB}hyrl3n}l+r9@@(3k@60%BEH_J;RoJS+1^Ha zKWcdWg4NA$o)$ol8KM9TuMO@9#;BZ}j)ARw1{zX%$s0AbCZ-I`{UE1bJ_MSz)D3os z5a0u}V2Ps5beZS|ncqx>3=Qas@7#c1d)Ahsp6rYwg$8UnT_=!Dm6syqS0#QYH@1b# z6a^BZPa{-BgsvX&mHSI>>ym9S-+9SUQ2TKGE%TW8`0AS-070~u)A31t&bQr+yf3u!Q7I*GJhC^d7umFAiB;LsKgCpl`638#zJB)&eRmi>=NQ9X%k0(J8B$& zl5`(@KxCc637_Y$Ui7m{P>izTVoY)s4z-AkiQm7V7K>mKNX@D76e|=s$tP0DsO=ALYqolOGm!wshuv*JE>~5Pmy( zGJZjTxWR3#D55`a_!zR>)vWEt2pplKh(SY1ejd5L&nu5u2~vz`o|o8odfZ^mUrC>k ziajfaGQC26&918S)~3Exx;t?P@o7)YE{0s-RvrnEG3RI3taB^OR6E~b3ExN)%c@H6 zIu<`dXW?r&-#iXhSID)cL|`m%ZF1JC;@sL$70f0m=9OD^Uo?cD;T5qw5R?fpS-C9w z1%TaLjo&ykBvO^&L)xfo9iMQqIe@++A6=<4;kZ|ix>w{g6l6Bx)T&y|EJ&P3t`Kf{ zoxIek7>{;}ss3uDct0^TMz?P^GC1oC#dZ#gSbzb>87aZ+RPlRl<4icu z($W51RFShN{p_#fCl1;tJCyHKW7z&fP6RmbE}C|LXezSF?KS?8eeWh_BGJe;?d=|4?59FFsG>-Ir8WyzYBfe_60a zA3e3K@eCy?@WI)eVng?{j^dO3T57Yw)|LkcB=48Ut?4d#m9C@9H_Bqa-~;sc1a)$B z5x2Sjv5DG#K5&Z(+-S^fF2pJmd8bVmEf6az3&j;f-aF}$Z*D|aYDv0j{lwPoip2kP zt!z8=bNI`z@o`WJ_$Y13fmgk3|E-l}A-Tu}51gQhw^|DwWQ7auEq9SwKpnDbB$t_Q zGcXJ1nvuRf(NP8DH3Q@|SQKZ)XM0qKDH$Li3DDA=p*LAGVIk_xDY5)MQILGl)*WZk zpK!v7)r)W3gB5CuPo~mq8}SY_0UM9S;Suf_h%dp#+c6IJnn+@_cgVQEoQaS-2+1+r z@^%0DAuxbj>!{|f=Rw&ID8(j+eB_>?<6-g3#KxE>*S9^cqJq`^6zbH4AGmlbDrnOv z+zW8yZ;zjm8nyn<>cPH!_iy!t5bqg06p2mK$yyA)i_2~LevXw+dEC#79?QNdKoea! zP;vMtTa(s};UFArqW~q^0#{q$()z#yuFX)0K8X@NWVvz6RJI+{gk#Jp3?u4;ew}Ud z?pkUYlQKFv=8V$WPd-|%C1irz9IK56Vw95BTbHQw$t*-U6ISyL{ zaNx03z9O)SJUTS);x>kz{dkZ?Qot z6H9)@@^ra>Ch!oV9h%RJsVdS$_y5=q7+RqnvXYIYKq*FVxTa1x{<c>1DBOrGj(Sc$oC)dJr{=ImfcR2Ijl1tAfZhtxmjA9piYKebO7m>Jjd#3A z04#I&2y~N4xIA4eivGk#7#(5the}VRWdk3LHZuL^z#4=rzuym=tI5gYMKQLF(XEaE zApL;=as8L|vLRCFWpm23YSGE0`nc9;K*|627~O<$HJPf*7jFyRR`-2B;_>=syN+aM zW(}DQLWSoOl9iaVpYQ0ui*2Ue%~hK>#x1}l0pPPxQM)oa5a96Vv%{ib`&4X|UxRGTdrvl> z8pZGD4O$^+1xl2zYmT|Vx3AnWAn4>ss$bi8eYh=K=3>G4bwx4_s#EC6SoD@v)EcaU zkAv$rPrva+vatJ00|-n9QIWYqNQYf~f<`qtQz11bPip+e*^T2A=vtnZ-M#H~C*XaF zL0VTu5&|*6E3)At(rP16tNndy-v8!SULOl_Q1Wu1THZ6rySYu8diZm$M;z;T&#o7~ z1*hOnaa?pI>A&HYr8XbGL=qN*iYg;%0p`F@XlxWo zTTaoP-90Rq3|So7>c0WNNl}L$gvEF!R=N)(e&4-8U)dvE9k7Z|V!a)hJ;5l&$rFjo zxQr9-7QZ*+*M=oskOBh82<@8^y?mKHsE!xH z6-%n&o>j~ZHF{7aKc>n%&k=aMQMpGM{eLwx32~rK7jk%n9=uWEL2_T-0uhvJH&f2$ z4!S+k6{#I1?_=pTnSIdpBo0*A+-xAdVrlFD>kx{%wzIt6u#WlqYa7U0cM(?Iz9@Fhj#Wq|8~b21)wgA-lcn(|*5Rx9eCcaD0LT;`d>Sq3fd>Ah zi^o*tu9Ev=&Dzbi98vrDHnTZ_Il7J;n{$181>2iL&Cd?ZD=hokJsL-feqvnShABTP zc3;BvSG(RQ2wPf>3%hZQ-Qejx&axNmeUHsyc-baJmJOH-ny8E*`9;BEP|lJ-%wm9A zFu#g&_K_y&`#dWN6S-L`_^BEk@yBu1HxMW19T(MpgIpKu8>=P5eLwhe;Th!`B8HF3 z+9F%FY-YV={`thE?>pTJwP!8MzjQHI6u-QzcJOi9Nlm4>?lq{TLAe4uj8`^@XlI{^ zz}F|73vJaU^(kk*>7UL|bgOQZlZ?-k{LHDcYhOgQ{>dG%@PC4_q9Ovs&>^T%@ zgPcp<01EZRboa~J8^)i7<1)kGVN3-2% z@IR~MKg^BIN_l=!aMbnFE)MH(LF?1G=JmO=50%KMF~d=nNuTY{lDSkAor$rCEucC& z_=Nf~-_>WpW0x0=yv1U=pVB?u_YD$X9bdulq zW+>2_st5NqrQ%MAs+^qKEu517qnZrTmLDnOhK?3kQro{@ld_c!G2!5?wJ1d^$N--q zXysGPS?eMuuJ{$rB4DQ`6=vIZes}=~%Xe4kUQVWRFwCuxd;2NSclW7Gdm+g1Luv|i z8&+n1-t5=`8{b8gk0;PPEwoQLE$LNW=}B?xnIX9mfat|qNz;? zc_>w-=A{jM`gTzwJFv9uj}?}^r(b>%W|w#&&?9OktZgL(Q1w5{aqUsM)U`@J;_)nD zss-C!mnT$GFEy!mqO;A)NxL1jF2Rc6UN&qFpvjW;E?k~!O;E}+P(#IdI&}HRAxIHC z(7ev)KC}Ldtcb@=FK~B-c5p9A!&#g1&Oq#I1iy#tpt{WMf{Df5G9@&q+;t6wKiXm` zqrh0$>`-$P2*^_KfGu|WO-sTcAIg6xc<})%rQ`<2Z(Vt~(R5)@2<@K=zI(X6r)J>n z_D`W|0dBp9DM=WDEM3@!+$<+d{C+`Exq||r54fH?$jxrQPD#lpo~7uq6#kj3RBq|n zE)W;fw=*f0m9|-JDb~c`^#;wbVj2{bFr;MS=K>sfD3EGd`AZUpR`iMQD}1aehI}T~ zso~}JPZ3LfEXb#^6SLJL3jXt%@BpiAKi0CQ=Dw4i>Dwqvi1}f2i2F4U@#hcc1)S;AVz^RY-s0lEc4c@CnuRdsULP+o#Dbjwd07JJl;^LB6!d} z@f5qlWoJ9m0tr$FLxPA>FiseA*ULmw-IupSxK3+IyKE;-9zRGpzQH@|1#sb!IT_MZ zl}71)eadlGsj53+`PR024J8r3zO)a4S1WLadpFq%mcxL)sq)Ik;?TyK0k?qcK7%f(VkO9TMHe2{+p162eBJRTz5y4?7I^8i6HZw;D^HV$ z3(r{KJXYNP$m_{pgbqFxwVyqYf7f4rffHB|6|isRbKgeSA=L6+a4){{C_vaHOPMhO zPJwL@{X>fkzq^7mBp>>egcHDEY2;t*OdpU*>p6;_9>Z5(>k&-Vwh$VhVx@L%9`xP~ zQ?8=@%?&f@o5G!+?#UC`V~?%egOMd(tF+{cdXZsdjs=bk^i!$Q*tY5p{ThA_ML8-GCz*oy^?cW7oRe#`PhdfXKvP~^- z;z>S$MS$`QG`vr5T=j0bKQ);IT_`IBDlHTP)v28Zace=0df9@1qb49?j8XpSnlGT0 z-w=(x29=+yj?3&n#lSZlBj3YZhR+0=nFWF-AhPVD4bL%0JgT3NDg}d-8+>!mQiUjZ zKLH-af1WV&JmKCkPp%;J8@LC+>DwHy{%NQm=kH1liu?=z$3)iz$c6pXydDk;?J_g% zu#Gdh9eg`0M)XM8;4ZkvU*7VO<(@5P-t!m-3!&-de>AA^PetqO76zXBw-r+ZDK#iXkBZFSF}+YRbF4QVLs$5ol><>u*{Y6H_;|(d~~i<*c3~`qmw%{F+@=m z997Dtpn81`xmj2)LA0fzX(7DBtmEh5E2-Hc4kNt)%o4o;f)w|j;1-~dAZTxfZqUm> zAoIm?^fDgxQnT{rj+Y#~?>66Y)_bnc{2Csbum&V9+&Fhh%D&h2C z2eU6W1CvZkJAJ6W0WQ^}9(>|ZO!T}l-ZEfT{jzl&Z*KD<`;<{l)tqA(kR_!e!|mrt zqTqP!l_CZX4!qKY--r*{xox1sczUrgQWup?JnASDQ;_L{lEh%i`p^VynP>Idl}EK| zT&F#;l+M;>6fpo$ud^Hba>XZ(igLNlw#W|@JWSt$Y`6JDYcrzPu6JD-Xkm$n z6zsJ4#*%pZd*%}`37z=w!{k>crhN;vLT$`_s?>e6L{O$|ZepPEBwzW2Uki{DfY?^e z-obpKfwIXfsp@`-o->_r0lpMfnYp>x%JX-XX>?R(p@o(kX6|y|<_CNw{B{|8W5}h& z`52utgC18f-S7hCuE@r4mw$xHsnS zJMkf9|D&u$;8mJ(bfJg1ee?%T*4Z`SG}Z}k;Z8XsIM5k*HSp@{LzpXvYOgAj!#>X7 z=?X2b)5MpQod4)`=d?<1?x)6~cd49q@Qwj0vo#?q@{uM(7D>+1mlP{X z)U)OlP~d5zVJ{qe4+x=(^#g$HxkLbwIfUa?U>y7*)hFU0!pksvmLxxG0M-hxXw(L* zHvPH@K)!&ep6A3=B@ev(IA7JX|yv>2~6 zD+QDv=~%A=>Ix9H<=N@?7gE#e)#)+Z_J$=deWDm=sT3?e`6@d)0FBRn_Vg()cfE#k zMOm4))$D9JX2D$%kzc=l{gD3BN8>$oZL+!Dc$}(1aWt0uAlvtX0{bzQ8WH65_q-Ug znw9R$BY6#c3hsP)4giO$WAt!tk?&Tw>+Zi>M8qR3{4o`(xlCVBOT$MxIhiBeIJFXF z;c=*K5n#R+;&_yp_Y3CG2&4~|(JJ}E?Ij21fZ8k+G**HnJ{E8+`_nDqO}O|}swege z|MQQXQ_IU34oqV*TnTo6b68zC)YI;O29+i@#u*yHbA{hnVZ+hl?no!dn(&-dZP?`* zz=Hd1MdLOjBx3fno0a<$9-kHxpr^7T*-K!0SxVp z)c>;Wo0VcQ6V#3$y-gjfcDp2P#*|Lz#hB19?>$Rz_#JZwGAC>c&;3E49R|v^gdO73 z2X*Opu>HUBVjr19v*W?)9p(>0`8<_XMi*tY-eZ%-72oOBFf-9ChV)K*hp)b_ox&|z zzvFG`waN1CVZCX9$(;yoq_mGRwGdLr6Qe#0d@BlS*OyKVT$l;Eo+&F;26ZQ9mxE`j z++S=-`Z3xDK|~M{4skWLJ&TOwRI7y1bWTTIjQNHwnQ+|T)|zB|TB?QG6#MjdZa5Z_ zg*tcavr_8SoPNvi+4=LE?qzZ~4J7+t9He7%smJL8@CCZmv4nVetro%ZaTb;RZ0dhZnP?dcYLB|L(?ont01m zQ?fTA=)&IvUu#{P`!BHp_oT-YayM%BI5spF$Eu@87v`JJD;OnApi!(8Dn$un`Hm!R z4^|yAze48J)_a;?UHp2ZB*Jz&@_VdnPlM{o0zpSK&l#!6l zk%ydv+y`hd`C}S*hvfS=9Ulu8tB1Hp>Fo30Zde7Tw+D{xl3quogdB2W+mi|WabHl5 zzR(`8ulsIwxQVNL5_f2|m+LjW1nrUUB%x7LCr5bv8RhAI&BOeFVeR$`{xTrlvt9J^ zR&?~Jy?oEZn5}p{fD2byZyzY{zE;3#l6f<1f1Od;s1Ao61L(8j{^qH=uhNB7*$k#H z=Wt%>mTT>xHu-&jvjaUACI}>htMX4`$+_|dup$^pg=mTS1p1$~C+96s2QK^2{Hk=? z9?P{|>l3A_CXa4y_{OyTKxWri;qA8mhKs=xRW(YM*Prk|!l%ERl2Uq>)wy5q3k)<9~$O+GhU zIGWLu6(}K0=4ENxtT!}<-KS>P{8%wR-ebuys)24|qOf9Mcp^FwO5KD=kS;4u!w!wf zt-t8gZuIalE!dqG?fhTSfNENL99A`F3(Th*{rEj|TCh)smH5Xe#&k-t1E~u2ZOc|_s zS5MsNZ9jdQnI?gGXwRzidEZfTZ$B$3`qr3!fr93o`*-oJC2pLJ9b^GKtlvdY<<&+n zO*JpMKexH#;iBvgG`)a@B(V#cd|Vyp>i#Rt{wG?! z)Bwqu#XxYU^%=uo<9bMt@Cw`8PrKuSGi6#SdkM&}<&vs^w=M{3&7tWu3E@S6$f&33)?T7IGGg z^@|e+-^wN@X=?`btyRdcG zfr{OP`5jvJZLRQ+&lgbBye#_}?1cF5SB|)Ijf2~^JyQQ3eZ%nBW9ONit^e-H-ffNz zKj~6p%z%U}(k6IQjz+f7BgON_Xre7I@N9gl%K#EH?AH)eX5wLVrV+}%XSEy$eUSg; zXU))Ox@hBJ3yP;A{$S7$V=#`$_!01oRU_?Z4e}&}SKN^q=06)?!I>HP?$q^)LZA31Dk6qVT1@kohRqO-PBkD3^|vR4UT@jjjS z<{ke)+VE>1H*d;NX2`owJt}9ijq*Te3A|UeFJhaFXyCp zdbu3F6NRn)0icXN?hkL+p(94&jIYZ3LpF3`Ujq#ZVif|K=F1Ymg>C&?*Z|4LH|(c8 zWc1_6QP-7a!1xjHN^LBF2GR%A5`8 zM7~C!=Dq3W(TlvSw(VFa&0vWFk=H@yUSBK}&kRGueXkP25qZ*)pMgFYUo)Rx_0?fURfgL^ zG&G3A2x$xR^4{V?C`NEl9UX5h7~a_;3J$>vm@3&0N(?p*hT=pwCro9CA!@9TrhZYD zBbh>sjJ$<5wTx|G`s3B07fg>6ZpVsLX%#p9|Il6tFTa+(Oyw{PojMfhNytzLoI0&A z#FiN1irn^)fy>HvpY1$(USj!B?u-94m1f&KCrVn)&AM>oGEk5Mw?M^S$TWV*X2bM1co9;|S}rE)X^mDHoVUdGKs_Qu%eGt- zqq*M@?q`h&X~SiE?5XKd&-2Y#6}b2PRd{p!{&#My(gxGx+#2qKmb{wqS!ndru5i)N&kj``TOD+jaZX=WV%=wiu!~0uyfF8^R5*go=Skl!3Uls*2wGI%) z@Grf>)#>%G<7dxGw#g1)t8FzQx_KGJ6dJ&8aDlyK(mY>m=dzo*lg}JwP7SU>hZ&%# zcpY&8b$BI}tY7CMigo;e5d1ZmqrQ8rD)jnbFRFt3Md@3`%coT!FxO&Nmu1EA$OHz9 zzExtz>kPNd8Qpf$ox6}&`#Jg=R3~2<%tKXWE6G}STlBhEbof-r$^1@B_Vo0~mB{PBa!EgZarA zyr##PLD*V0tl_h%6=^Y*@Mz1{(@@vT+o>H_IqKAo<_c3ZVI5Lv{%JQwCoMJRB(~I# zY#po@Oc=7IQN#K5=%fde?IZ0OGup}D)Y*a9GIIzBso+@40<`${P0CgQV~@WZRY51a zeB=s9aT&Zb@Z@=E!5PStB!-vMS9@VOGszFIqB)(_3wC5T_mchr6>Mrs2&rp}Au`k1 za6>5#oI$ zj%{mHu&5~^#zJQJt*~GnRQ*hZ0ns8OmAx}2u4T7zIZZ5R*F$gR2dt|boVD)~T}I>j z@Aj8dFig2BEmpWwL|6OSc!ndT?J;ZUEk15j(@xArPw_k)Kr6pGA@IZUQS) zdlUiD002kYiV-TmR(sqrf9&S35_< z;3NE$81W(zxUGoQ$X(xj8k2W`2f!vQU!RFu8me`m^DKC}?LBG_|z#3h}yADNPwdhD?%86n=6CZHO50eGTL9xEUKXaaD{ z*wX%YbVSDn$^DyCuj7Ptr0Q7e@CB2iA*eJ9n|9q+9YSb0Yl+F>7{>4N@{S}x&*H?*CEYJ*uI&V-W*<_2s&L2YRzx7sBm0Hc5K!Ll>TWg*h z=})6KFxPeR@=(Lk@K>aSIJ_T#MtST&x0^YjjXi*xOEHFkm$*|_);uj^Myd&1@Ulpd z5k2<;sCg&FMN+JAQ2SxEyna0=y$0@Oj&v|FfG%LF9`Fjo1GPg$=hQ@iCz%Dk6;s0zfsZk>3*t%hu-i93d?Ry(e($ zHBS}mE1z%wm;$Ev=@5AGU(!_3{|OJX zl6n_(&}!J>YHUDi-ehXw!p)<1#HpMvy9)FeH*N> zHls&c<1^E1SN%DPR$>Y0QHx@?xzCaZUc4b8A<_P19Gd@4arE<-goOyDFHaToO_UZ& z!x|bIBHFVBO(9Hpj~@faOgwUw0(*4opNM8ACV;N;7Olt=*#2ylRNcJm6zACQXTOOe zlQ7b}=TnoDi`_lUxIe&Fe{f_QAhCk3TV}ZjN6TkYj;i`-G_icS8HrKHeY6b`mH=DP zGqvwc?+hdS?5aRzR7`7md|Q@QX7q$RuJ|t<`}_SP9yzmo6uxbVSX1Vh9pY+jW9oT8 zHN+Jdv@%3dnQo5Qi4g$g$u@UvLvlMdxWo)AsjTNR+PA?W*_|c$f_wf2Qo8nbjlG2u z@u>oz@NMPB|Az%Q3v+#Zh%^q&HSn6B6)mefo$RWGewLy*8~D5j0-auL{w_;RA7wsK z3mnlnr|`+T&-ZNg#rRq4XOECjgC8}f$7fiMkj7R29szRO(Kl@bk*V3FD@UiH+}oP$ zFq6##Lc_iUE}rYx6ibcRFs{R_l8 zjaKl_`Pr8c#W-lEB{jgdOP}{Fe>Wspb`8DzHlg3X&Vy3IvZks;jBEF(gBB`3(-Azl zEq3WxRecSFLAB{lPEBhEj;--2zARL=uke|}c`|EYI`Hq`BO(+PCAhXVF9#b?9Wg-A>}F&N@+1Q++{Lri z-(u|*=gi-aY&@HB9q%O{rF?*@-3r#;lRTAXARjJ(s>J$zg&q~v;|5zsac@uRrBtpR z5R_S@s|-qIj4xXo(Fd7psabnJ`wrO6V|)|W!0-x7Meqr-^Yac*=?>qxYAhTo*?2ed z(d_XBHefaJ#H9FnUv!OPoHIV#?tXdyr)lLI&iUEDpS}H|_y3JGaq7i%<4^UF5bHwA zG+K=n={;I9>%%T+Zzn?(SeL`fd9IT|i3Re* z#cAP^5X*U|!8dp(XZZsBS&C;{b7nnt*=#T7ca@TS=D>%nf)k$E^!usQm5A+F^B5Xa zpWBt{2PqewPCWp#h7oQg!7$)mN)WW?TBq8AafDIDy7&g)mOH1jb1g0G0!J$7mI0pz zHTKuPhk^Y0KCLMnXuFo1a^9Ytro2O(o}46w`QvkKC+=eu&!v7l z12$TA<0?_<(%eti5tbxxHBRq(e=9~n(`9E1+Ln@EDYIxQ(jzBg{ebeayJZ{XjE0i@ zDn^|XHP)&+6()ZesnIfzAa=PR%ljH8FZgaaO>uEe&l8x)^YU^^@l!z9Uxh*$CdKU& zglJbrVGn#`zDO#n+!A11BxvJ1(E0J6@g1L?~xZcv`*5uN+5} z3sLQwBjS`FPjo5_0&~ruP9;h1xCokcuTtmW`F-Ws02Fc@4Kj2~iR>8yj{E@PM=6G0 zq43LTML7REbybQw_M*^2_86nQXLZ!Dq!6?b_5{Tcik+`@YSshKF6nnoD)ZdvZ|={_OV;1 z6DV3^B+a&2bWbGUptVlYe$<3Zf)6u2ORSckvD1k~v+K7du}XOi3XZreF;R+X%0N3Y z$F%LcjVg({IljQRj_K1slo|KrI4=Dg!^chpjEG{Dx@VbbE|i^ER)qL^lzhKdHxM1D zozYTnkQoc#;!04eeGD=i6L54$DVg&ifN`+v-!iL*x?c}g&@c23jm9fN)&@N|yRv0j z(?3n>+olOz>H-2Wu{WGq41E3h#nw8flr%+GvR-*+3v16OpOv##9-hA}deX>B+|3Ru>&qN>&WGOPPn8O!f?YLz0&qbAS-_}9;(OiQa zU$_yUh1hGF4n$mbQq67TgCVvwN>dKWgE=6N{}T7deJjK_0H#Q{P%`p{S<0Ui0h+}@-7OM_upz^`t@YK&p{z?gK;-8sPCB3~ zT730CIs3fq=%>}o0^qJ%G}fmn_Z!atj_H-$G#7@+Z;rrp_-_!RTU<@~Ie|C|XG&Y#OiK*jrv=n-K+yX&hnAstPPyhVgDkcwnP7brFV zDJUbGE>{Km;Z5(U8Pg%W@2Hw>_6j!NeQ{ay5K{DDxB~W>hCmCt`E%-l5bms=XMqw< zjaEZ5Ce}i_U1QmQ?xn~vD4y`(9u!u|wTN?_wM6u;KI%N`ak3oR`qJxCT==f(xaGPv z+#B76RPx$kpD0(=Koah;mp?(8;%`anjLBOUm%OAq#HtMUhN$>4-+oG2^Qq843T)qz zT)xf}D((1DLsju|d=YWJQes!#cxk-}K?KGv#bB*6cms>j0YZ8bAs))&FsX) zw=o#Kyuq%%VzCK&FQ*3d1y!K9epab!ZPWIbRz=lvXyyUOu7-wd1eX-0;Zf6m>pSU$ zbTnD0oVl}`NjaMo6yp!9^I0H7kUE(QOz86|#kLop`tbUcm_m9Jd_qA?lV4>tjeq;- z%)n3=2em@YXWmZp{1MYMUlhgR^-VjMXvEONEBu|Z8ZDbpzlZZr89E*YLO!bwr&WaU z_pl0Scc;Y*`1g=YZ&sXAaKEvBIjMoft1UPp?v(I(QHpqQHl|FXIA}|L>N-<%XB8{) z+t3f}ebAXZvo!buQ+kJXXFhumtQ9Iy@ya+?xi!%xN;>@t`OZ4t-8W$sqG#HGm)JJ}OIs6w89wI#4*%YkVa~_2MIl^RMP2gq5cH4MFfjCNoVliU4`%$}VfJq1 z@|~WJcX}3H+A65L{-oqna|9YDMQ(aLJ#BGb>n;8OHM>T6PhUF#DPsj*#faAPMw4K$ z#tMs4+8Y;_YUynN8(4A)Y=8;Bwx<46iMmqG_Pe&}p&$37phrrdMK1e02~n=3o`kd< zHY=u|q=&S(Zk1^NoJu`+;)~2jDB44t?6a?G3>Z*l((SF;NhUa97T$|;DHQVZQM3Y& zLB26BSD-FT`wQ4+jURaW$^l+yx40xPgy!ha_7oKL>s*)=9pF@7<4bEW?e?T`(bTV2 zT72Q>?pt;UCSOQDCV9$7qH8x6fYO#pQD=GfoO>-*J__POW#T6siG!|Ac5@cxR_+(4T|B0Q5A? zUtoYV7gDEU?&&)aZRu%Xy#u7m;ONlg%=ff?vxlGVsJ^Fn*fSaiqpq4Ybjl3|1}TTQ zodLGJvE9HI2)^8}&~8eLHf@Ih4R_-fH&cWa8V9G@@eN z_rf{+VBcA|>qr)x87?@WKxKENZ{VSnl}ebp9V&SpGB0Fs zOeFk<;{97)xx;zZGetY4=ZYvhffOct=Cxk2;ymEn^+?C>{>`B2je6tz#5V6X9B4L3 zX&Z0g_IZe(P4buIpG)iA0*DMl`TqErwl_PJZ;>TU*cAZ>H$AxU#a@8Ai+3H( zJZ8oZST`ljbz~DOsNvyIr^!Z9-o|OJVqTKACsO%c)wLI>h#zkQiPm<9F)|OOKCrpf)naT>p3gR1yy}rt z&o*cCazrI?-qUd{t#3>l-kUi+@jj~KfQ_zw7F`3mRiq6TOgH zyxJ@2)U@6ilOnk|Sq|4KJI_upXigiZ{C#?2XWzeiAUzLSB?kmWeBS#?u7FHc>*H5? zS{!|k!VEt1hL7e0J8_!;#51u(>E7^~tv%OQ{tD}Hn0?>s#z9XaG~9fuJ9c6^q9B8K zaJJVuLa?I7NXu_+n*0;#mnDzFFyhOG|BU=-&qc{!v31UG<+)DgEP4X}PF|+R#=3%6 zUzJVI_KDPa3#tUXuHxv%Z`8bgpnDTb4AAL)$Ma^WDo-(poq0+lIBIn~jFxWD5TcO^ zBj5OFE+DH5S=#aBs(y9IqrR`%Xayaa1>$`GMU{%e;$BHLJ%E*ZWGL2b_M7zj_Kjo}%2E zeW|ceov*Y}MdVDnQlVGgRUfJLNqqrFjonSn9s^7eLbH@nnOdO*8O9vz(lB5Bu59=j zo!nY)etbg5>C6_})2AN{H50;HK+!(+EwaaCO*vKbedts7vM}#*vtsIom*fo|jDm#L zw>9JvJ>SdDP;@f;-I;B8SyW-rbisjj9&g!BG5bW}M>|ft7k^0jH4RZlqbfBvQM4ks z;0RLdhj#@1k6)>wj@62`FFfKiM*tpM+eko?L*xNeI@x zLRR%bshaX4i>H7&M!YYzO>Dgw_6zZ@X`j-+ly$hN05B24@gSyjCWJ?G_(b6Y@k`USprSDK*xe= z8z zocv&OwoE>CH*R)jPNey9fcap}nq?^`zj&arpbeWGgn;_MYl5 z)UJ`YqwsfUq5AN}nfFSmO76=Cn0WRWY6>QJw@6R!0vF-$+s-z--p1@qsq0j}*EjOM z5idRZj3qdy)9cTt5`|k$GT9DcggXNj}CWSx0@u%^8_K!cR$EcY2W&E(_CUHPyS@5>k=<8#3%n~Rf2!(yxc zX|5wqu3d7g+t%3z?_ebQ6$jyy@wn(Opf71T2KCMqQRmR%5T1nrQX4`xt`?!h1m)E( znNHjo*Zi{LZ{MV5{;ZwK(VbpmT+}U)F65MwaGX(1$BlBEiRfEc>}Q)ietMN@;%tQ{ z6zLJ*>XM>VI_{v&(*an)*ur8v+r&})jL&#+kW}$#r67raO~wCV8<|}A;p4q;S3>D; zt!A^G0t0u*@QLg={vNg@L{LYRiE%JNG;3sTc;)Rj`9=wKf2ep@&vg$(oooB9fU7Nz zDaE`U!$d-zBylSPGI)L;4ULt(dHeRnsibcbrm3^ur+hdncBGesaU!;+&U0UH7;Qx( z=B-{fTp;eJ6XbHV)am{F=BcQsHsjAGacSUGWKGM|L5z74a(QAM^%BKxPNM1I-(_`Q zdBa%JSaJa6lMD}QC{F#1y&QP@evi@Yx7&)18OemW>x%T%#Zir*-NupKVL1H&=e7!? zd@tkX+5 z(@>lmu|NN`CSi5jgiH4!#i;%+mo=L(0$vt)vODsF^xfHZ7rNQ~_C_?WC`1#oczlju z(WGf9;$v#dA<@%=S>|}Vv1PSubGH2%-8`vfdn_P8yfT|NYPy;`YpA);HK3;Dij?LM zbJl@Lmq;~Vz|-43L4*&(fq%@uICBTv_%{*8mGyeC{FQdhvOirahN$-#3-fS_phI|E zQj+!)!iSz0FGvrqOFtcET8Maer3?<@Yo_HFo^@aRxv?74@Y6Ua+E*M432Lc_g5!G_ z1bqF+7kQ#x<@5*DZHu}>EPqxALyA*U%gEE7iuW#Y3vG8!N)0QIg-Wh(+%!(vk#;t)f!1T;Igi;Ttb#pho<+8DjQ0oy&MI*X}el@?(-4=!S&jZo7=8lnb>-AW8$0=vGZ0rse%K)O_vH zae~FhsmdYdp452j~2e5@3Qgbt>b1?qbzEe5z~!pv@Y4-Z9> zAU@}8zbNBv!`RS^H#;=WD;=ZmR|YTH5(-v+{m|*+5L2Ge7$n`I>%WnBFbTHh6Y!m^ z1^&9O;=J>MorF+@7poqsWYI~wr!bS(tz10`I2%A0OdZ0gRF_`32` z$Gz$UxbP$(x=xW2ouA=F3vX#wl!Y z&TV{t=uH);Br7W$)>xE>YpeROr*^0d0Ii?i2-)Nqr;MuJ#4{0=;=rOPsR9}xGZGZ`#slYcy_NCV;>OFeu8M! zky^4IxiBP>{+{yKg7}yR zLMX%(2mI`y!1pHYAr(gr?={Q!g{Pl|v*kGnIYq9&F~^4qVL!ZMUFO^(KA z)D~6p%5-e!e1Zq}I2|v~w%+oXGhoE~Sy3JY?X~V71|Uux3mw8obxatqB2H~RVbG_A zC&T1TfHxY(n`4Me+E5<+p7oeDxiCY#qyJLX&uEDE_ivqFQGK9yFj=}j`+_^*I8oTd zQZ|&P2m7tpp92tQ?+PnM-Mc=^pAoQm!Jts@V2^Zt88fusN>At7w$^IpgF-ClfS_@hT6pw-APc9B|eId_|d zE4N5Wt8}T^gek7!lMZWQ_6mt2D5;1GY z%vluTKf2EaICjy=JC+=0BM?)J99@}7r%=$ylvCs-oq#T=mv5$MiODAy9>y8%7+G4o(XQN%IB+yi~z&SbH!#D8#~NcHtR&4#*L^c zUP16a`T}A4rg~v#<^;<;rh_Hzc z1{lKK?-rTvJbA<9wp;SuSNe!xYvZT7;QjN!YaT&z#}(p?OB81CBSK=N^Ss-}(| z{P`wcK$pb#@=&4$qx{0!1=+V(Q&!^Rzev7QvCrZDIz2EKB=6V+1nF}hs{SUCr`aF< zAXnxK>a!!(9}yIH&eAhi2ft8@n3nVww_PjoIa$~X)^i#ZOoQ%mOQX0H1_H9ml z!Oq3KlW-6L`Z9HrN<^ZJL;44YK~Xb3v5+iPJ3K;KDnKqYbBWj~yvL~2FtW16D-w&F z90l}Hx41gn)i99nP>YkMB0YG+-tJS?05Qhw&CH}ME-B%rx_8ok$V;Eb-s$*8c@}e@ z0Vn+Satu1%JZux2(#G@3-568$n2%V|K?;ZD)00v5}ONy$m>&oNBz$&nv8g>8RA#T7xFy9k@`(&HGH5^RYz7tt~yqG&OgYtUi3k<5)?LA_5%y@A` z6~o}>BiCR#+M1dpAbKZ?n$-lu(NUl7W^_isAALc zFpiR#cE<1*ZOj+}+l+{!r;NQx zb5H&vyyv~zGB-|mFTdAhV1E8mngSv2-ElRb*5@DXMfJev@m%m17eaZ(uX*pARTs>q z*}2BFvd4s}L45S$pX$^0xzgKvgaBiXQ(~egi2n=!k34|_-#d~|KMhN-gX7y4S4iw! zr0t?H#_SMv7XLA2LE4Y+yIKORaCXez|3V2;C&%*tO-)!bs;}4L7hRN&z1| zVo*H?&{31XWyg<7%$sXW>bArBMK8*HmJF$(|7Hp*@{W(a5)Ho`adGBSa|EEsv01io zJunh})*0#OKaWJ(h2A3F0%%G|hPiR9F{KMECoNooPhiv*&RA_NlcgUTUa@NZ+X8Xg zsO{IVc}G*&++9S3geA3$u8wV$UW7uA^7*QUOeS2OPUCEU(@ zl!}DrqHztB3mw)>1kSu_3%?A|*Z;UkS#u8v&#!^P>M&e^t5a^Ah|MvfOcudiTlD~E z(N~e>+&Hs!F(qjYEq#TK_Xus1ylVuWT3W8Mo?`G(Es_Y$%ht ze8hkB&T6NwXR1U0v03Nu3_$3XvLw_3c+mhB4$%1iqp4Zh$$~XgracT^oqsH6MCiQm zRvFz(J$zEnT&@8fowQ#G=mc14xHgpj1KF&l=`0x(MlD310!Q}Oed}XAUY^RYci=3cW3APGY_5^=lL^6JCF7-k=I{jB^BJ_%CM_?R!AgHkhzmKvg5r7_$z9KM02cjN z-L50GU?W11^FnXU$+no+Q-`LNME=O+g3Et*Gm_Hbki#eJ<4ji=Pm5+YI##5-WCHTy z(;mr%O#@y4^M zJY@1*vv^r&-&t%!qVJoQX@$0q&iB#LH>0=w%$D>L5{oBB`nAyvYj+8z&hQ)Wzakdw z>{NKy7f1THF!rwLMlnt#i*c{jCvWrj3nTtW(ZFcsPeE&U;IG(Vo(f@O?X@tAA6)HJ^i<<}hD<-EnCblbv40_`?;Atw&?G1m6jc`Bzh|p^MD?4zH_opZik|%f4lx;oa zF=c9XBi&;d8H@N|Pf?bEhQ=*^*rDRdEijE1aCBnv6as6}IG=k0)4(JLEt$^INeS%Y zyQO;FKZjSOOmT2{@Bw)-ESFi~-ctsp5i8{Gt-vj4$eDVLmk~n9Rkc$yl86JDQf)*$ z*rKP~`>kSxvkysD43r;1hH%{2_&!QpsOe)JpfmyN7yacUFlavLiKHe0@ zr)2X_vWb5^wwN8|v(yvLx+I_^EyV_vMwmS}=D72qh67&pj$u#6Fk)k4-FWf8%fW2(Jby*fRT9OWXqpX(~SdxY(pq z>=2Gn>D075X3H`A3DLH!WDV+NPM~n0Rs7t>O3hUA9i=8I*ZcB;gFQoLz z5#vE>nbi5KcTvRvRQhsBnCiafJrbw#x}81}}$+OXQ1a*6JDM+F!p6HuT1hHT&aP~`-r6t4YZ12VHP%BctV9|)E~QQ>>~dysj=`gtJp+`8;KepjW^{%vmU#2 zOWTsBMptYHyn|!iAM+5C^W_h=Y6u{^Y<3cX9rWEq&&~q5_6s7sBc|Sjf+4ID1XC9D z_Jw;=>^9IjKc3o~@ojuoc6Q|~ocV;UwzG@Np2eVDpiPykpGei4>b0^A(|0G{lTOm% z0gY$g%}*GS)-R;hryZ5-?ARH@M?%3x@(Rf?n4*qOifS^&L_tPIg%NREsC9QR25OZE zsvX6cL&kU_b)&Z&JV7*09tvLi2sHCr@EDW$zN|&~#CmkNKnm<-=!zX@rGPqbhC7|u zc9K{uqcCQQ!GeNyb#;2wvKe2_cE7s(6^V3={bYnK=s^gD9(=ZaF_44{cf=9Sv<#2z z-JN>xqvn(%WAucXCB_Z2oNgFhcXGn+K0y=LT0;cCNo_I})_o+V-!osnACZ7=TXAVK zMVw&3?+H7=O?RH)Q)mj|L;P-?UlFI`V5ZXZ-k+)@tuq}g+3}eDl#$60ggiL%f@Qn2 z8)M(veqFoynp#AP66DI4q|d?72jUVVWe;{0dw94GO6VCM_NEk?V3o(QSd9#o*kw2v z&_?fmJ%Uu#PU~uNSGCCMf{0i|H;xx0vHkuK6=DQ{h-B@hb%4&sl#Oo05k&UBso`uS z)7h%uM+euZ7-zo_#_oQV%`3}xPxulWB*@i;+z*9w#9`1`y;w=Xggpw^2@_rxtn*}y zT`G0sR6&yT`03)E)}J7U6}WCJu7C!uo6MVz7UY~x2BNDq;n&tVr)v>JbwHRNhT6TN z-1UYO%PkVw$B9Y(Vaz1zSmfoTkc{*Jisu%)FFJt2H~t#!`Z_(&Bv)9_lV_$X6fDT9 z)?a6)F+z1z+95$odD?Am+4Z0vpiM$}YQJ!bZyIj=;2$0yu|&Dw7wsF_3%1A`uAp7= zyiM^cWN5}Oo3F)q=y%zYzL#e7!H@LJuBY*eJl7i1S7r@RD(jLdEpfPQ+7=%fc>*M( znr?>_xV{=(>Ew?xa^7NsQM_~5Q#b!u;^-TX{V6}OjDsRh( zcx40in`@<+@A~?Z>uY4afL6P6`fTsVdPK^|dY*6!>rMjM&J|#3 z{q4R7lPHGD7xG9uV0!Bu&3x_RORftd+g(oJxWM2qcE_}5>}m}G`dyA~039ZlCoq{q z(T+{ni3Ld>Csn%mK*dK!o`SuSKUqjBNAA|0L~VJMD@en(GWa!Jx0*(VB-%uv2fXOH zyT1Mqz|9>txNCE4o9^QpE64&YK?9 zoZk>Os74Fe8-dG|gJDavaE>XvnmfXzuKZX$1&4@L#x>mL{Gz?Xu}gU42}~v^vR>P^ z@_7_fm07{VxElC#q?19~3Q@4yBLmTJ+4sP_3ih2moMzS#Fjn;3GOEK-(t`vD{EIvl z%PZ@md8gk)P7NYDAc@2Q@-M7j6!u`mDX|L(1cmo7;RjB3i{XhgNxwtYpVnPY1J=1F zTrDeu&pvP1eEH=gq3IQzb=DN+)dN0|Mhw~fv(O$vMKu=O2z9`~eLtla$Uo!19vaOV zIG1bx9PsqicP)nPNooIYf93aW!heS@*!ufZ#eK@p*MaVVo%fyzG|#h^I4FI15mLQ! z0qR*Md6ol-^mkIG5H_jq9QF5nN0cl>yi8%k_Q4z5Sjfp{LX0zQ#b+9(g;m+GN!E;V zs8zDA6%1&0b9z-Vvm&35kie z=YQrtk{4xOb)JrjRa;O=_%}RLN@B3ayhUwGrSCM8|BzxuZqk4|>^vG3>-uk|mnUgf zh3W@8lHm2iC^hf!XoyN&#yol^H{-6%QEsl|W$Kc0kxRhRa4*=P*?Dmg$bvH(Af;BT zlN|WfNH96|^4R&sz|K7R-iEWi2g@m}-TL0$V=dec$O@UY>huH(dq*cm&DHazr`LK- zv4R@i6ExxzS^Ua@r&=8W{$$ZdSrJAds;BLtm5<&z9>JE3&TeyW{EO6Z^@bKFBg=x= zaAU)}j+1z)r*`?9oR_{8lUEz_kPY;wh`+Y2oW};2%e`OVb~NZ{mzB%I>^Z6?fIQ&p zVrW|dvcdMS4j37jY5hn0JuBm@BXSJRjDUb&^>`K*L(57_ikGEv&@WHp9+>=e`9%P6 zF+u#U_a!bSK$mmTdiJI&cf<@t%}r+y{%Z3gtKoY0bZDK-((jFJr5S~o@^&#Mh^|dX zD=!5$^HukC#{*ZY0N8mrd(W~NlXJ&zI9;+li5A$#V@XeObw;CONfkx{Oa`LbzCAZ( z$eYq*r&whjO8*@D?F}Me{XHFqo`~5oTR1`Po0@vsr#tez$%L%=$HV25di`6~IllGj zT(x9$7S1Pe^PMSUD%(PO+Ldp^a~3#viwn}rFG$QudceEVh^U>=<=kpB2wc;XImLC& zFKG_AUh<6BFcvx;ErtVe;WT2$d|Rvzv=Z&?ta)Cl9lz@vN;L7%OGgF{F;_{GhfaF_7|^f?Hw47xZW*x@_VnP4r^#m89q<`++?xwAt&Lp z?;a<7_j2-07hAgE0B6mkp2DVqjo1m#E`Q<}o?}l7L79&dtL4?kezp?@Mn0zbx!)HA z4!Yp`q@@`SYl{heWP9?6-{S86aVr<$syPEneHOt}f9LnJzxYa*@_h3Nos;=+9v-`? z1%!tWND3ymPIxks9iHm^2U znvUp-`?wtG21GqWSClDfh}LaO=EN&(GZ;$Gdl(X!~bBz zg|b(Cy4OgG2_V#=_0ecU`Rz0qb*o*IWz`zH|PV3tW7b3?5o*&^&(4; zhB7+f4JAMh;E+x5L3w0Hg`F9(FC(yYX;WEwZ`FhXPgq{)G-@2;cG0G2glwh zUr<@AdbObQGbZA>wnG2!f20WP_J#1&u%vF)RVsiq~N@h;$Oz9 z=wyVi#0VI2z8`9cs)*o{IX3^4->TEDf5PUDWFiTFHR>jo{3kXIGGt9CMM$|L%LcG+ z(+72Y7di@>D|T?#4y1cCHqCgQ(p4Z=6x){Jv4o+vuX{yp7|6GxLNRYRiFygc4m@2- z0M!xN{#CDjZZLV_@qziiOZu|qwc~DV8d?#QWnOpk5GDY9Z_TmXaghkCB}}yaThkz& zQhKzlCmY@j+HAITlTn37^pO$Lj`xjcZq*pTK!_13BkyIRJ+iSqeNR|*lI{nE#i21V zUv=+)r20^G=La1A*+Al%cDIn2(RWhN*j~Em5Rpo!2sAvJmtE>GxDT7-1_V^FCn+Z@ z-LXfb2H<7b0FbUyvk!JmB9nh${I+Y zq2T8Ma=0BwP+ev-1%5|48nYd&U|ockzZIb_zpc!~?K`ilEu)*J$Eep=Gv=dY<3jj~ z%WCF5?N(jqbyUAkmg&e~7ItheuT$!{Lr33MEyF^W7miE?pU88mg_|a&14*{bxDy6m{KCUH}pP#Uan zk3tVHE|tcr6v6jl?}SY_t3>ZKM^+}g&i?>-=>OhT%$;|ff=98w>`Smn)@W^f&Kd4h zg_V0eV^>kP&YkkNv7?g(G@(0cM2hvFzXV@u*2U+a;nr7J)fF&Gmj9O~bTmcvkyH`S zSIUuP0s`MY6vjxBXR7~}Jg z|1YfsCw&z0)nvkiXL+G3Q;juxUIbRb%C|ko@z`W~?`)*;%83J6w%94k!!X|bH2#nf zo0`DyV0Luzf~;TDLbLyIY}eHP$f|(i45M=6v$!Qtd~CYMCr0_HT!|VMqXfF_^O)F2 zLjS>bk}Sl-Ms~TNcPFZ7#U-NSoNe1ckxkv=JeT7SPiP{+6NkUQbr9fjm+MLqL~0kW zqX4S2FiGFkBfpjEaUj9h=5qt~<%i91qh%h?Wqj6$(NevM*S@V0D;BC0ElA0@QgRjJu3A%1W7 zZRX%msM-j6<3}pD1-PieJbal8Nv^7yz<-v?K;rzHGy?eBoY&rJbNiJ@sv$bakIn}d za`~3zW-9@!j_P>PXZhuRM?588uTK4ubFGV{nZpDR3l2Ew@9R^8s|%M;a|Pn9ul_is zemY=8+4R(C@Q;jZRcE{k^s2LmEH-ZaiY~gLb~ry}yAzS=zpO2G*tilC*QzFM>QJAc zmLuqpAMY)|OW&V{f+h9k;k3J2v{JD(T~4$^Uzx6q-<|Wkm}5NO|Pk+B>o$IdZ+r*z<=3O zUj6Xp@_Rgx{bLfkAq_wSv_Osy@}hG1iVHVHR1HzSNC#GU#gXWGGE}aRGuv^L7}%{- zFJatgJ$HC~9b5L0=?*Ich%yF9PO6WeFCsMx?npa?$;AEgI#q#QNV8V( zJt7AiZsDi=;!KyzQdjsg2+$_sjsv9Y)t{=<$w(4N{fa)lhPM~B+%dIjX z!x8Hp*8ejjfc1LqD-Ig5IdRx8^xXml>dud^Pb3eCQ75g8SAFAJijyB6CkUo)uKpX& z_-CsBGu;vx?s8@w`i_=z0L&d&2&|7i^`G?#Sm#N1wWwa^^Jt-y+{|8Xpe@*tOz+J< z8QvzJJ8TI+_VruU5LN3`1cr&0&m>jW8U$25FCdr6B{^ln+cjXgsocaAGN%wIppuiQ z6u%Z57x$XGtML@h1aeykH#_Hv26{Y!zl>|gg42ZgGJUrRcYLQj7dqE@YqYH({*ale zTihAc!!uxMGQ~qpY0+Run=l&Ja$Ga9oyqbZzRT>9xH8L1Wp!6}iPddhATHqc<(OJ# z@=H4V{l1ibmyxySz+_%Q3fi$=&$`TS4fdc5v_qYzP~DbXUSID22#E6tI_r2%xLDnK z?^ra>#wEXW5CGjt7JDa|oS6GDOPrA|-#Tf9;lg!IAEPshZjTF4-vQ)<2N8)xZ@AML z=Dr|L%@rP5TY_=}%H1m4@>Lug*SDx4hWJX8)$k2zgvejKbj$7obmLm1DxTfvD@dlvce*Zb^UX9~bcPIk~3*Qf31cmS$>Z4bKG7KzSun zRID|~Y9x4#pKK~$1;`2lpJqG8uQA=hxC|T(MRMG1;leLZr`#D>2oflAGDW$6{0|E4 z{{zL@Sj2VR%G=tQ4SSV4W7I}d-#+<2witg-5m;Z?^y^#8|2O_%-)qVrfFc!powcV1 zq%L6fw^uJPxzwJF`|!pFB-R68{kiE$?Ve#XF4SPZ{JL*Lv*&0RL(Ic$TuZq9l$gj` zy$O}|G^SP`9P~PC2uO+?FOsX)iirfuO7S!z#C#5|#tUWk;8avsZ?;|v@}PmE%gSj# zz8&Kx$E>GuV%YF#t6jzM&H$eT8j<4pg{-KO(-Rtt8 z)t~x}GXWOk+hz%^+`T+X2fKJ;KD~u9xr?o-QJ-H72y#JRJ9Gj$x~=E?eNH40^J4^x zA+VMV!XI59<$W@~K?mlcUivRh`_nHix(I@y!n_r!==w4-znx<`+slDS{nz^vd^_#Y z5_hs~P`W?hF{daq)fKxI`A#)%eH&C^;s9*l_bE?WIr1UsRd&GFbYB z`1tN_{V`E9w~CdEZ>fEMHZ*aL`{wf0TOSQoQBzdii7%AK_U9-aD5}+4mwG|#O@;90UIbRsVxv z(Fy3?ZXCW`hkVdO4;?+=TDPT=a&gxqejsS-w@FU!1bYH;1O6kKo11I4o~ap2x*>d~LE8QU zancRWLu>_XIKDvXFfoSj7p3T%TV0>$E3aPbFW+uL9*`!zWhes4$doM;q#1K)a~j!` z;5CqZiFqZRd{4*t_$TSNlqN<-0T2l;b`TR^AI^O2bZBU?G*4_amLq0(cp8?nGCf0< zRoADW(X62?Ir%C{kCvP&t$~VqAF-t0 zBEirbugyXi+7nTWZd)8Xw>1h~S&xhRenEcf!d6K)X!>M7ur@fg1l|1rNk z$>VhSt!KITFSA5IXz78PnA9u@%Xx`=XQrt6_oLEuusH)WOD*Kmy~%Ww=KAnPmiZcP1u-1$K?%j6wfJ{Z`xq)3wIl#ch zyNMzLg0Th^e7?+UI5AdbkWjJMyxK%c&tgzo|~WgwkJ~$mFK$}PCat^arJS+UzVTy6tg7IKCX*oUNh`6$8Lu%KY7#G zc9cjr82hPjFwNyY_3I&VEpC%}pnXI>DBtO_jild@AOoE*&uD+GLHqoM;d}b4sdrVo zq779nv9jgK^7=3r2CG zbkwk6QY~pz4^$qsc;C~*A+9O#FJyE2|TwVbI9U{qPVQ|30h?jBL$k@j5}utx0| zspoz9$uEMBUm>HTZ-CBu_y=Mfw-R7S#hXtKA1(e={5RmoxY3rMT}(u5JxC4x9B>;I zxaZp84Edx%w>fwaHbO3~jx!-SIx& zN6qC@g*(4J_{V_46c?@X1#*egWU4TPgp~X+I(||8cPTu~Xh=Mffc5Mduph7FZL$MP z;dagR!Vd2i8ODCUpk#Jhwqzt2=YdQ`l(N$bS^wz^Nfy!}i+ zN07#fHT7ZCaP70kW$zQN)OyfW&W z{v#xvvuBNlY`nZ@(^!m+*&>s8(~rLtuO zrhEJ;ks>Gk^@1wa-E2Vh!`}{5tOgOV^XepBbx6CCv1F@pzg-U2)&#fazP%+5#D0j) z2d!3qDSIedx5_K1TLu&h&$l}H3OqEG+6nOD)gyU43awZKjO_5#La*F`Eo}F2!Kpkw z1AY%m__lVO5%D|+f2+L=xD(1ivl4JK;EjvjG1=4P_sedC5lKB`7Us?3+;ELZ|8+dg zShyHk0g`H9Z2}$%4bBVRagd`>CU0!}H{Eo>ib&MF5k4S80BRu0@p5IyDD zZY#9Rqk`HLe**6N^BL^TuDgkER+g+npWmU8p>h9|*f&E1`vu|w=L*qEtV-NHC>GwC zzR5IH^Zfxc(OZR~rbPT0BK578?(AkPKS4%V4V>H!o(x7I*Vd^p`ckNL{5&&n;^DW- zJ0?o(D@27er3zi-bFP`v<*<1du^)e`>^M+J?i9?F?+h8~pDJQc^Dk6M{|Qo_bN@m# z6=wDm#$)6}>I+$~(pkdBOvU~TsgRxGde45izGy<4#nN@RuL%lvMhN9f7HFOxaFARE> zjU{6UjJgfpY6;tt*N>ZARdLgcFo5`>8|nvR*_PGT#;XJ0*d8E^9zFgP{x0r!SFm?k zA8EN-1I}T_h)GHqP-3Pmy!5L zvgU8QUpM^WL}eCk-21%Iot|#iJPtUrMJ>(g6pR;eWGrM^QAz|T#HW3m6bBoHVJ1}a z!SOz;v}^f`MybEgj3l22CI)Zde!nDr1Cvh2E@g|5X^l{WHXH)!DA`{^|274Zg8(i| z*1APMin$B2zpGO}+FK(E8D2`5Mqk$*`V3npq@gSLX*at>ha~1Wv zS7gQ^@UxDlB(2tv>Q-t4*hL*Rg1~V!>xGiY91&2%R-s^|-`Bm@$6FOXy{Q)4MY&j3 zTAGxTqh@NFp97l1A{Gjm<4qa}3k^lj-iJ3}r|ooF$pG>4F|VuMwA%aaRaUedNsjm) zLtp%%PAy8Fck!fm<<|0j#uRqFH5@|5X4ZW#I{IEJU%r3-DE~p~EKE$@f-wyin#oaK z`sF3i6Q|tcPo>g}mZKgKZNK{v(R;Ftg)_x5&bBiM&K0fj)3SN_06BbPp^dsf)))Jm zl@U}68G;Y?w7Rb`>FMu30d}glDpZ+KAg#BB6j#mM0rGsv)OEIQr;?C$SttsmsXcIy z{(idx_;gfr_kt}Mq#9F<1=T^`%)E7nwK`fuZs<;Zcf`G#R&k;rsLzyP{L`eaen zEKR&urHJ{Nw{Nl=hW(#~MIGgQrP4&)!^C9?eMi8Zmp8c_CO@j9iox_ND zWj!k@^M#uroAAiJL;6tOXWYT?diCpRfyi9*+BEk_Qc30rX7{+6q-M{&>!8~#t}XSz zV6wMn_jpKUc+)}M%ZBAa*&r!Wz+`DpRFNDU@~OrRF&$-x7lZM(`BtOf^fbr6-%B71 zkxB<8E&U@_cEm>OWV091abTqy>nSfyg4>`xT9RLLr(<&M!Z8LIdg-2V({}<=&=?to zz#H&XuVhqtH$b4|i=nbZqq=H(T#_Dbdkj?G>g3Tcy_2wSZ&rA!LsAN4 zRRuPjpE0_ms|?AF@!FotYvx8`_(;oB>KWaG+Gd@Lz<8^>!Tva^lHqC0-%WJomqdNI z>-qCnS4GG~Jnqv{-YX)}c5?fD^d}8X8{^va7+;lM65Diydo5kuhns*u-+VqdW;#Du z2uE5QYueau7odxl|G*is%R-!fzh)bBT&yw#wH5zbDne#2g5fn!iqrnjNEce+FrDaU z7`KmoIh&)wnGNEp$7HOdmn69#qA-r+a?+GT9qOoLimihzq*+i019Ba(U zSdemAp_+eN=^3>V7K#8LU-U7uOmfj~f4fbM6(=M`!7Krx7TYe5G%>kqj2WiGME31y zN`nbeTcddnl?rb!`(Ac2g#h`BE?yp2LTAbirjkQjHWy9^pe)tjt`QdO`~B|m_uvgQ z9YD9F*J)r+!yukp9y9RZ(+vsFGh(NcJk_*iRf4rau=aRuHxDhYqOsIPsyZOA60+TM zBKucc+gVPCl*H4M6T1}l+t;If-_mc_LldykBp2;sH`M-ZeGZ0Lv?P$unCc1GSnc)N zeN@Sm`5Rgd(oN|1D}R}{mt&7Txe#m%M~7!F9nDF;b|34a5&IgB@0$WY8xgK(sYd-i zy<>edWArT@9uxWq8?DyJCok{koOn%AV@s0Bgfb#CF5xaXZJ2gd50=XG?EPL+yUSb& z#F0jG-ex@ZWJmmVu(YckC)E^xsAnjTY~KOIkxG277>97^UM}$LPf_wpmB0K)?tBOE z(F#PU0=n*Ts44#PS^qw|Q+`|_5z+22!H9Z-Sk@5LN*>56PaSTH1p$^^NqmZry6~vU znS!r3X=#1rVnmso;liub;8e(|ELqy2^pNERl|-ZE3y#uYxjWkCCMQp?E1!2U#eon*g^L{{C%L#?{R8conYH=YKoo95v53(+s8l05zQQ>mC9IP;;RS0ND zfVx=TKLm&;$^QS!RY)(nk94~nmfTqe>LW97|Muyf(Z#kld_UaDyRSwGaE(RmcSC(d z#nUUOkt2;WjGs|p5MXiW4WzoUz%P72F07A~)d1W}>2&!vgBJ&Jp%qo@mmRVkUu8$4 zk7jkkn=r8}=6D#sMIz7vep_v_3VCW1KBh<_ciuM_}num>T+fk@uEtQFBf42T~s z(;&~{1K_AT9pqQt=rH>+W7lqFx!#s2MdAz4e@`)y_CO@(5<$&0c>9e^>%$0184G_( z<55S606aCY*6RIeBz^5Ou`;s>J?Xj_24 z*RvIQAH~=geR8`Iqb_+PKb0a*pK@z>M-Eq{yN`FoyK;MxPmlicJ&|rh;KVBx1P%r_ zP`*NcV&lJ*ot+GlX8t|XRZ@JdyDP`O`Vb692JF?|P9A2o>1%ov#{nMmQe`Mue1;mIBFyj2R zusx)H*0vl4-nTUvkVgvfrE@F{f*vK0=CE=D0G2Dno!Cl>WavVrK035UFw3}mrYbu&SCq5c#H8Ot!ne+kCQBQiqL?0oAG$J^f zdtq`(hmcs3BTNJ*fVh;$VQQ}EM~7X}=sf7?>xmmlCI<0O>%q{eINnX#Uv*C>7kPr# zg6=`e6cSHtM*~xIS+ZfYBw_6HSycdl*V1;r0~ohcIc9$zBlkfDHf;w!7Z}K&xu29S zZEYogz%}iSuH*^V8uMD8wcQ%g;SvINza3?5al;R6#rDo>04%v@TB&roZ7m6OTOB$e z3G?-{1yr0p$B+WHBSSY`6JBVA^g3*2GhZbR@ctQIz)ftkv`&ajh6&bkx+$2`KGJ4w`M*Z3%% z0UoK7F6eO_n4KHQ1`=mdjNfrxq4-ts(g8MaKwQ$VZ|YYjSG0T&GDn$ws%o#IVg3IQ z_2%(Ve((Qymh8K-CR<31T|y|7os#T~eaV`Aov}rt2#tNskdS?ku|!$246++bLiT-_ z?RV?-d4GR@c|6QH*SXH~y3V=p`<&}~Uf-gwn$Ib22BMyJia*7Uj+QL0MIw)3r$zx!$yOeoJ_ZIO}sKNO%X zD+kf(9N!J&x{Botj&z;Z;fWj=-SfvUk>L)M ziJ^C?O^3p$-gWer`+|+vr+=saIYKW9zq=bY3rpGSM7$T)wP%P#+kbpDb^eX^V)cL) zUDxvQga$)*RRgs;*)rSibEq>I6t>^Q^$!}kly5SvjIZ;hjzbqnaR+EJ?98{?jJ#_% za4{z9%7w0Gr%XxE(CYu7>ARKjixyxN=B}91yTsi2d-qD-ll}gu*5P(vN*wVz_mv$b z{-=9sXZ=Hl+xRb_{R^Rg7IH=rB_M#n0Is!3@P_#=H2(WKjZ^$$Y}LmI=qk0uj&-`g z5chl`%4BK8`bxsOT9<`J@QI_IPT%kJppApB|4f-bOA**AY8%k8O9%KSA$lgch7E7z zo%W&Xg*oKzxd3DzZIk#9yw$s^DAy%!3eeqq_*TVB?^LU`-M2$mFWsJLg|P}EzEyuG zx36E`0uBS_D7ujI>J^>tqv-#d7S1r#vc0=@!!hs68oXb{d4F}a>z@G;2LTzd4XO7Z zTGS9#o%!L+qPv4*Q6xj*Cy0Y=;JLIg#vDHS?1}kR+b#w%Cn6SEY`moR(*QnZ*3EK!fGq)t>Hdqcqe29L%@jJe+eNv6IT-7a7u1Z}4K>k-tkKJGJRfQi5bb z(AC?*H8p=_f1i0878Mz3BYylj}P+ppW{P~hoFZ!Cs0 zRN!&lney30tmlO`ufZ&?ZF8y>5PrPp$8H)x4G}4#l)<#V+E5EIoKND{j>N_G&{P<# zWPt6Keb-6o=8ugIk!?C> zG&BRdoVev^!!ai%b(3xR9ml`AXIrn@qYFB&5j)(ZjC)KCvW0{VXc}5ZE58|z9b`Q7d(eXQzyAvTZXOm|)*E|I1d4T*Fb2bc2Ae zgtQO?kW)II{%kr!?uhAoLhg|V3PSX?{%+L!kFw#A%7lQQ^&?gZe~?hw@s6O$M-Lts zyt(G}vEO)rzO>a%*d|#!o&HuLPj^|9-=@KDDQ8h#OzT(?)2ysek$tE;*7J|R9n1P} zC)7*d-T0ferkM0AJZIOxz(M26Gq;+H-Qw+Uq3k(XJ>bRJ^$rr6@WD8S#}vz!^?l3nJen1n_ ze;02rvc{MSdpNHrycV;0P6gO7{@cq~f@Lopk*Uybteg%n_MwkVQ7oh9{CVwA=+A!Q zg`TLAkF^`D$a zw1|n({K8+VIvG)bBa5fU7yFb)g_puusLm7RuWg$1$!jPTjaenYkY0|n0L>Ee(Sz}n z?z=Y&>d%RfN}5q3AMWrrgWo(xCh57FRgTnfAs-qGY;o^5E)9FuUDQxlPm+MPKl4960P6z5q zTpTd@>jxbu;C4l%eAYEPe*kbA@A0D2V~fnwUh=|Lirb*&YS2~fDj8{Uk2h_w=TFRO zZ6BITRXmp#(JE7U=2oLiH(szPu``%UQPyNGnyL~lKP&v${Z>wSld0gAFb+sUs@3AL zB29x`n?AjgX6@o+U7|I(@Wh8@V&y_j)?S>~QNQS&I(u$xTqlI@&s` zaNj^eqwP3;r?5TtJCh)A9+r_6tQ8yuY#^@b%KYR#jVFhB*_meMy>=IE;3}Oo{i(@k(;#M$Ww0jMlVgIjBpfyHiW3C0C)|l? zZ-wofF4T`~3r+po)GUz=-`>XTc|<3`e*#`QL5uvmimMk$bo%7XaRuJdUZG@VvME+ghIvcxW z(yg5azHXv%x58n#^RKerpQ*_3x)}bt1n?w>;*O|L)P?*t;hKR zFInWVA{z_Q!I^dULeKfm&(H4&K$bcqv(omxPgW~+5S@(?c_Q12#nbM0)*zRu5WRVF zVz^QRMc=VoZ$zs_lSS3cyD2vi0CWCqJR94m0+hv4`e{sx`5qM}mL(E$K!IN6CVYwj z2XM}f!$yFYAbD<}aOx!43Q!yR>0ao`-^ssl;7zU41~rNt1Fp2s9r;Vvw#|&!*L%vI z73AAfovwYiNXN^%+59yMoDR%$$kOQCo&oMuy(}-Rh9&8^VO;Eg8Uo^6TswyTzCC~9 zPX#Hl5;xaITtTFZ;WFKpvY##NrNy$eNbibAoYZvzvW~=BvJnb2N+Hr-#)2SArxTI$ zCs3->4RfOya0E(K$AwA8vIkE1CCi{P$#qH#qPn17ssn~>KLxHSg*vaZf&hQX4ONguaSy_uV9T8%Q5H-Sz%D?YDa6;`C@8-cXo$12h=2XL(^^ ziHzo#PgH5|&r0uKgAG<##WpZnWRIgQTpkgH}l}tD_AoGKV-@|p!bo) z=-+&|EbFnad(@HH8taaRb3U0r%a6*IuBrTL&;%3*|K0kzN|y4e7C4;eGk>m~phGY) z?YURd+SRejyr1&=<2*6?y^Kgw#LRuT z`8MT#XyaO&!oJXG>bS!Gpzlp5p?0m`U9U1NYkOeVx8xtml33JTmjU_2UM;%-o-tOp zo37wpRQ;VXA{EQlB|h1l+lmeKw*hI`$a^wNO#z#%ny2oA=?|`z`U4+TL#1*HLEg(B zEo;eZ9eeNSkNtS?Zp&O|>FgIAN*k{$+tu+b!77+^s3h?o7rJuxuwe}eo$WPQkqF<^ zlb{#N8G#Ez8!ODa${w?Q(t27gt^%xpDy^6@!RbJk8n>H7b%Q*^I_davF@c&mjOw0E zkT+gcY;ty{7IL-pvu#1Zo3b<@Fzq5F$+rRsb+`ic`}E6JCj$DjUE<^};F&J2WA}-j z2t+G>OTcrF^`j?nT}%1Yd-iG`{Yc#6!cvz8t4~?qFl@@i`!fyMi}a4D@c2WW@b);^ zy-OT6zLLBwb1P;BZLSdZgqiZC-cntdoxs0nR(_K z+Jxw<3TN@ZmG3WR4)J5-3+>4vXJrcOA5O3^9`&L6>j%2iE#A2Y*MUxRP-MM`3SU<* zxljDpIl4&<2NE;qqmPDq1!22hd6(r~x3G?Vb|T@O1nJu7^x8ynQ?1e3SifiijL~wv zB+CZn!KX-4r!sE7-7p7NVbgEBhv&XY+umb}Ub4gnRA9I<=ph+r1w`vb_@`xX?yl}? z)7;bS-ddofB2g{>mXN$@NC=@w?yKC6v~tc@vt;Eg?7FexIKNTXS;{XXH?8+3hGCzU zSv6&m=&MF+-!-FIDbl$4+o5AckF2v#<%@r>l}SYc?~U)O!gt(WKP-4ZEDl}O(Ix|+XQU!EiH!pU7P%G+Cr#j28?G%~#?h3?YI{lEOf8}22si;!u zsZlm>itFh6Q7_*@)i*; z@4aNPht@~tTgk}re(0`z>#eh;JodWWP3&Q_xG-+BJl7Rlq$UP=Ic4(J&L8wRgut0_ zIbZ!+vtS8@To{GTB^R0&L<3gPjk>_g$VOp1)80g5U`@rsXVoJ<4l{+J|Ermi8Q)*U~4-l|L z6`%UElJMATlDo_#h^fPT{!cpekf0HF4Fv@DEubNIyKL4q!zBC+D|`Z2rNCV(94)8z)&{AW5$|3;7viJ9-@ zM{(}~%9sO=1kPWB>5_)pQnFE33bAv>`cgz({t<`mKtlszp z!0?XxPk^RDk@x0ftg?Asud=(b+cmd-;~)6;Q=vs-L}v%%jF)Gml13qvSd#;Ce)YC8 z$w!RauOecc1%3B%I`CMP`?leU(`ejtn(7~6{MZbvv&eA%TJf?S;!GUoOar+OM|_<~ zOn8`6yhVMiWA+W8s%ZDw4AdN3xM=c1eQBlDWPhk}g>cq!rljEjF0gJTI^GylYni3K zp>rDjprt1BpqCYVTWPTwxJaRC!qY3GA9y5c_D9ixBT?5+*OXK++jT$OzFzz-zbyBa z$RYbCA4mb!w%1TYq$ycWHzd4IQu-y?DPHZRehTOB&Qlsis0`#(eZBD};h`>tfEBm^ zx@DZ9yr7s4S=TB7zD7@XESrN;-jCnhVgnA9tS1h zfkV+2%WIp9Er42nO?dvcCf~y4Tl{;F3i}A?(hFw?)FRFL*#ie?vUzwvRkIO|Q$=ljdRnuD}*s6TKBAAvo46P zR2Wnk8(O6j3ih!5-Lrq<)phE;gw>+G;I^F0{XNDC7(lL`%@fDXHKTvRWPnX!we&Lb$%558kBUh9prUPd2)RMAS4 z{Bz&T7B!(jihb&B&i6Pc^J#!pw^l`t2N=|{IOERa)FR}`)r+P>`SF<*#%09KbVw=7 z&q~B6G>QJ?bcUjzZrqjsT(fWZrr3BsL$NU;NAQiSgUs@sOM8m2W`4=qZdvaFC+Q%b zCH(mXHVS+F%$XxY(aGh1JsW%S21iv$9fwU8NqgT)m@~B=XW=VZZ9~df^a8mqwH+;L zJ7MLz^Jn6KFF#Xi}=B0cTF&eDWu3jkU0u>T&7D;BS`c3wd3XU5#!BT{Rc5<8RCtL|{;RT-K5=8E+8FsOIIjuhzJN#p8YL0(X^_c@TsPmVCZ^^8 zb=d^)KfaPvYVs(4w)_`!hy8`rAT`{$j<1_k|TV%|z(xOdc#eYeEL zF32IybT=Bm)3RT&&yPOq*uRNB;*OpuG}liWvQt!kHCfpr$LXZ1T5lYf-@@`cx@{|9 z-5rLYzlpANHST!V7}m#V?-{#b;Je$&_^!#)0Vt)D$fal;Sv%Xd&(|&f-twapxF8T9 zM!q8u-V;lE>(;GLt)W_N=`10E3;yXO7i-PrH-kEHWWHP;=Qj-d5^c|R7jE41zEako zPD>_9o%W7I>TCRd0v#a6hA=3OFd9*LxuUKiq68H1Rq(qFCR|K$jS^;@^ACVa*%sH9 zJU}BNVPWAr7R%^^)z9h=?rJM=0ELs5ul6Nzj~GA>nH_%#{RtmT7dNruU=g#NE*url zW-+WC3&P$z=!xx`t^q!ytRJD_qMe^+(iPXjWvD23?BAXs~ja9g-;sz>fyB@V&EoAxA{% zftn3<{6SCiH`C|+pq^|B;AGn>L#|FAen7n~Zb5`%rzfv#}RH3I|k=;#BUB6kEekeXcHv`AjIN}y4X#U=;We;?xF)S8F+9&aT0gIU@61&?d zaT~&BmbjMxZ+0`k6HW5kC+ ze*Y&(()fsxGeeiy%4i{65aBG=(~^*VV>ExH^nSstlY&NQ1e6ABFGugY)cw+&Lyetf zE};gSedb3X0!(&(>@%@Vy}eiPZZgN7B>vWh|5;|5WcuzrTse^T;;4*KgD4f|*0kme z5%*bxz9nJ3<5G5HZ(3#Ahv!@z-}>4PR8Tte0j$mutie^GOwP%~`>?8QL^Qf(VOfkw zgX`kRZHXvQxSkySUA=R+sw?shb-j_CR0UMj9{lR8{@GAD1r(o@Ba3;F8Af9aCFK-U zQ)R8(RX#eC2)sA%pE@XY{tQ@k*Z#S1M|xG)ZrpO`0d@U^jFh{#s6CWo&o#Zngb|OO z9L@@F0K)x^y<%ub)Ko>&ol2A2|UqbzvuKYwC=ITJkj4 zynonZ*Uv#snDD|Zs-x?Ua%C~KF*67fDwCcf+EF!NFI!5_Ojcm+C=<86<$2(#eBZfs zN5c|`Ui_YOpUikCR*hVY;TKX9Wm|LY?JFOv1UW{$;^99j@(m=)7PR(q57aMLlOnSx zkWF+VkSO}SV<--hRSzJ-3{>M>c;d4}TnKvmjXq%wXuvvR5+PDB{wstx4iNujBzsyc`rQc85q-%?Nx!mcB{i}S@eN(am z;ni6+kJfn6t4X$9iX)4ir^x1hNsNfVbwMND>FyPvy4w*tm`Fqjfi=uiv5K!BxGyi~ zL=a)@9>_WTU;rveY+nH?fkczj-x;}LvLV-YM%}E#62UgzLKk0>;98JzEH5aIHkKyx zXLfF&)TDMI3!sF%sO_@rUQfp9qoT>;+8w z75v{?96GRJOu(nuptGvwfc$o}GRdisZj=aZwM!&3+SfWJ`3ZW};>+mXcOADK!880R z3E})NZh~x9^WBY2=KTat0%3>-C@4p^jZ&s`r`^X~)n76QXCziz9&gGS<(?Z!a&_DB z+{Ja(bE6H6_DU5-`wD)%S0?(;5HrPN`MmdgoXGd7r@7a7YUP*y;aC-c2vK2;#<5*j zo)B7^nnw!(wbV#X$Ac1i=ZBq)6(Yc$c%J-}5iiRE)Ob5Wi4iZUu)kMzPOkURitRey zKR*IB`4$y{lUcN(&~kVBOoG0;P4B}obHn=;q%IU8*NH&<(aDOkW4nHHm3hCd^?3@P@DCl+wH+$i4V zYWaRjEPYOFbUH7hN%0@1M0nf>S(!;v$-i66|C^?(S7-9A>HCwESmIN1gJ^fU=6|;3 zTtX2XY4z5l*<@wrg_cY_v8l)CJUWbPQdjbv?UA<7B`Vl!htO4GoMEAh&)yjs`i$@~ zHhJ(N4afD}|7o5}hKuWz{?Boa|9|5W<8iWnZd65QpS=Hv2cr1l2=9LGPk@l3S|yaB zBYThTKer|P#&g(ZMZNw{YRkb^HB_FKIQGG`6YCQ6N)~+-pz=e&9T8lN5E69x*%ZUP zkpcSCJ=FgJT@UR}{!$&B%zO#-uln6L;XPaz0_~^<$9&dKa2$0jWm znlzk^vh3?LMwGjPedzC<5;xY~A!ZK!)N@t$?U-?limFC`^q#1dKDJNURWH*j&2WfQtl7$+m_aRqTdz1%gw_!Bq4 z-0#Tn!zm&Wu9L1%UoX^6h~~ydSa`KR2TGubuJJ|nKjqtFr-R$;xt0y0j>O){(N{$; zOOfbQr8}YBg}&Zb6DjU+q!}6-k3`(~<<$B9tiF3oL$0SXP+=USG7x9dum#_tfD$)n zot|jMvc3bZ_xP*h0^0W*6JU4wv06{|>}CV!6f|8#+U7lF6eIm5JL)UJV=X zA)MhD%42dVyLzWrI~o?9`G8yGtMseCOcbl{CTd=D$iPlFw%~%RHFSrhINEL#EN?ei|L?%YQ?~w(&l^*M8aMp0P91&T*Di zN9z2>YDHyYUMq~DWB02`BjYlwuIPGV&kTeMA^4X29ugf`8^=CW3e!ony%#KM(g~bz zv14P-&=fC$^ScPe=fz;d6_4L_Z{yHq0afn&-Qpwu=Kl9bA4_T7SXCOx8cAkjs9MMm znte1l2^iAv`R2J{s<=H@s@7_NK>%? zWqdeuJ%suNx2i~jJ2iT(MgQ4qkwBKcXmLeL*0(D=*6dNc$gsB@_*+p%Asz4cTi)G5 z`b8^8;&LY>qYWLO-j)#CJY`x=x0kwCSxZqo(&H5JQs`-jaRsmdH4${P#E@VylkpCR zDEU6UG+8jOFl*uWkbZNQNUXs!Z~I{* zXeoVNVds9Y=DS#X>cWcF%x|8pEbDNTQ;dohj34QuDV}6{=B9~>1io?Uhcf6J(rt#k ze^`7WLKGi6V@Ve=6h(aXfSm-8;@8{n{y>q@yQV|386m-6#)ozCf8V-ydNVE8RZ!A; zTxxi&u}T-iSJ3CH-RC}gR_E^>H^}s-Q$NU)%<{`Cuf)hl!5sTK+ED#i*yY}1;1yda zro$G0OwdN`#BDL+6;g?cKDdJ2rG9fq*E#+?)}5%YkOkRB@fCEb>Zqr{^1Li1?0
6ikVPh+(*7`&RGCjwiq?_gx!E=(%O=dm$*T~ky#Bf`l z(eguRPc+cq(lGQ@x+SYgsjeV*v#=5_r{^Lo5)L!)XU&8r;l?r&XLW1Wj1 zC4AfKWKo|W)qlS;OkKb8nb(au>`8@E_Kh~{H<}h0(gAhDV>#3MM~cQbQ_Twd9H4hZ zeg$P}>EXl%e63K0Q9kzdlQ09k{_G*;4Q)~dAt4QTEA{-&LR)&Kw6lWwk(LJ`r|tq;hWOpBhQVDVlvQL7AnEIeAt!7J%!)0G%8o7P=iiUTglh_ z?Jd246s9x9-Db59q(8PamD(P(b#~BflJfZD4i|qb;Q@km<6K&YA2o;UKTxk>A2pH= zciZ+p+t0n(&$hZ)Yq>SK=pRIa^%=tKA*$x_0$IT6AT57;IT7OP7m;I~2|^PB2SNb} zRq@QS(jD!gwtsY;-8!Crw3)o~^DUx?xVH9z z%J+$yt*M^ZjI+MiuSfphB>rOc)-ytAd+0lHw|vu8z6ZD8wqr`LaLshSnUV*tbfbJ5 z!~LgoDLyN5VXVCxBFI*Ge(^SnyDI9-%O_Su*|i0xZPv;5+}8ARZ$}excwy!z- ziBUx5GIDs4>-)hhIa3WkYMQFzT+F}{w^zro2?=0OSs>{7mq6Dc`^#9;{FZ@^=z zF^qUVi$z{mISldsyw1(VWuM>qQJ|nMQ}olFk5yGobuJINf~zLpON!*=u(sW1R@n(* z+@QA|TP>xeef7buRqAlAD=YBU`w$D|R2J;M#_VAWBCv~p>OhedgoGI&FM1!M?vpk* zG=^otR?axj7q&UFIItNVMT$*rF0K_#M}1KW0qut0r_Gj&+oxaIu!7=HRLg-$`GU8v zLB5uV;QT;ct+2o*uTq!4v0M|$f@%z)oH=!^ocW@{waFo zyQ$*5j1=z#d7R6Dx_*1JGPeNRO1EyKVO&7fjYm}FXyupcPalHJ+}BC!nG^xpWr;jy zQ$FgM=>D3+jFR33RV!t2z|}mo{|L)@P;RV!_=`aR*b{jIIeI#`<(Yk6+ZWA_rtGaT zNz3cycD%Xyh_qbui6{2@^pBz(`r}$6K&DnAkLr{UqvS!VeS`E+634Txhncd)pnUh6 z&2B9-Rte9vvw=*bW;iGxxk4}hQsQZZn&*dfn?J6f#sf(nKkEDpY*dJDGPAY)Nb9>i z-@h0{F*06M9`aqfnMe}l{izIvha#Yh*ywDQK;c{W3?w}=Z;-Bw0%@L?GFx}Z)rPGk z4p^*oD2L{${6jRVo(fn0#W1j5z21=Az@n!cCsoZbj((fc=Y1cb`p@ zrtk&&PQ3(x`!nhY=>=r@UOCIGYlRtS3a~XEpRe3kGfg*eJFm)XEd%(YU4) z;d{X(D9Yrt*4cEtHeDLJJSE-b@-uMmb_PP*cU8rNNZhfD7q|xguH16db28mNG(m=0 zMgFcOkW!ZE`JvlRvXwhxF2~)R3_JWNp?)pvrn&zAVgXX?fvo?tW)r~;kMnJYYm_}c zJb(vuurB6ry8mQVp?X}2oJWhBbdsBSKc3?I{_aDGYb%WT5sx4QNyKZ~wlnTh6C;Ve zVu_kc(lZxpb#c9fp{e7>Q9{h<4GLtsePerNO=hOeRJwiSM;`YNyM17y6EmA}U^lSc z;(Y>sCwqNU5aQ316wd-AqV+A4FMWn5Xi-z{DR6t1gYt{l^Ib=UYOnm*q-S3Bd#p?^ zP5&@gndt4C$mb-$*78Oq`6PHN{bOKZ0!_q8Q_pLc-1j2?=59!i=V0D1Pf%eSu(G^Z zvr0!5F1CT6xx$qs%E*s1>4lCxichmnwbHLrh`q zFZP9Wjk#20z7I)S#W(AacZL{&tDnO!j$cl+H#NnAi?GBiOoiz`uf(OjT)l625x6tE z7WCB%)$tkfwYJuf%PsM=_*mz6dvUQk{G9rMhK5F+&zkmif%LIF3Iw)Y{aoNstXkZR zsxNuudk#{($}JHnqF0{y3gAPQFTxy}h8kV~(aTVLSi=}2BV%E$;8!BZs!}+5IW9*9 zdearOL51=lLfjCk60Rh(x3jy^7n%2Ly#Z?PC*vXp5~vRJ+88JI^LiC9wXc%~eqcGw zobHdckT6%+6L^Bg$#vj-lh%^}netOg!yYDK0nZNuR*akG?P3+0CP zNIqOpeQX!QF|D!ME60xlWP*}piATDdg!$lhhAGxvFkQok;f;N zxMq=@ThO^UfsA9}5}UQ?Asoa#30Hp8Cip`Xpiyj~K!j=|)X`i$H%H#7cx{I$F*5!&twgnCGkjelR!S~ zD;nQ1WGg>u^x6LH7|`#YVNfa)-d-FiZ=ljn!nE0=slV}l{$FR6JkFrkLh`FfDX$y+ zmrhbMa*&5f>GsJhNjZAA(Q$to=zlHc_OhBbe8<+8t(~N3v!_bF&{?5=3J$o~f%+kX z*ULV*r+y|2;-x~1KiLcLeg8H?z4gi8+L<&}83AmX z;pZB;IHV#^n({SYRg|BL7cD~lyf?#u@7UQg>uC}{k{=Fb9WKxZN15s0{~)7Sgvo+! zRV^FvW-wj2{({otkLhR&3?y?#mm2{CZUJS80psVttXW}W-ONNH1_hKS<=9}~)g0@j zTdV3fI-y;pSY!*2B!#xsuMy#{CrATKZu^(a#WAAebJ?8HkGVVko9VZqVYludv*f&V z&6Lx>1J)D9wdItug}3z_h87&ATnefOg53l-v>{Y*rt-E4-Mw#DE)rvyLyYSFd0-NP z=w=AhaC7|-r(8F%SksS?rCwB`P>wqziXSoBI*Pg&!<2&GYPUggJQmU~+etEz4I!wKACO}OF?31@jD6NQf$A9rB2tr{-GYD8l*-j2?E<(F+X@p=JAc85*uBD$ z^_|M)^xFuwBcF7N@x`-h_w$P#|u(9v?d)ropy{K!#92`JBbNQwTC zmch2xxJT8$`h^G!1Z{er`Q&WvlL4ndU@7L`;XsDRq4MwGTe4tF!rPa?H<(@&aKVK6 zjReA2f><^E7BuSuG2RMG&@Wf9T>DIag-Ou@J)PEOTBcRj9YjFBk*jfo7^mbEDFg_^ z{e1Wn4kpLP)=F)6fnpX$2j!Mb0-M=>dVmej|4;br9hBvT|B@FFvg^0G#<@QjO8xmF|#pQXrK@FVSZ% z-3VfDNsV?)EqLs27f7)FN{o+{dX>_y8cqU{eLMD6(0!scVigcFk120nO4R{U#vDxs zTx;S+Me5stGhA27XZ;5$1AC_3mLzBab8xR?zU2k&l6ad>9!sc1yDEP;F+@)%02%n^sgrZ;1YTxV*RO1!4VkSIz4Hh>nlnytOoCbs<6r(U0HZ z>xrX3>#sM^0{+RGf92&StMr4J+sTbS9j(WKEc={dxD_p){L&1D3#R2j>)l<#1%VQ4 zIKXIXsG79g6E3|ou3tM$1UaAtZZO|OlT*^vjoI6j6Jo_n!i(T_5#YehDm0cS^8MYA zTTSMin7>GrS!Wf%tC4f>HMIC`o>DBvVYbv0mP?9_)qw{0J`^LLMTaCUD`%dTJ<=5- zLM$T*j=c|oaQv$8-uXZl^-67O1Zo)xewnP(C2`;BwLwWZhiL%aJ`g-iK7wbqu({V` ze{l}TbltqMBxiX+4-5g4c(W{d0El!oS0G2zj(0>m4_3>@N#0lP6B<{B!vTrjn<}OO zEEZNgJ(ym!!|YUMr?@iF3KF_MZRRc;NyE*wn(7L6CME!h@q{In5vB=-9|g;jfJlGA z{RD#upG}n@7=;Co99_~ue|?p7Bp{G5)m7)$a207Eln5x9ONotj1^0H z8}AqqeWb+;2ZQ8x*v{xi2Fu$2A1=K>HU94pc6XPF7lL^~DIFL_vA#_HP zAPzgBzke{Aze!-f=bGa5sWjhyM}KoqcgeuOq%T6F(W_KosIOB|uuFu!TBFVS>x;oD zvrZKSE~mAZ4rc-8-5x;V@-4IsiT;*3pjVYxt^S*RA$ZSD@Qw4i0QbVXo}BmML!?~P z$B~O^_+e7K4U*EWK|wLhL2(jv_c3kGH&3a1pWR%&w4u(#P$-gJ=jLT>ieAFoHZpxX zcJ{B8|MweVq4?-pFct_w5xeO6osFoXIk|gS5>Rzq1Oht~K^2~*N!mO;n4325&I~(h z`cSy|82`o16>8A|%-9dF!%o6-9U4(7kkT(lZx|cG$+bplC%9<<*9qykYo;dN-kT?k zA9n?^bnB(aMDHlaR4TvjkM=YMTE3MDlEfUwX`kt5X0ZV6;$Zs3_+yu!Y}Ff2Bpazg zy7<$d15dm@2D}NLgjLn?VK)hIV6^Z8w{!e|KWv8n-w)4Z>^qB^5-3~dyRA|I3Nx~= zm8jD>0JT5A0n|{rbOvi(;5TpLs~aTj4uQUVpMVFRFz&DQj20svznLYugfFt=^8nFg zgw;t+xJ@+F%fZ2wwhF@C+&N#^Ngz*+Xc`md?*~&jgi&$6<;b}5nqt&&=jTTgwzQUv zQ}(1l;C4WX^3b!id4n5`8$q(}xEhR1*?rvcEPMMO{ zMWXZdZR+E4PVVKyhxSe0(PyQspfq`q=ZSm^V245n=5D)1h_eznPpN;NedNynsfp)x zXqp`aIc+I!2`h)DJd(~^8*w)hyO8S8?j-QcI8y~y}O{QZ~Uu924r>FrDUy~iqJC; z{k$(ut|3`b;gJydng}U&rlz`Cs3H_&rGK;BVe_lZKU8%X)JfeMPX3IQi=?#x5pPMr z?)qOw+ZGjS?e}|a82-NArEDY<8KbSa2N0!9`tn;~>#<_JpP@GNl-Tq>_b-pI^a1Ge zS{GLi=;EiAjdFSU8>;;Evmr+tGt_qmJ3WV!cW*60B{-#6dfc`a*H-$qZ(3!QT-v|S zgc2R+(6iLL|Eo2y#jiGHQ)m1dfbAgq4iVHPpq#$TZn|aHYB*Pv*JHDX;}Ui1KbLc< z>_aDD4tHC3(6|=|h8Tmo{MhjCy#8=OK~d9ah)6pA8{0kKuA{$6bW?w6zB!`UJX($i zQQrby9r@?UVxQV(eR$E(k2i7`gYP1S;2PiX&V?p{Fp!z{!iNwT$fB zN_ayhaCrQWp*bpEG9Mr&2%58l2{oWsZ1$3ou{wwpCeCu*wISf^rVOAe>j@eOQg-zc z@+TNpc_jkjh$8e+0y?ly7r`@M8AuR7Rj!>CdK#lqFV6&_r2efR7+I2riID{5o;U9r-+LVltb4F6ucHxPy@-OQcpr#OdcH9I#zpeZ>*bU14L|DLVaNXNdypM2tRJiv9Di4R^>VXB}ANw za_V=O$CVf6#|{==yXH>-uiy6DDEju08uxxCb9a-VkWHz39rVU8rl`AYIgTw_j=$gP zzFN~Py8!C>*ia-1D4SOb0!X^Px`|HYHho%7LgwsrX(hC_S6Tu9G@WC`sn?fLfBDDgRt}WdurRfLUr!{I*e8B5Np*0Y4 zp8u)sxD6`KtG*?R)dywi5CnijzpZ6pV}#hXbO$GJ;BR9omZ$(WJX&kt&A=C#LlC~r zUf)(2+(3L)0uy9D#iY%~8}rP*5KbNsr0uoAZWjTxw9VU`9|3&Mv)Sxgegr3RKwRfa z8`gZM_)u^DAonH?sW9hSE<7`Uz4Bl$cBIxsFk-Lgo!C!$9q@#v#A4&x zSl~CAUibJu-HPX+4^KcfY12`3m5wFjV}Z#^yr&=sOxy0de1E?@xqN?o@!7hsa;2vJ z@RToV1c%+-YK5?}(>Q(@_Hn*64gk9j3kXj5tVK&$u)L6EksJ2yDT)Qpp2oYP9*LBM z8=mFccLycMqmOtbYX~}wbl>!$2H@@rU7b{ zOBL)z+TNTLP3?na%a#$q8?)WZ=p(s``+{2~;jHBss-K4~4bQ~M>H1!J^ZnpeA0qU9 z{#8+f$k)HHW%~>Y-(f6~%#rp&2s*`9%GxVa!^j&r@a2N!Hv@e)O+-OUSOJkFi4`Qk z6)Ko-Rv8`~<4P$n*cU;LAccCpj*o{IQz*aA9ab4%4!md-7pzCRY@}Rw4&7WVw*+`1 zXGnIFb&kKI(C1sqM9~#3houp`t?v$bDrk(wtl~I8I`S2tmeRXB;>O-#=`nc0K`*GML z?Ix2-tj}789Ag09MvB_abyg@gT za4;mjcy5q45}WA2@B{JTrDog}My$_o6c~YFTPB?%`%CLhigbh9L8vN>S+k z$za-RklbPJ>0lPRJ@TUfq5Qq^3yzdk{uCmu>3cZ^0#wzgRSDqHRQ&>bxUaSr@^q#B zZb`V^v>btS%~^VbyRb67l2fJYQ6eUQ?BSTJ%fvOBlwgOoR+-bOtCvHLsH+Y8%o`%j5=dd#OtjahamOZI3_Ioxh_U^ zqXfAF{{R-ddMDaO2qSW)ZEpCZS25!>zAk*S6vBw@2zvjhBP8iA+9%4&VIHr(3RE$h zJ8KeH-P_h;IQsAm(awkEt$)6GiX0G6AG{PIq-XlV`JYn-rP7E=;Njp+(d_-e0D;%c z17#>{Mm&S%^VatI!&Kvtl!w*hzY9tlFO3lx#Us_+i%utV6U}a1-utUNO8N7@<|d#8 zYxDCp7B_ZMMZFkj4?WDc>OFM^hxw?3XfV<=rD=I@Q+G7%zt+i(=9j_;+bbLywkvY% zw7*XEU4p3pm6Dy+23rMy0<_=KeIk)F4Ddm{U9Py^CBC8{gwl=ylOoW5*%X7xp8tse zjY?4j7>k7qEK-XvcGXugT2}L+!`pduEH3H~UNN`v@RRo;N@~LJ{ddhViqd@lc^ks_ zHOv#$O-|+e6tGFQJElSQ(m5xEcvMLG5~ob>hSk3PgC7p#CgFzj&$V52Hdun9 zdA`TM0Vq~R3FXY*0wjRBEtF>-+e4kdkh<#Q0uuJ)TsBYN0*twU8$Yq@HnbR5cAO3* z9+0w$7_Qw(t@37B?I_6gZq-D**8)nmEWxz?qD-0RSsJvA0Yl%n-CX4XR(^ubkmR(h zPb)v@luE~4X2&;H6sKOJw>k%;nDj&XXstQ8V|%E@zdq^MpYj^##Rk~_%y7tPABIE` ztUbyTULO0e^M} zqznS-wL`>&aV4AB1Xgil(fIiI&+ovoN{^scrN^A(=K^l(1E6bz6J>rB^y&Ogo(57F zN_=R;T6yKt)cE;0tC#~!`8$)d9$XFOt@$p}zivkey)_F58>}0ETawL0>Q7ScLGN(2 z#`YLUdfT0j2>tsBRiA7|Eem@T|19{c+C91V6o1?msquM&itc7qk#Vmf?r>&dul5ipATBKWYrMpYIOFE_ZcX^)g`}6zz&dixJGw0lU&zYH5>zCPiz#>P$ zUu&H|pd7;Z;FSR9G$_VZZI3Ghqp|-d8M)~%eJ5)L7GntQ398+; z#CkbYm%Drqg3mhL52=6kUQZsU} zJQ;r|ZFtmB zx*{HjgFt$}4v{Yj#6K&1B}tlu`w!4(gWwUT{iQNcClDGQemnd8p?(>vf6c-SzdQ(4 zR`Rdm8!CO=b{dKA3g5j=6KEE92g#ocPv3`Lb~3zfLrn11L%n6M_VkXCCogO4I_4cC zHhb0PymlW{yw@I*QMbqW>L0RzD&MU4qj}hlYE%QUFdNWfWBqpS&(}%{?;Y+hBade? zR$zYb6%vr8^*t`F4R{$Ab*bA%dF?ZFuH>Dchn^z04l3{Tt#*I6h|}~i zoQT`>|4%ntp|67Wq{vI%hvMp*qia&dGvfGesMO~REBY(7N?e-(L4lhYbLuzw2e;x` zuWgnf3hQ|;d%)`rQ3hbtF1^jUGs|U)_q>wN$QM;STRTsLoj!7&U=VE5P}~co1lP7y z`Tos(-8DpiK>mND7E(V6J&pDiO&z2U=7%$R$DJp6=4HtI|K1U$)p)3k&+WU@u<|Tn zQVidYt)r1Ly1&MF0Qw-!okrff@ud{y-VW*UM}Bz^4D11L zXAF;5`;u%iu=~|~O4Ub>RDp81a7WI3&p*;@G3( ze#1ACI#hX|Hodw*^gVx(Mi+&n%&AL>ytz;!y?*WUC&Yhquu?nQSJs*tc&Kp`YIyds z+t<^!CgDL}TQ~Kp16w(_>Gp8Eyndan$vxF7ptvgU2ohZV{u|FBo1Bjrd7VvGB^5+* z)~4}|exk+ggBzd6^AFv=$R2WwBKMB4C)tw&%GkaQ;5Q5R4g*$pJ-`hKpYNcqz#$~K z{{1(lrsY0z^7VdMHjvTPr|IVd{}CnWxTk($1j%*@DlQ>1B?GdQnjjrIKgR>B`#ZA# z9QOoMo|fdDFE0ZnH|{=#eU>{DoH`5f;bD%k&9E0=&~Ovo5kY1@*9O7y32yYUj~cXi zVk7T?*GAoXJV9W#n$BUOY**Loqh-}^*_DsN^U;pR9qoFU7%-%>4jo(!!xWcVvVL`= z0g|>fJAmto{}>mu%FG+IR8Hads9vNW=I&F?u$OB_en+V(;ROYyRxE%RJ@27U@3B}9 zphG(UJvwp~!18T~+qBf+rilN$PGzlb^H+3+&u8L|nP_YC1ecRF!$4_{X&uwicAI2? zQWFxvzq0Wh_@QZ6Xlb4tO}oWknB1$-{9i7BBk%(x`iA8#2Db?d2dgFI6q^1NoAsbo z*E=wK;d%JvKry-38TrHQ{{NfKh_*>X*TV)M)|awW=jGJqprc1$uAgIPQqR3#>|sSk zMsPdg32-YFuO88$e@&vOQ$|oPszpKC7xFQ+I+HQ(0X)nfy+0=nNr;IBtlJzT4tsif z*s}h4|A?sp+e>J#v0#bN<1pxWeQGRJ<{(StPUJthh=gi#zC*385A?lKsbdT$;?QJ1T?0OVXCk&X1h`UWzt3DYvD|ZQ~*qiJ7}hZG0x+*u~`+y zQ55DnP?#JAe0M0BPycpPtNz zbo#iu*0`+G@PABr79R2rKb>GRN#qm&j+p+TjLZPKvjB~&{&d4guAjx-b2+X2dOpz_ zNg>EuExG^?4z zAQSfBsZ3mJq`kVfjefQ*E#=R6!_EZ0Fud`;@b3!exANsapb*4S+0u6uglv+?EpY+rd;lJ!DyeWj=W!bLvmp}Vo`Aj9Cs zTkh94Yo%e!lRNc+3p$*xA_|?=Q$L#YbX+pb)Ez+@frj(H{yiiCF4H4l*Vk8?F_l#f zZ|>>78S*jARDEs*N`!|)@LPAdF@6*XbeP)1;kb{+dux@`U=Y_O$p)$dLo*x0ra7QK-9DNM z>N(3kzt_f>Lyek;Ogqz$C>uJtqv$^jb35-M^1Q#NJ!FbDJfa?WmP2K@!mLk~t4JNb z<}dt{RZ!MFG8=piV*En%QqOJoFXISsLe%6i=P|X>c%JhjJSAArsK3UMa$ zo?dS{_xB%%#_E=Q8=%M#RXSt~yGrR3*_2gamw3a%%CEwrzAIsGt}OA_PLiR}aQ!N5 zj{BC+Azgv5YHv*E1fyQMzfZxQ2}2heaRc%~=|6{A`}eW7{QCX|?rqV~2Czd`w-*ww zU&j3sX1HMor}w^ZdG-Sbh@loI3vOtLa8~kVBz^EABk~Qu+ivu)3~RkOExpd~Z#eZD zIMCkQvl1Z+h6gzV13#ti)Eif}*QzR3u&cYS*8=5nd`4a6^Ir>uC8Z5a+ z`(}M>#w!yWAMV7`QxNC`IMzAK{#|HE4@S6cYh3>=s{CJv{Va0D=qq<_^MJ~k{yWCK zjq3g1lS(T9)~TYaYaw13_v;crDL~Do7^^OzDHza%!k%xk_ys5veaR>lSW&wbO)k3= zKN$WspkLZUuj3Ga6hjvzc}@|NsNeq`9}Y^OxVoG8pm!^LHtVCHI4Xna5}yS$dDpUX z&_%oDv+eTAfs&GY_OdG<8J8$0?cuVUBqx1pbWdmefp5bqk;f;2K{?k2WlutN^R0wc z)NnA25txl>d2_(O5#~5&-CIb4%86Dqg~)u-)cv*$a{yQl89>&uzK7E;?DbO-`HsyJ zO*B0d?gWb8=Qga7_vsD7G!6`a6d%4SU{R6qfw6vQKW;Q{L;qbC8FarG$iu3YJlj~6 z=`|%5L#neV1|={tUA#O8`q%0o&5sU(Qg;5kIZ**_BXfUr+i}2-dxE85;mG$S)yp4`D_A8Pj^KkYvV6*M5m%_O4A0r z!~L@kO1;Imt#{N!abL!P7U_xy+1x?yf zn=l^Md!mcgUgK{Z%-8E%#5O*}(#!ui_r^y)d&VfPfO`ggO3)diJclcZ$2P^+>_Va!7^o69C;WQH%JR+H63^JMVI)b|uNS)%`$k z50op%&Byv2$W4~1O%x6S@=9d@Me_dB!`~MbIN2f|${3gv9jp}0k>hs#@G^bCKboGl z!==SZunnSzC8&ynA$u&(K8}j)64T{rd*hG9o$~^pj~PrmRJ9r{U0pB-wUR%R1t0sO z8dSEA|0W3oj^fHmTn&KtMVhCRkJQ04gwQSe9tf5>Fn2KxW^CpTJI>Zfi0#6rWA2LU z5@-X!d>pFyPSDJ{8}OPcFjZ59J}d})WW8D(1rrZhJWis#g*yy_9l6E|_K`;2E~!{h zJYFthUrx0VoK5*0u;R?o+*pA*%n0JQ9}qOKx?ay|@bN^4_X^74bMuAqnx8zuzngg; z&hC%I^g1C9cWuk+kylyyp0ZM|sNYH?GC%_iGeD&)ry4=~QQD3TJSO4(>#OLqieZA0Oa8r*>WD0b$%Y zLV6cjviA}HIrel46=sB~QW3u*QI^dm_+VC7J~8)7UrawLLt(P_mARpR2*1;$OPF&{ zolj);&xL*N>sPwxRg70>WxoP1Ed7xV_Sbp5NwbLjO7>-E`!H^gwjMj=9~=-qVQ3ho zls2`D%GX@D@^S%Sm(0X%7uDnKj4znH#vZ_pma~5A`rNqHVRQ6s>y(J{#`jPe8SGUR zVjsLG$l9ud`EmGBsL}B>o#F9zn>^wFS$|Huk7f%x2tSwx8`1E`;%i9%OntU2^Glcw zR8|MzfwUnMNbWo3 zC$q=6P8+VWKI|!JK^f@OKv*hF7Q4`4;4gQKu@T?CXpMX|5~hp*a?XLZ>^6xCTT)Fn z#%(*o>Is++ zVl+;ClbT`jZt2ZDflSj^ViCY@@< zXy}hYNFG0C5$*@%ZEbVyu_pFW2TF=2c`f{<3a|5z0PxovWEq_sI=GLU&1C{i60GoKwSKAeuG}~^rs7} zAj58(m~X1D>aD?SIQ`;JFZS@IHV>=WMz&|TINpv|L=8%qn%PxCY*exXb z*B46^htj8@P8E!}PI@T8#JqPU1y9Q?xR0qpeNBRRqmxNO1VD#-&AVc|+Y5sZL=xvt z_j_}rkyj-%D@{xB@g9W)qczW*_q89LQ{JzM;J@=GQxkmJ+iawuTi$e(*w^HNH(EpH z?DemZDxp|2hW4W`Zz0!-e*+txc9)e!8^;m`_mVL8@@3hMYIGQneyd7W7yRe#^7b`U z;V$h)Fd1L0PuIq!Hc5f6_x#)Xf*8+h5ffjp#S8{F!6)pg1oisir^;b4A~^c1?W)9{ z4Mx4-QZ}y{&~-{9*TK9fb>lNh%T>4bo5cW&4u_{cX#`2%Wv>~!5YNMLH#Wc~HaJ}j zTJxtDyEtsf@3oup+EDxnV|lO5roOj+=J+qu+<0vnfm&08QPXH5X|I{1`=^cK&r*bE zFe!XI;E{bzCpgyqe}oj?jn18?;Ot8JOe-yV^WrkI1nn{2lyU&=DE~?YJH#Y;W_&RL z{F2&C5$#t%8T$VR1TwK@^an-yNb@_uFZ)VMk+zcW9lF|vP)k)IiF*bk{C8#EZIu)T z1I_P_#dY1891CqEKZV3IBW>8b5dHo(PlW}4%)rZ|nM(Ha{!?GxIM_!24GA--u9SUw z$zgOTV=skdm*`R|@izJE3hwcxiTxb`))RKt`E#u=Me=Plye}n^;SwK7IGR(}%0Lo*+=}Iib*9QBbghJ|q z{_&8OO>1QZT`*snNtsyE^a??gbP<_C35x+;qA^#|Gk7bu->oNfzUEUugAF>GY`yI5 zRr3yufgF0;=-2MA7+OoGaT3)p@|lB5$IiU<%wQJ2gM$GiUmxG zJZuHVh?bd&nZ%>COEDck?p=ZU8U57rjy(N;&mAdIIC!&#aubY9#93O=mA})XzjhMjWGw&kMtg<)Rzeeq26@9qlL-+^2djO`|vmLU@gFhk4-k0sAw zDpB_j(fP_GYdN{K)~z9S@xt1U_z%4bquakl&3dXjN)}e4W;Po*I)@_A@c;I4SCqN5 zd@r8@y3Lj=kQSCEc`T6*L^&331un+s>yWH%$w`~Rl*b?t|7A{s%u(Rrz@jJfPvtqz zZhNrvm;xV?k-I+Lo2^{gSN19+G!K(}VE!n=Vmk^T!P;#{|Ca=h`>rD}zm@LpAoR72 zRm$nG?xj|IzP!OOs6_ zu$sR_oD=*swoa$@);0=yW>|aJXDH=`MAaU?tbT$l#BkOZ=64Hhs^ov*7$$SSi$+g zx6OX}^5%}ml-ceyL*TM(&#S&LWi#W@K6;hM>4gQ70pBuLl}9c+))%^7?wG3qJ3_Bh zVa#X`CheLK{D;d}yqszkvRjVZAAJPl41p3dJ+Gqf1kJwn0=5JGe(1A9hfgnmd(49E z;YOXZBhQfC@SJ5tCf!{uwBj6-zh{X`G}1BZu<~a#0En_Fns?~!HA#ULazkV%geC7V zb4nqLVE32UshjWGXdP{A&_;`?pn8}5QcTevwo0Td7-y-N5RaeKOv(~S7DAl`G4E+V146?onHYZdN zX|j>gebD^4#}LOp=12yhd^6ymM8CNS8F_O%$VlvbKqFvBD)Ded4|J|ox*DjEJ@)qU z`VoK!4Sn!2B%6KC48iD_i{Q+gY6Eab(;HErXY?C!glhG(h7mj;1Un6Sr`iDC~EVjuV$6jc+F%#rE%W!5q@#VrHS{Cp=Lf!l3%7 z2oJpT46Gr2+hEjrLfUd*wah)ReWk5M7UU}OTATaXii86O6DL<0&yp}5dpAIg~>f$Eld%lb0kUQYmENX1q=@J|8kSp4_Qy&Q6eWa(nPvn5p}0> z8*34xr#?aJzc{zXzdhx_Q_&ok2kDtp3?%Go1mcFQ@lh~uD16TmPlf_dsT7(}Nx58{1k3D8NWFf88Xt3xuWV;dCMX_;6r>Gnv0Gt^ zs*sWR1^DWguoI7QUD0-`UoGOF>hI}hroWiF{TM7kWqi5#Xk|Mfy31QaMJ9i6@;QF7 zoq1^L1GxqY-Rv*zsAFkB3*ZA3&pu_)T5nwz=lXR;9ASFN0^5mZw_lefXehxZ>&pvk z&lb8%dNL(0!%*eak?nBpc~`Zl)Hf;LpLERr!li659FU+G(r+hjqmg;RIFT{^vq&4N zN$1qw`Ay@`$&1qDOa2a7GCU(m<-ad0Im?Zy={R=FeOj$kB0-LX{Ki}qKTFDe*vB2i zS8&^9vrMA?#L#{@OaI1GZ}9Q<1&dbxKLyfhCO8J)K3F-+qr$k#IvLov&Sb;w%{;wD zGy>2oR(Svwo`~qH=>f(-Z}?@dW_|FTir{s6Fd?JOspdRH_ebK>4<V-l_NapK~!_Y^C#jvS3pp+WcBtW^JikYlEWv#uRQrsn}q}j!7qki4x zJD4+qbhyae9|amoy5y4bLxV#$7*$ib)+)C{47lFko~FMH0bA(@LZHL5_+pEE6K~Em zsM;iKLzLE&VtF_-8E!R8Q>PbIb)OHIMT-{ac6PP>p8E_pjl_8%w61SkPEf~J-Ep$9~)FEP{^)-58bIx*RAvIs!5kp!DqP5VVtq(G>gVB8sXj= z9Lu?{!+_eyeJL!ooU;<{J7mAI8q&16oAXNPi6bAb#2*ot+fcD@iQz$??y}ZE{*k-d z+@{QE8+y-sz)LfQe<%H@=mq}TcIE3@%RP%uzn+l0$l=ooO7=NmH6-DV_L8NG@&9KB zpaTI+Xk?cklWL+( z7Q;ZxGbG4J-R6#b!1R)RR#zIH1jZA7Yb7j=^-KWsp+C`4y}%a^`b&IQea;7swBWym z`{?n)ljJLmrSiI6&`h7J|7%*JaFoyFK+wE^KgNI;Il>g2(cY?-G#Qcq7lT-32J9|5 z=su5%Fy;2MdJjM^_~(=R!=_*8Jrbt3w?^`t?~3_9J9C9g*o-~CVoaT%s(Jh$-3Rta zNTp9gd#fS8ndfCCzE6du8CXC*{1RBUo7?H>*(prv)l~;N^2gCB`S~XUR};-I>yC=a zl$U$tjthoetfPqkv#6j@Ksb{@eY+-A8}b|kNbQdEWXYS1vG{F9Pg-2Pkd7kD{rx*4 z#N*7J9w!wWe{*ZEos3cpxI9#LLxrt_0evIf&NOwkrQ!I|*t9Nfjx~a*XYv0^FMdXU zK#?aK+83JdybAbs#7h@YMIog=j^TEC;pEL0muY9n^Cal{QB0i;-Az{uOz+CtD1@@$ ze(C`kP{c-y%-Jy3F&r35``G<-W)LKuLD{xQG@RVv+^gm-j&T^@*1>K`?QdQW&Dw4PYU;9_z2_E4Xr5KGOy7`fflL^KCTD?tK}TPo zq6I;^u$d>*+3D%p-SwFQh2X?14Oje`@o_b*8*?9^EO&plx=9!w9^2)28g_zk<5NZfG|g`MUn=l$^=ED}y2 zkq#wOre|_;2~N}2HE8~(8=*3!OSxEs0qg1N|E5;?+PBwg&$frhO;0GB(;CFEUl>x9 z09-Rjegc3KnjI4eaelsckc|*tkrf^%E?^BuaZoZ6w5;UWiLZ2-3N8WKK7$aM#KXoJ z`F{8N7OaB3g$w(QLK6nEf0PI3O8DC`osSVFU-L1I7B<8zEJ5#n7Gb~~iP-|)kcI2` z_IB%4MWhoC1KDw~sw@fK#4~N(1?#f4?}CH6l(9iy4h<^W*P=)OfZ31T;~%U%gCAAy zrU4iQYt1pU1pIqRYA(ZWg$F-u#f*@J?~SKh{$N<-=Ot!JkAeGImDI4E=RDhPFpn)= z2`UZ?Q&yJX-g)o6`Qv*38dR$NcjMSbL#CBW#;VVpm7;I^2NALJF6Vk`3U?+U+Ja3x zS^RWBcUllhsxmB;`d$FKs7ghMp`6UKGoefH`)qbguS$jS^x4pkqr^;#632By@^Y7T zS=yx`ueblScIy{jAnB1L>ISRWOU-qH{x1AP3(c2&falVuuFM@2Ux+`eHvji8B)F&{ z24dd4Bl4b}a#+TVPLNvA+abk-@>3AdLBzy+m*bu|x^Gx75TbVz`Zmi{ zQMW5|sMef}JF-_pWWXd@1pRbG*TklPVO!5P&=YT1*9NgQ^>i3g6%p3d@CS4Tw7u!# zff0F+f9&Dm@gYZqP3k^0&^(9{4eJ9r$hKt+6iXGS7-xQ>1{GBYP2OLAo~KE)1KI2M z9>lh2zJD_BR#{tT-;2T_!D?m|!-TYl6NfP$4`ZJ8b);xvy0gY4UPfGtS=dVc`T10Puf-)5{l`K0OK0&S*+Q)wo6%!J0p`u9v;hFiv;tYuFHpd@be*SB+C_yB$NfApvTeHbcM*%$Q$Y_Rf5 zAX#{PFvr!9?ni=EN17K0u5ep2733l%Q2mMv51y-Ao0!5BB74e0pJobIm(d~yE*$54 z+b%I+W~R<>%>cP%6Wf3uz==zZeb@LDrkFLx2J7ryFTsOJ_nJSDDcohLF`X)N)kL6d zl_86DWBD#C7noq%+C&{uXfffj0IExnoj_&aYhJkJXXZ-p#fW@H{0HYw9wjS4c=GP2 z4@0fux_Y%2j3yU!PqCrq@jV37Trb4m%Pkv=S(inblqH9*0`ko~ldNl|%S=ZFt-2qT zry+(BXfxqkAJe8OgI4jX&tJmUjdtG>GF+7>=QY?CcL7rX-G|8S9n+!tezF|=z<+yb z;u#V+#fHhpH?8yV%rYhA8vJRu+~B%S_R7pgm5<#GPPaAqS#4^6{_AFT-RlwqRbw-h z*{+I>r-M9uBKsy?`H;#-2YENKvgt`{0AiQYvLBtfwhRx`RgBv1cY`VM3 zBdMCY^TfBy>B7AK8pcPjmVw)Zf9VU_uz5!TLyURdfj$t}BbxCT$e+5T`SywZ-#9IY zvHo?ZpSC?XwIUTA1>0aKh$iWm#GtN$Sk0AkB1N1;|8-F+^3aGKMQ=d{IHe zH9UrJ6W%?pk-Fd=_qk6l-Tan=*BL)%5hTjBsEB5pZ}qsLV~E18PgJ!jpo5#vQOA^} z!7*xo#NXUhZV1IeltF^0T*C=PPm6J$M{`33kYAV#XIE%x2{{G;BHl?0`|9Oiaq1UL zP0dOlEB80$1u6SBMGOuOhJ`fW%^HE$mXN^`cV8|K=8KoUIE|k1?7zDDy1JPJ z(dIwp$yxYsDmYmNy*NW0Sas06&r(sW=u?zjVxCC})2EX?-TR<&wntDEi$U z)ky75&JuX;LNN@|x(y>1Rn3qPD>GVa0?7t?776}(eMW{LMRKKJi1#_4aGlhd5<2$6<|O?gJkJm^h^brfx1k1b!a)()S*=aZmafK@ zg;$_fopj60gQk6(WAlI-g+QuKFye>o?bPBm2(*k6toC*e*QpDXk2J!EDlXGpQ$`$u zU!5ygKLU#SiZ?z#!!FqpCJMFont&pHwlOha4K3L8)^D^!oCC)(EDsh$ImhyoFlMYgDAE78< znY6>MU4(o{JDtWr;TxI%>Mcwl7hQ&T!vF@C=(eT@ie#F-m)ipw&3S3G!$w?$+(@Ac z)j(&v-P@7Kz|2QY`({DfCA#n0|1=tMzVF60>n!eYcAWrDL9IB0m4jCe$P<2(t_uGA zvaE1SVF(zcY!{^HHo)WA&m|W@8daU!P1lY{-b`>wCKzX~|1RF@9S9l!n?V*z2nc^D zC5YTy4{WsXRJHO{x58gV(!f6jb!^00etM(|Anl`%0F+HquF`Ea6&~12wwO#X!J^@& zbj*+qgs~1>;|5=6@}<$=sXFCy((m@{JkQQ5ha~a44f5E{VFV#W3;_QbDGCf+`*%<> zMWP7EUoBeqD;Sy75cJG>TPAK*`E0sOBd7A%)T#CpI|?GFzCyXO`gIfb&UoTV0;*A@%CLH!E!7Ngw_cv(A-QE|?0F2oJiA|Li8JPJr5P zE(^DF)`imB3|pt_VBD9C)4|IP`fd=6)4N8(cH?}J`ITGEEP!idg?y;S%i4&lOQwN* z^+hbMD&YtRBbM{(FeQF?Ct{j?;I|DH&BG5MlHe~Y?nH&sQEZr2!@!q^K#h(A2Uitg z1hh(X$I6h|;yNs`1On~>(Yq2$WH3;`VNZgirRSdfG}R7rD#t+RzbCzZ9s!qrVYp+p z39s_GR+=s^)`x3!@DYbz4&be3HBvr&B5hR**t48}0EDY9d^=Lu5p2}l*|tioG6l#> z%Jt!pJrKb`(yMl)#K7vHNw4aEaq^aaHFhjf3hAQF!j@ESZbJo}vkR#1DurGaTP07Z zH&ZI%N-L%w@ZZI?9*Gg8%jrD7H_c$kjsh28r+u?E*Eyi3Z-;pbP`0AlZ2y|ZKs3f) zw^<8UP6k44rriwbnPy#Ss=+{;$>!>|Sm*3=JP~Wj{Np4@8W=+q>Su_Y#(8SKVc=IR zyRw#d-=O+J_4feVpE>}s=Wv!x49l-^@wqC8o$Hd>H8$^0;yC_^Gj*hlYvq)4hxnXy`I_N>0R@u+h0Nu6 z52v1;;j2I$Lzpzq)5)RLej+yvPnF0`ji@IN94Ary_xH@tV>DdDbAPBih{mo{_N^WA1ViDf&k=*n_aO~5~7 zBre}}ScPo%z7pH>nQ)e`Fb|=s({x$!{Jy!6dt>091(y3d{x|=N5ZPCRPbNi*lLLDC z{4*CkTIq#rmkz_kt=JDr3-a8Qux2*h*S^RBdx~qi z%j#QqnhD)@vX^s^{A&t%Mv~b!*lZVz8{W4{gDqA;=eMGM@ST>`AQ0oZput7P|X64{5^V+fwke*LMV&fk7#Hrc`>Do_IE`R1MP|-gW7;eUoTc zIBx}0s4mn;kE{F>2`tw4hy}TJUvp;xp);=?Au05)+8D5FF^d%SDikFT8}uiCY=zaK zM3j#~1H_s}D&{w5g`0;u&ia$!+y1rApQA|moo`URR9KgP!xPcrwz5xvS@gJMooYKb zmi6{AA^?R;Dt(;x0~lijHJO* zzH0j9?hHwIbab>x2q}*_29WYBBOBP-NO|f@cUo^Znr_s3K~uY*pSFi@ENo`u#_n&%T5WYGRXe@igf_gDcz9&fPS1K zpZ4()@CaxF%|X_FnAwYXQ9FJUrD5|b?@!OuaH-9<>o1y&sBPxs#>y{qeS6A;8mIj> zKQcBU6iv>C&Gr}c5umrxHLp!wC8+I}iJ0W)!C}fgit`!m@Sz@sc`yQGPi>=kwF4C! zYh@ey_{*i}b$n^l``^{qq`Mb`YiA0|XiKhQwe3@JXfqF<%cqMg4}gPVPQ zkG*R6Iptbq>VunB9FL2(!UR1JS%zMDE~7;`inNa%EKkjggUv8Ex_V!^dS7AQVS8oP zV9TWBZ!0dznPCBJb)0=QqW z@AkKw58>^f*shuRq)XuWO_u@?R$TA+jai047LKQHG@~8Y(!4D2Bkx|&L3|Q}o7{e_ zl#70yt9Vf6EwAMCL{E!4GQZU*4Qws=%N?989So<)ZS5YRbvrucK{npCByWW(w|WL@ z=`~#ctp8>^k6cZ`$v8fBkj-^*IhyW9NZLr{e%5byuEqA* zR-1_erQ@{1NuVM4+**csu@!FeU9O_*O?M=Pw(XT|J6+L<>Fb$nY4i;)$EmcO6q;W!h1`xS-X=LSqAfw=_5vTKI@czOg z7g*1`>Fk{M;PWLoqf31l#Q`cLe4}ZQQ)$pxQf;2G`g;sC?k=DLhc6w9J*bFgPJ+qF z`cItBa#M0Slic8+M3jxD$)IAXU72Y8Yr6;UZms4{eh&L*r%yXTKLe7~<4P%^FI?gN zCA{e(sj^-u7S4Z9zS++N?;a1XfA+4;X~w^5@Lab&W^CfqsnzRmNmW})c{*%K6ypmD z2$;v=>-DZ`Qd6FDKTrs^5&@=s)lmCuW;A_&JX~G--Qko}21C}q8I#aYdo>h`lLGsh z!ky#6iO=4i8cV%?S^B&_*c|3bz;zKvoW~ZHRkcg+n@cquhxsusV3Ati0jRlN_}+&G87rvV$?jMkayh`4&89cddSi1M|Uf2C+0 z!ZwFYf}fYi={N;dUxUrFgu2_ru@kyFg6nWS@;lZ=UPK%e1{TGT~Ze(Py*bx_2MFXi9 zCRLvsZjWW=%fx0^$(oy6tUoMact{AQUX%YUsZJkg=}&3q-N+nTlbG%KJtYbDS@8W_ zXRnhv2FBWqbh`M|(KjPmIqU+q>Jv%ps@ym8nJ@)}vhJ_R^Ya`5e5f)U9{3j{ z-#G<^Dr+A!VkY+co;xF79k?8O>+l9WimG5`nna%AoXzOC|5^Uk0c${eX z$h970jw_0%;pUtQwzAyX2`FU3HC#6gz1xX<3|Ww}a93%(RfK)oCfWq8u9z6c-fTRh zg@xEs18>ykCg03c@@H!8B<=CHilVCdz2`{tR* zK)pPR5G>wal$?Vx%D2O!^ws(UMFr?%_go>;0%#a!!L<{CtC>A!WdvCLjsfGABa^Lqb z#ST?X1kAbhaSna(mq04vTt92@fvu3vJa?$H`qa_PLEV~pj)7ZH;w-G@zOT~oq*3B3 zqD}|C#SBkpYuF&(__Y5E-+^d>*7vLxtpV}*%4>|inZ_a#TWt0OvmYDB6{bGV#;eT9 z+?Mrevt-yMS^rs*;Vm zO&}vb+aRQ3@!%R2SFmdMR-N7=(9LqMHa4dR6w{9b!0nMu?mj}m1u zYYgnd*OnDuTumwbtCZqd-jQuGh+WKQcY>ZWxT@RLtBT%*es9vyEVcyIq;I4_3hMA= znMU+it^TupMaN`NshAJhC_QCQRkzrKxjcCy#b;n(VC4-pwd@PYqQ+*c+S;+?C2aFJ5LoE{lKep zi`=ALDMUe<&ca7NW|XPxw=I_?auP}hkJ^5esg*$N3MzTFtD(1A&B8A(^fGC)6mcv& z(~N(de<^Q^3HYZ^H-_)(2Ba1f&5=T6s=zD<2GSYn2MR5eV)RT&&d2kY_%r<9n6tWe4(59P1i@C_Z2AN zO|EUP3u8P@G^P3V&7>E*nmXu9X$l^`QdS$kc|&SnG*YbhbVPHnR_v`lXX*7tpt{uU zWP~gZ0CuzfRvV;NI&+F@g8BJ7KRsh0fsr&Zi<;2o`rB!a{~ny!%!Iuql=dvu8M-79 z#t^!jcp|_t-=2MNp(BuU+3&s-_|7M^sO7xXSYT;rgLdVY+H#e}>=vNLsO}wRhERG@ zi&1T?)U7)p_IQH34y3PBz6qoUN&|e6MJ=qNPiLPppg%!}-o&yGXiwP!Gxq#Wm0hlC z{wKV}?(O$0BVf?ubu~M1ZHdtU;mdHCs8q0;`JZBbb74sT7c+@Ui^ZycC%trl;cG+p ze);<=<##OTt@okqX-SXr8ky=p0>4?I%>uQSAQwERt6yq%3ssN80vRf_MCF3sy)Fp? zX=Waeph#3&4m=9OgS(f`aldh;d&O@a8{n6PbJuywKJd{nQ{Ai$`BsMSo)Ndm>#V=| ziSh+8>Y5xg{r%I=B4Ba?RBx#mHrMi!l;YA?Z&jZm(eVj)1%<~W^6}t**wOQE{Y7y&e2X&rYSoVvUxgP&x})X~$?C5w5w5E0`ajnk6Ab6EHpTl;s6@||vHDQxn)hL&!p-!XtspabDeWl{Rm3fz5TV|4XMlB(X5 z{^{^j*R>qU9P)dDa`uiy-zk*TK{A4+#}Wyq6NhYZ<9+}NP`xWNEG%+V?<2FHsU!RyT`D4KeGJkxIzTu*s)Ggp@fK0V$ zVqqlx=dkX$FHEZJSQr7GA+&m<8A=@^|B^v_HlP7RWdrQ+95S53?Ai9hPlgb7Ex@tP z3>YMh@4=jD8eT|j45ERfH^!$c{dEzi4PC(CK~kxQPFYYYF>E+mAdnKa@pMsD3C8=U z%}>2j<=U?=cM$kZ)@<4Q=1QYJ!+;`|rbmv4CV~2v{hRmZOZr@DEDR#$NpzJ=V z6fRl}kq-`ukFi(LOmy<3W9TuET6!MjehwZvxg(#hQx1Qv<#G#l#=cuVwJ;NfT{;t z8FB^-pdhDfgNCP#(5bvqk=r}k8l_W*a@-Nhf1!ebl;+`zVRq0-KTShQ=I=s3ynD_* z7$S{~jM85x0$(J%03+w9XSkx;0rK+vXdT7J8(hn;S!pMp6iXJo&l3~1{Ac~NIQ4mN*YEnFloaOJR7|zC_~$ZI>b!eH5jYL6 z;hc`y&09YnUcnB8ioul76>NI7d&}+hZN>}az&h?NW5zQ0|%x5}lf!8hw%p+5zvX^IpX1>pl`E_k0p@;aRD(aD@j z3QNQy!#t<#TF;E$exHSigqk(B*yM5a-6&qU_bT2qIfh;(E~fC{>`US-&Hf>m_~{Ya zqdfPg6UZ#qG?{(q$T4JIcZvi^z1~>1cybtMU42_|O^YB2%%SFu07}(hQ zod+Hk8l#2_ff`1p6P0h)2Dnr5Z>QH0%wHC6YBZM=mmgmC%Ede~<0ay1xha%`Ah8f4 z5#SuuB{pNa5mw|MDkcctenEGG&QP30yyuzPjmcXPcb*A9yA$|~sZ?2!&nASImX?r< zjx&07U~)N4HqATG(OF^lT$>}KCRnyX+B>rm>0NdpibNuBpQB*zdwg4hoe{e-e0+Q% zeSI2>cu1lJWnN+7)a&)4Gw#q27=ZCHfdykkcp4k?1$pUraLM-(;<_DPfX!%Ii;T z(L3Uk=MT-7v~;YJ?|e?tBJKQ$!~91}L`1?m$;GbIhU+9}P@hH_Np=c^FG54R@CipI z`!F3#8`e|u+X=gU(`Qhi?Q%1c4jpCj0kTu|JOQSHa zy$UuzZ|-5bO1U{$owjft*!z84kGjVFxp1jI0K>c!HH3EI4EbqMEOM<*s2Hlsmi$wP z#x_jz1DEY8rQfZh-wXuja!cD8<$Mv>ZHnsN&Q|0ZHENX;tsM z-_*Y%BuEIj6*>LlhIrGn*M*H*2=e!RW5CqO&o55d7tek0TKBI3*q$zF2e0dO@n~F^ zz_~`LiGAqPb!^S%vZ(as>A5fZ`sKUf6AZp2>De93>=(@@8VQaO7_AU^aWtUiSSN9o!=~^!tqxt<@-Ltt3DU4@2zS_%^$xTunCJ) zcvc%@*gFDUc%K( zS|akN%WZECURqPLVylUtSR2ML55L;o8Ry0`h?uFhh(Fu-60#ain10pP=|%kWxD@%1 zx$I+f9C6Jhk|?@-+Za$_;!^V)>KW`K=19c$|0#v67~VJ-qz~ z_k^q&K{lI+fnE|HoYJUAA}tTMJT99>51vIuL_9Cs?;EeK-#=O%N%pJ|9jQ(W zNRTz1nc@e_Z0o;BMIS3Yp?HwJY%YCqxBhmT+cluXv8C!6Ij?(Ajg*eQu9oGY+>F9@ zj0)PNetr`;t*o%AUHl~u93yu(c_2P2ORvsPwJ1qxVx(05g}LV<_*ce6t&S=rPL zc4l*h)#6!0VfK7l#yMb5nhnNJluE20xKC2!cQ2#_nzgZ6 zh7!{wsQO(x%Yk0YGnI^Fh{Ebb*s@=RZIL{wihk=jKiE&-E%e5*CamFHk(x*ppyT=w znlkJ*%K%m+AG}Xx7RU7k?79q1I{$80v$Y$6no(G7$1mRnAF$?zCK$CEgeL}4Pc)^X zKieaTslM6laHo*wp*3(FpM!#k@oH_KEE*6%5fSp_s;Y^vza?SymwEJ%6f1Ua8kz?t%}?@kAYH01;HY`#EiA?Y&5zHd3ICbS5-M-pX-lD>;2 zE6cr|vy3`O`YG@3T0>%Wbu4}9AMn!GU!G-o`GgljKV>Ttj=A0w2smy~-|FvATPmeG z9yO1+pSQ!!dlgGCA+5|8^VOHn%A*RZ@k#p2Z`NTJOPO!jf1Z7JWIHa2 zKPWlJS~k%Li1;fo!+nES<4e&$`e+1_#U|$~`YtLZmmO!%Y2(F8G65ED+x%j zGR;7g2(g_IPnU@J!>Nh1UR^_?Ay<>Z6^`cuv&Ob%m0>Io6CVo15pgtZF@cTGwr!%y z7iC|ai1#_On*pf9-w@z$wwR5qx_lqG45JPirf#l42S0{csWy>K)&$3Xl&M^{bTR>K z<~^JnO>_kdm@FEK4S256&*&0e2rULC5Ci5Edy3acPOt&J^hP`UhYkj2Pcr*3`D;wQUGtW_TKm8x%4(>g;24pU$r2AwJ~;`vKMCG_l+nMCM&l z)#vJ$Qi?bq9OX7c8E{wcO-mq&<}kJvVtydrS#BJiQQq<$5iwMJd!)w(;T3z*ZNo$W zGLQIthw6CIRcnv$*8BpOAbEjy;pU1?&D+WLK>nz&Lu$TEvM*90K6Mnk!`bt}PEXwG zm0*g-;OD9OPzCTQd{qW+%|!B|5|)A{4pFj@7Ax%!%)0^2bdP5flF*#SGxawA}eHi5WSt8lXw=zO9*Ffp~@ z&B#hqUc@MRq%zzF+oAAFIh>(v1mj3@)zY}y<7Pe)rV0d6+Tmwch~2i5x#y}fQSVAG zO_5UY<_AFDly58DA}Y_Bz6XNg5y}s%Z-Ch#4lj1tTa=BeiErlnV_Jx%{DQH89(1bQ zF{?iM?(twlsjqoqu+zxRUdehC(O>TOE?Uk?b=PGz^;UM0pV(AX+QI($S{4ek6KygDf;I?<7?|Iq2{FDE z_fv*ss~kpH^rCsIfn!&%nWMc{l+21&nL^7s2KKPkVSHX&ZjN^-V|9PY+L$D@=B?>L zU_n^|pd!$~eAordpsKGTzFU@F@zP^m5_jT86*u6Q}<+t&)zFXy&YkP7Xn;AlngIObr z985I~RjWe~B>y+Dp8{oJ;7XiLRJ;$b4R_^E(!ZT-NEk&TQc!-rDtmn*n!N$W(Q(v; z;2N>)Q@1`!e2%gi=r*X=&m$gGCFal-_&D2DZeKO<=CIBNxs=0XPw}YcuteULbq2ON z?H370UYjSd3?hX;J6KTgG$V(UpwHq-@s$Vf8t_Wl%5uECit{edy<5SlHI+cbJUw93 z{8*mv#_+uGabpMwVo$Mf1Mg?u>;SB3>STU#po(YPQDhk2?aZiutHw*GCY9b7dZ%&R z-eT2{DqK_cZd>@0+Xv15QXUsb7SKJ7{7%0_A^&<1%b+`{RA3pJsIb8|BQj}0UPRa3 zl!AckT6hQJmX5p{SO_yU6@S_XY!W7Z~icqVw!o zmRemb3>@l6=bCs2!*u)*C}$E!2P&AHBfrCfxY(@%PGEJOKmUV5d2co92NW3rxkku8 z=lN{E53b(Cl4$PzdAJzeDxQxU4*FA^O3|Fn7GpJ`kLD{`xC6Wn;J>c z9YzkgL>xj5-ZO&hbNK`%Vv9~0^;XXe420IobMU|>X>Z4JCqH+oZs>v_QTQmx6BTk?;M(V4?b9| z0grio=hoyb&eEnmTcy`rQDfDq@KqAd?O>m8%qe{V{h9832;jNQ46qBc#kz9<3 z**~|bd_H0f*a6N^U9IiE*?Ntm!5RVGOU!IUDMVH~)E6!`0kY%OKqiMgAbKv>WyCo_ zFL)jb3d{B8sv`i~U%|z&SGc1sRgH#zw5Tgr#vbWM=jUwFElLq#0OwJGxq{~+X}Hk5 zYTAI}^ZQ8V%XfNE3tbTsz017DL zEB!%lAI9;-$>@l^2>%N`^#d6KmN4QBtPx)77-Q%)d5_`PM}{c?wTS1(8GN%Q*!NCS z@hHiaBn}HwNWhtgT4?9(PgVc89+$jj4&56^H>eM#BAvCNnY=eHR491WPW{Ge2gkI- zcY$dQ;H(*5+oXB;weUn3T(P9LFLg9_{zFUc)}IwvjnWthyyo{;Hr&3FO!w3tM!0Y9 z#F@8(xKQuiJGtdMTY&ln=q$CZiycWlP_bsA=!!D@PbZYZmxBI=pjQe8yPN9sk-EMx z-`Ik#m*OrMNO<9fhSx*maSb6mKtOCHmpYg#!IWY%mMSv3hj&l3W4vLT;TrRv#^HHe zTfNwv&1Ep!gF7Er^K#9Q@e*Z{cT!UA1e3pX(Su@s@Ma7F4)b$Gfv&>abJzPy@cmGY zm`8OxYN_H-Ya9%8h%0TWb~TO{(s}?-n|X#_y7?$od(mtN_O>;mnY6DLARP*6S+Y?=K4- zM%HkuvlWBk?2B1k;x|cYETMk#lI6}3k)AHJ3kCiDkQ!Up(|?v+?A4>P4Wgs3A5mHM zrubOm=T4V;lWqnvCdw22w0n>B`40eQ?z-G&47a9rW4bcimK zG5c<-O;;NxIZMvru6_%JsT0|gntuadb^(8i>)7DkH7DIm1fTpdDntdC`*rrc!&u6G z?=BpCS%TyVzz~92#KMbsofv{VgYn>sy>`a~>h61|{WX2BSPS=g6cf`7&$c45xT(w?K*=A02eWv3 zb~*rq{UP4xW5YT%@ITo65bhP5&|AEut+Qf3aNj}_k>0-R7tN;TNz!jvr)d5sc5%c0 zL(Bm!Z)fxDch1W)a6_7JI?V5WXflSq>+p9p+`8hwE(Hj!G(+0In{4w$U!HlVq1p4co`vjeh|M zS%uYGC|Yo%St!?cYsHRas_{;wo3$>(`!^Oe-ZE;{~bw)2(o=8a^?zOD-4zr zYX!Iju@cWE_lY{G8C$Ii@9HTn*igoPcUd(nnb6kMtZr$Fbt2-ylWq$O8W{8pYKw+B zruKrFhq+xhpY~tKZZ(((`Fdt9UGqCJ3h>M231EH7D(`cgvI)ibo!i|z>!&*FWN-`i z6BIuNN*R}H0@SL9Dd!{4W&hd+{q0mfrkWimO}1PqTuXo*A= zvmGu*rVs&a4kV`?gW70Hre>@B@z0AbR~oc+H@-j|Mp&C6nZkn=DyLmhjLlYX<5ZN& zsq5F#zi{4B(z9JuKLLKXj_}-UMPNMXE738&$`*K4hBFxUU){;xeG)X$0U z6I-*?_~(3;OVOH?^OL+u6ZlM_v_D*4KMPKI{^!)7=UNZ->nYz=EGD(gQX#?0?n?!` z`F{XcLB>#Tn}T&(;06G+g|X{~`lX;u(_}oJ zoI5Po81=RRT|JKiy7~^061{Ro0iQb4DFXJ?d2Ke^c6iqjX$ZJV=l^k)6CcSd%JX>C zkYJjO%l0ICf71cz=k}u-ny)O(b5j0rgr}cf|zi6D>J-YFx5cnVW@BgVQwEy4#`Dj$< zQf)_eRTD3OA%qvX{YpGSP|qd~++JaLtWeiUsXFIO0TylM;GplCq}sBskiZ_ZaWM6h z;MdNk$*Z=q%8%vR1U^b;&v0G)0yCL6H#7Kd+E}ivz2J_;Y5*U?ltB}ZKMTuuY=o=_lGxqGS|egntT|_d1o+?$T+rU-iPYk zlKYWDc3iDUT4klDZ`8LPMsL4)9yycvi*c-cd?_6KKfUiwolSn&t!dqsl(Wz2Z^Y<; z--(y{s*IcE?a107L}wGX9G6+YncsI^4rh|Lxsup9p=+D0P61t+rhaAG`$tQ(&2~0x zA3g1kpQL&t&0+14mu$x2F`ZkV^XmZn9y2TrCQm#cyDjPV{|O+^4JUoY0U)dIGHmy{ ztC~{__APlBi!a0pOirJ%40FH5v$%ktGGm6#OOyTK4?B}O?fCVK+~dQ#-Ht9gtI?)y zhLbP^V5KdBeRjNQpsjC-;N$vFF>&e9r5W5el*j#s{IUc*J1?WkJ5(3kN3cfC5L|XI>xvwUQ208dtoQ^l zmL$--1$c?={~xUDX+#87*#+OCy7>90rq8H=*u0#{QF@CS^EMkCUx!D@pf7)?HE(T@ z$bNr(1Ge$W;@2JNdya& z{!`5CV6?5dj=BHCWLaxv1~9>Wckn3U>(R^q{>HJ6pJ457`VGx5`ttdFrGLBibAm|L z^UlHA-eO~`GHm^!_{v#g2x^JgZwTuv5bVBex2na??BohYdOO6}GzyUVF25VarZq!O zNVxvCCvK+6e~@a%HiHj^ck-*unT6TFjlO-@J0 z&m&9zsbBA)12m8U8otJny9i{YCn#%pI*uG!8x+E}Hs%Q%k1GJ{i7te-E!><~ev?~T zE!F}8v!m6eQ=hK@fyKK|h*kDcf_P3@()o|C0@*%9f+Fl;Hg;#c!iBY+v} zOee1Y^IgWs7TcD-CYr1uzXNMcz-Q7AvmPK<6WWI@0bS&P+ zqUTtYHY>gi#;U&MLGT19HM;9*<}cvru(`&G6gb!l2?@Co-x2Hp+;K+1>fJVq)vvXO zTt-UGJfl8cg37B<9`{`XYvIk*tvA~_Ga(A}&hmS=>F9Fg+w3gwoG!XbSh7M0EIj+K z>bAfR!yqld=d0DjPIkXvZr^s0HxH?dN%wo_KE_1O%D^Wj`2m(Sti#aLxUn)t>|uU-=E7~E!(0itM!MLaEr18dl&igCXEKna)ZQZEAwKs|BRMrU zdACvQ`cFe^@=v3%zsYP4fv$-cP>`=ld&{NlI4Uc+nzU%RLJ~nfQf(xLh`C+x=B|cl zaO%9rMm|aDZ;OX;_KSDk1${pV5RJ7C(MwqlO@!uU|M<-=Wa2;&MDO?wQQ+&zfl9X! zvVmuXWIo%-${Cx^ZfD6$!1;#IGIrTQL0{a0s!{LR-wuojN^j!{WB!*5&=bE!8013c zyZmW~`=!IzWjpuLZ&1wLWgF$7qJ+eT5{9y&wf*$!4^WIH+2(Ei_g@{}*MU?=_g(PQmj9Xkjwc2Ebt2wVk^blgQ2eugZj7`9X= z*ZE1(dLrqx9r-^0f!C6#(^-2W7ENT8&Fw=!Y;;^9{(@ckqa&K6M8i+=m(xq z5@Dxbhhqs}iaXc~d@<#JGUj}Ks#CLO(Y-o0LBcDOA9C;o?J8YiSWrCxV|Bb9~V5CmM< z2QX?J2<@sk(AFq3oYx-C>?wm|s3Xeh@XRczK^^O;%DvN<(GYp{HNxJ@GQ_jY?(&g> zQ$|J}py_rSBK)P-S8Uj1E4m`#QnDr}rn&i_c;BEHU=^ z@&{FrS2cn5Uc@+M=(yh>3oTt>P`lMAPtha3ze2!-OX{^rWd*y40H&T>8x4^NV*nPKi@QJBmj&oWKi1Go7eU$s#HXX~&)dI4|^-V`YRu7<%t z&^F`(VASt1seu1b76+Aj9=uGMq$>t%@ZJ&)_{R7ux+>7#u&jD|s)=LInO{(^2}g;& z@>raC#c)1chN3p`M)(_rhI^{FaMSM|8J#YA>l@g00nt3IWX(oK!B9HOF;!Zs9ul*09GpShm$g8`mDN1Vx5 zHlVs{OUNu6Sq1o23ychWMdIlgq!V{;I(OfP9`@*P{L8jjyx}7+BieX_Z~O1hR;iw9 z=HlQEz3#0!;LPUltU@ENfV#wq7ghWT5@+T_oZ#2_hvOi9aTn~Jo}L~f?5u)_4+AcE zEV_{z^fuTjyddkHlwxuS6zTEd@QFn2V%!ABkdiE~7<{N~c3(PNAbAsu9CMk?LaP#C zn}n({HOIV<1s<9fDL<0o;!-?lgnx77T3lQd<$z>?F=Udz)SttefB!XsGz(K-V0#9X z)m_js&%Xey;;V@uH!TWGt<=}AUxg&z<{fIM-0jv4NAJW9oX-Z)06Yq{e0fst!EkC; zzvDKJVy_EHtDl^H8k+Iu-_s~f{1+?f>UF8yE6Qjy}-Ywev%uoU%;3b3f9H4mWEonps6{n~n^ z>4MUOWf?dzT3XL?4$Dy<@EvL>Zvf^&KPKE86@slJ%t`$ay#m6Qp2K@eFWICWS5gaf z&uq0plKbTAC%bbsNgLJpZ7%Tirp)VN>>|_k9R@Uvt*HQo3156lQ&M zP+t4Wqu&URnCV@}x5I-ltaM3`e>M<}!07ANnU#ZdPXQeiz_G9DrT=wTRg2+j!?r*D_v|1V!S7BTUe-LISa)Z-3G{$`#NHQ?u35 z%ib&)E&%w|6>Q&m+=Sjj;9F6X3adjd>#oQnemWoSA4|TV%5W#(q>XU$4M_BS&RX>R zWiyB37a3m1QMzL4+ok?+qtk)40^iPc;xu#eVU=G&Le)rY?wIYHxlJ0?ZF1gJJ(0XL zCkj=DLD8yf7mhyr$y+z@^RtjLyixVBQ~k|Z24I?inmNKb5Kn&To(ViWO*-&BF_9t< zkhjPT3|V~kmSFX&^Jb26fb!ko8Z!9P7!c9nkhHhN$D{Wr2#*(=xxlR%fZbnJ%Bt-q zHI;&CCbrsIji0@}$v_YE>bOb+P}P_DD{#M(<#imQD`pdVMS!_mC1d;X^0U1YW1eg1 z1dUD6d7LiG(C*<|x_O@;KSM$)6zkSU1VlkSS8)W;j3$C3(2H^3vPdG7YeR=$ic!l>TT~8G!A%B6!*s|(U$h4+LAWel;TS|!InArrwp!}P!A>8W_Fn z?8&cU`~HUIEX`1@*s?}%lU*0Lx#_c%htzdz0-Xudx^Ew&`=T<)^*#mXLajiy`zgm9;Jbr)I+vYOqDH>nmDCI{kZ`2bC zrN{=>HGj9p4!1t&R4ed6qn}L-RR_U{XIPAC#qP`=1&~U9?BOyIIWC;gJ9{r}{WX7o zK;1V*Wmu&-CVcRnZ18cjAjPc1X8gr{eSZv^nOfo6M&PSd!)AN~L%Kim<(i&c%Ebd# zX%aRh6&HacaJ6W7TJYSy{2FqV$({$dX*sr3ZsIp1tOX;!KRi5~5a-(!#r9%Kg)i8ewS7O@JT{-M4*LYsZm{Q z;%l#N&xrn%j@(Z+o#B^>rZ^8qW*xs=q5yNx*3yyZ?3&u|c~r8@Rj!j0#EEBkWiCl< z#0{Ws7ihBF0h5U9*^Nh4*VXk&MSeBV&fi^GSan>xj<4q-4sMnX=dbTKXshtYP^Afu zQonR~+ckN+t`FJa+0^GHlc1uK*Ve)FrIF`2xcLq6BA$-r7$hx*&IPp5jzm?H0D?mX zy?q8nl)iVwPQ=M4{-*)@diZ^es|NIS?4NT z+CR|(>jVM-n0E4+vS6;X#+?lhUwcssO<1QwY7c$Tu=LNHor5utlpfe-=L3lGAllT_ z4cbi2th;ty>qOGmec-y8=eJjb1RR5NUH)(>U7wF9*_KK~WO_w#@rZoXjdD&hM)O2X zyF!1Yo(U|wUQVdx(XhAO6k7SgLEe(72WrL{75JurAd^M}7rH{yeH93m2X*T&W2MGD z%QSr5NLPd2zYFel`6H~fy%bN9ccr?3Mvt$57i@M{nz8n!1qnAKrfDRVcNASb0k^6``yJ4z6|%EnrGJ zf7_p;PH4#LzYVMl!EKmOx4G!=PHdi#WHf%w04qSb^h0Omm^PTWBlbKc>q3w$jz>+!RuScw258%3*fmhM{AFr$mk>>Zih#%D{ z2P^dH+ltws7oAhiWws036=xbpRO1!Q^VFwM@o&{uYi$i~*t&Uxj#UmF-A-!}i2OG< zlRk;I?O(^_LNO`lyS&2z3i(ohA`749;F&O$BiyqX%YNohgqV>+7W;En?e2EYXO-9c zfRY*S692V1odd=Jtm(kei~Ew5@Av-6wKEURFeyR|~< z>%GZcX&Z5W1yPdC{#;=EJZ04%gppLXayRhH1In~?YhH4j$`Kh?cG&*YeP~)VmvjxI zAV?h3wU}ZSN>x3^U5=qX97O}YD8Mc4∨RqVZ{a{oK<<9H@y#bU~drm?-yi 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ГDYHpoZi*J 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�t2AhN{ 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 RtuH4L6I=M0mN(u_ircF&^jhf{F?zm}e{c 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 z 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