diff --git a/frontend/package.json b/frontend/package.json index b10313263..ac87fe727 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -126,30 +126,16 @@ ] }, "devDependencies": { + "@react-pdf/types": "^2.1.0", "@testing-library/dom": "^6.15.0", "@testing-library/jest-dom": "^4.2.4", "@testing-library/react": "^9.3.2", "@testing-library/user-event": "^7.1.2", - "eslint": "^6.8.0", - "eslint-config-airbnb": "^18.0.1", - "eslint-config-prettier": "^6.11.0", - "eslint-config-react-app": "^5.2.0", - "eslint-plugin-flowtype": "^3.0", - "eslint-plugin-fp": "^2.3.0", - "eslint-plugin-import": "^2.20.1", - "eslint-plugin-jsx-a11y": "^6.2.3", - "eslint-plugin-prettier": "^3.1.4", - "eslint-plugin-react": "^7.19.0", - "eslint-plugin-react-hooks": "^1.7", - "typescript": "^3.9.7", - "@react-pdf/types": "^2.1.0", "@turf/helpers": "^6.5.0", "@types/chart.js": "^2.9.21", - "@types/dompurify": "^2.2.3", - "@typescript-eslint/eslint-plugin": "^2.23.0", - "@typescript-eslint/parser": "^2.25.0", "@types/colormap": "^2.3.1", "@types/d3": "^5.7.2", + "@types/dompurify": "^2.2.3", "@types/geojson": "^7946.0.7", "@types/jest": "^24.0.0", "@types/lodash": "^4.14.149", @@ -157,14 +143,28 @@ "@types/marked": "^4.0.2", "@types/node": "^16.0.0", "@types/papaparse": "^5.0.3", - "@types/react": "^16.9.0", + "@types/react": "^16.13.0", "@types/react-datepicker": "^2.11.0", "@types/react-dom": "^16.9.0", "@types/react-pdf": "^5.7.2", "@types/react-redux": "^7.1.7", "@types/react-router-dom": "^5.1.3", + "@typescript-eslint/eslint-plugin": "^2.23.0", + "@typescript-eslint/parser": "^2.25.0", "cross-env": "^7.0.2", - "eslint-import-resolver-typescript": "^2.0.0" + "eslint": "^6.8.0", + "eslint-config-airbnb": "^18.0.1", + "eslint-config-prettier": "^6.11.0", + "eslint-config-react-app": "^5.2.0", + "eslint-import-resolver-typescript": "^2.0.0", + "eslint-plugin-flowtype": "^3.0", + "eslint-plugin-fp": "^2.3.0", + "eslint-plugin-import": "^2.20.1", + "eslint-plugin-jsx-a11y": "^6.2.3", + "eslint-plugin-prettier": "^3.1.4", + "eslint-plugin-react": "^7.19.0", + "eslint-plugin-react-hooks": "^1.7", + "typescript": "^3.9.7" }, "engines": { "node": "16.x" diff --git a/frontend/src/components/404Page/__snapshots__/index.test.tsx.snap b/frontend/src/components/404Page/__snapshots__/index.test.tsx.snap index 00d441465..135e6d308 100644 --- a/frontend/src/components/404Page/__snapshots__/index.test.tsx.snap +++ b/frontend/src/components/404Page/__snapshots__/index.test.tsx.snap @@ -35,13 +35,15 @@ exports[`renders as expected 1`] = `
- - Back To Home - + + Back To Home + +
{ - const { container } = render(); + const { container } = render( + + + , + ); expect(container).toMatchSnapshot(); }); diff --git a/frontend/src/components/404Page/index.tsx b/frontend/src/components/404Page/index.tsx index 484019e57..2af4859d7 100644 --- a/frontend/src/components/404Page/index.tsx +++ b/frontend/src/components/404Page/index.tsx @@ -32,9 +32,9 @@ function NotFound({ classes }: NotFoundProps) { - + + + diff --git a/frontend/src/components/MapView/LeftPanel/layersPanel/MenuSwitch/SwitchItem/LayerDownloadOptions.tsx b/frontend/src/components/MapView/LeftPanel/layersPanel/MenuSwitch/SwitchItem/LayerDownloadOptions.tsx index 4e4a8edb8..c33df1a3a 100644 --- a/frontend/src/components/MapView/LeftPanel/layersPanel/MenuSwitch/SwitchItem/LayerDownloadOptions.tsx +++ b/frontend/src/components/MapView/LeftPanel/layersPanel/MenuSwitch/SwitchItem/LayerDownloadOptions.tsx @@ -38,6 +38,7 @@ function LayerDownloadOptions({ layer, extent, selected, + size, }: LayerDownloadOptionsProps) { const { t } = useSafeTranslation(); const dispatch = useDispatch(); @@ -131,8 +132,9 @@ function LayerDownloadOptions({ - + )} @@ -172,6 +174,7 @@ interface LayerDownloadOptionsProps { layer: LayerType; extent: Extent | undefined; selected: boolean; + size?: 'small' | undefined; } export default LayerDownloadOptions; diff --git a/frontend/src/components/MapView/LeftPanel/layersPanel/MenuSwitch/SwitchItem/index.tsx b/frontend/src/components/MapView/LeftPanel/layersPanel/MenuSwitch/SwitchItem/index.tsx index d9c911f7e..bfe2ea9d2 100644 --- a/frontend/src/components/MapView/LeftPanel/layersPanel/MenuSwitch/SwitchItem/index.tsx +++ b/frontend/src/components/MapView/LeftPanel/layersPanel/MenuSwitch/SwitchItem/index.tsx @@ -22,26 +22,18 @@ import React, { } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { LayerKey, LayerType } from 'config/types'; -import { - getDisplayBoundaryLayers, - LayerDefinitions, - ReportsDefinitions, -} from 'config/utils'; +import { LayerDefinitions, ReportsDefinitions } from 'config/utils'; import { clearDataset } from 'context/datasetStateSlice'; -import { removeLayer } from 'context/mapStateSlice'; import { layersSelector, mapSelector } from 'context/mapStateSlice/selectors'; import { useSafeTranslation } from 'i18n'; -import { - refreshBoundaries, - safeDispatchAddLayer, - safeDispatchRemoveLayer, -} from 'utils/map-utils'; +import { refreshBoundaries } from 'utils/map-utils'; import { getUrlKey, useUrlHistory } from 'utils/url-utils'; import { handleChangeOpacity } from 'components/MapView/Legends/handleChangeOpacity'; import { Extent } from 'components/MapView/Layers/raster-utils'; import { availableDatesSelector } from 'context/serverStateSlice'; import { checkLayerAvailableDatesAndContinueOrRemove } from 'components/MapView/utils'; import { LocalError } from 'utils/error-utils'; +import { toggleRemoveLayer } from './utils'; import LayerDownloadOptions from './LayerDownloadOptions'; import ExposureAnalysisOption from './ExposureAnalysisOption'; @@ -131,32 +123,13 @@ const SwitchItem = memo(({ classes, layer, extent }: SwitchItemProps) => { const urlLayerKey = getUrlKey(selectedLayer); if (!checked) { - removeLayerFromUrl(urlLayerKey, selectedLayer.id); - dispatch(removeLayer(selectedLayer)); - - // For admin boundary layers with boundary property - // we have to de-activate the unique boundary and re-activate - // default boundaries - if (!('boundary' in selectedLayer)) { - return; - } - const boundaryId = selectedLayer.boundary || ''; - - if (!Object.keys(LayerDefinitions).includes(boundaryId)) { - return; - } - const displayBoundaryLayers = getDisplayBoundaryLayers(); - const uniqueBoundaryLayer = LayerDefinitions[boundaryId as LayerKey]; - - if ( - !displayBoundaryLayers.map(l => l.id).includes(uniqueBoundaryLayer.id) - ) { - safeDispatchRemoveLayer(map, uniqueBoundaryLayer, dispatch); - } - - displayBoundaryLayers.forEach(l => { - safeDispatchAddLayer(map, l, dispatch); - }); + toggleRemoveLayer( + selectedLayer, + map, + urlLayerKey, + dispatch, + removeLayerFromUrl, + ); return; } try { diff --git a/frontend/src/components/MapView/LeftPanel/layersPanel/MenuSwitch/SwitchItem/utils.ts b/frontend/src/components/MapView/LeftPanel/layersPanel/MenuSwitch/SwitchItem/utils.ts new file mode 100644 index 000000000..11a485088 --- /dev/null +++ b/frontend/src/components/MapView/LeftPanel/layersPanel/MenuSwitch/SwitchItem/utils.ts @@ -0,0 +1,44 @@ +import { Map as MapBoxMap } from 'mapbox-gl'; +import { UrlLayerKey } from '../../../../../../utils/url-utils'; +import { LayerKey, LayerType } from '../../../../../../config/types'; +import { removeLayer } from '../../../../../../context/mapStateSlice'; +import { + getDisplayBoundaryLayers, + LayerDefinitions, +} from '../../../../../../config/utils'; +import { + safeDispatchAddLayer, + safeDispatchRemoveLayer, +} from '../../../../../../utils/map-utils'; + +export function toggleRemoveLayer( + layer: LayerType, + _map: MapBoxMap | undefined, + urlLayerKey: UrlLayerKey, + dispatcher: Function, + removeLayerFromUrl: Function, +) { + removeLayerFromUrl(urlLayerKey, layer.id); + dispatcher(removeLayer(layer)); + + // For admin boundary layers with boundary property + // we have to de-activate the unique boundary and re-activate + // default boundaries + if (!('boundary' in layer)) { + return; + } + const boundaryId = layer.boundary || ''; + if (!Object.keys(LayerDefinitions).includes(boundaryId)) { + return; + } + const displayBoundaryLayers = getDisplayBoundaryLayers(); + const uniqueBoundaryLayer = LayerDefinitions[boundaryId as LayerKey]; + + if (!displayBoundaryLayers.map(l => l.id).includes(uniqueBoundaryLayer.id)) { + safeDispatchRemoveLayer(_map, uniqueBoundaryLayer, dispatcher); + } + + displayBoundaryLayers.forEach(l => { + safeDispatchAddLayer(_map, l, dispatcher); + }); +} diff --git a/frontend/src/components/MapView/Legends/AnalysisDownloadButton.tsx b/frontend/src/components/MapView/Legends/AnalysisDownloadButton.tsx index 90b3221f3..4fb0605d5 100644 --- a/frontend/src/components/MapView/Legends/AnalysisDownloadButton.tsx +++ b/frontend/src/components/MapView/Legends/AnalysisDownloadButton.tsx @@ -1,4 +1,5 @@ -import React, { useCallback, useMemo } from 'react'; +import { IconButton, Menu, MenuItem, Tooltip } from '@material-ui/core'; +import React, { useCallback, useMemo, useState } from 'react'; import { useSelector } from 'react-redux'; import { analysisResultSelector, @@ -18,7 +19,6 @@ import { PolygonAnalysisResult, useAnalysisTableColumns, } from 'utils/analysis-utils'; -import MultiOptionsButton from 'components/Common/MultiOptionsButton'; import { downloadToFile, getExposureAnalysisColumnsToRender, @@ -27,6 +27,7 @@ import { } from 'components/MapView/utils'; import { snakeCase } from 'lodash'; import { getExposureAnalysisCsvData } from 'utils/csv-utils'; +import GetAppIcon from '@material-ui/icons/GetApp'; function AnalysisDownloadButton() { const analysisResult = useSelector(analysisResultSelector); @@ -42,6 +43,19 @@ function AnalysisDownloadButton() { ); const analysisDefinition = useSelector(getCurrentDefinition); + const [ + downloadMenuAnchorEl, + setDownloadMenuAnchorEl, + ] = useState(null); + + const handleDownloadMenuOpen = (event: React.MouseEvent) => { + setDownloadMenuAnchorEl(event.currentTarget); + }; + + const handleDownloadMenuClose = () => { + setDownloadMenuAnchorEl(null); + }; + const exposureAnalysisTableData = getExposureAnalysisTableData( (analysisResult?.tableData || []) as TableRow[], exposureAnalysisResultSortByKey, @@ -91,9 +105,11 @@ function AnalysisDownloadButton() { fileName ?? 'prism_extract', 'application/json', ); + handleDownloadMenuClose(); }, [featureCollection, fileName]); const handleAnalysisDownloadCsv = useCallback((): void => { + handleDownloadMenuClose(); if (!analysisResult) { return; } @@ -132,19 +148,30 @@ function AnalysisDownloadButton() { ]); return ( - + <> + + + + + + + + {t('Download as CSV')} + + + {t('Download as GeoJSON')} + + + ); } diff --git a/frontend/src/components/MapView/Legends/LegendItem/__snapshots__/index.test.tsx.snap b/frontend/src/components/MapView/Legends/LegendItem/__snapshots__/index.test.tsx.snap index b67fda684..1b3e8b19c 100644 --- a/frontend/src/components/MapView/Legends/LegendItem/__snapshots__/index.test.tsx.snap +++ b/frontend/src/components/MapView/Legends/LegendItem/__snapshots__/index.test.tsx.snap @@ -30,14 +30,14 @@ exports[`renders as expected 1`] = ` />
+ +
+ + + + +
+ + 50% + + + + + + + +
+
+ + + +
diff --git a/frontend/src/components/MapView/Legends/LegendItem/index.test.tsx b/frontend/src/components/MapView/Legends/LegendItem/index.test.tsx index 301800044..338e211c6 100644 --- a/frontend/src/components/MapView/Legends/LegendItem/index.test.tsx +++ b/frontend/src/components/MapView/Legends/LegendItem/index.test.tsx @@ -3,25 +3,28 @@ import { render } from '@testing-library/react'; import { Provider } from 'react-redux'; import { store } from 'context/store'; +import { BrowserRouter } from 'react-router-dom'; import LegendItem from '.'; test('renders as expected', () => { const { container } = render( - - -
Test Children
-
-
, + + + +
Test Children
+
+
+
, ); expect(container).toMatchSnapshot(); }); diff --git a/frontend/src/components/MapView/Legends/LegendItem/index.tsx b/frontend/src/components/MapView/Legends/LegendItem/index.tsx index 0ae9f2594..b7d657d20 100644 --- a/frontend/src/components/MapView/Legends/LegendItem/index.tsx +++ b/frontend/src/components/MapView/Legends/LegendItem/index.tsx @@ -11,23 +11,36 @@ import { createStyles, Divider, Grid, + IconButton, ListItem, Paper, + Popover, Slider, + Tooltip, Typography, withStyles, WithStyles, } from '@material-ui/core'; +import { Close, Opacity } from '@material-ui/icons'; import { useDispatch, useSelector } from 'react-redux'; import { LayerType, LegendDefinitionItem } from 'config/types'; -import { mapSelector } from 'context/mapStateSlice/selectors'; +import { mapSelector, layersSelector } from 'context/mapStateSlice/selectors'; +import { clearDataset } from 'context/datasetStateSlice'; import { useSafeTranslation } from 'i18n'; -import { setAnalysisLayerOpacity } from 'context/analysisResultStateSlice'; +import { + clearAnalysisResult, + setAnalysisLayerOpacity, +} from 'context/analysisResultStateSlice'; import LayerContentPreview from 'components/MapView/Legends/layerContentPreview'; import { handleChangeOpacity } from 'components/MapView/Legends/handleChangeOpacity'; import ColorIndicator from 'components/MapView/Legends/ColorIndicator'; import { getLegendItemLabel } from 'components/MapView/utils'; -import LoadingBar from 'components/MapView/Legends/LoadingBar'; +import { Extent } from 'components/MapView/Layers/raster-utils'; +import { getUrlKey, useUrlHistory } from 'utils/url-utils'; +import LayerDownloadOptions from 'components/MapView/LeftPanel/layersPanel/MenuSwitch/SwitchItem/LayerDownloadOptions'; +import AnalysisDownloadButton from 'components/MapView/Legends//AnalysisDownloadButton'; +import { toggleRemoveLayer } from 'components/MapView/LeftPanel/layersPanel/MenuSwitch/SwitchItem/utils'; +import LoadingBar from '../LoadingBar'; // Children here is legendText const LegendItem = memo( @@ -40,11 +53,14 @@ const LegendItem = memo( opacity: initialOpacity, children, legendUrl, - displayOpacitySlider, + isAnalysis, fillPattern, + extent, }: LegendItemProps) => { const dispatch = useDispatch(); + const { removeLayerFromUrl } = useUrlHistory(); const map = useSelector(mapSelector); + const [opacityEl, setOpacityEl] = useState(null); const [opacity, setOpacityValue] = useState( initialOpacity || 0, ); @@ -55,50 +71,94 @@ const LegendItem = memo( const { t } = useSafeTranslation(); + const openOpacity = (event: React.MouseEvent) => { + setOpacityEl(event.currentTarget); + }; + + const closeOpacity = () => { + setOpacityEl(null); + }; + + const open = Boolean(opacityEl); + const opacityId = open ? 'opacity-popover' : undefined; + const handleChangeOpacityValue = useCallback( val => { setOpacityValue(val); - dispatch(setAnalysisLayerOpacity(val)); + if (isAnalysis) { + dispatch(setAnalysisLayerOpacity(val)); + } }, - [dispatch], + [dispatch, isAnalysis], ); + const selectedLayers = useSelector(layersSelector); + const layer = useMemo(() => { + return selectedLayers.find(l => l.id === id); + }, [id, selectedLayers]); + const renderedOpacitySlider = useMemo(() => { - if (!displayOpacitySlider) { - return null; - } return ( - - - - handleChangeOpacity( - e, - newValue as number, - map, - id, - type, - handleChangeOpacityValue, - ) - } - /> - - + + + {`${Math.round((opacity as number) * 100)}%`} + + + handleChangeOpacity( + e, + newValue as number, + map, + id, + type, + handleChangeOpacityValue, + ) + } + /> + ); - }, [ - classes.slider, - displayOpacitySlider, - handleChangeOpacityValue, - id, - map, - opacity, - type, - ]); + }, [classes, handleChangeOpacityValue, id, map, opacity, type]); + + const layerDownloadOptions = useMemo(() => { + return layer ? ( + + ) : null; + }, [layer, extent]); + + const remove = useCallback(() => { + if (isAnalysis) { + dispatch(clearAnalysisResult()); + } + if (layer) { + // reset opacity value + setOpacityValue(initialOpacity || 0); + // clear previous table dataset loaded first + // to close the dataseries and thus close chart + dispatch(clearDataset()); + const urlLayerKey = getUrlKey(layer); + toggleRemoveLayer( + layer, + map, + urlLayerKey, + dispatch, + removeLayerFromUrl, + ); + } + }, [layer, map, dispatch, removeLayerFromUrl, initialOpacity, isAnalysis]); const getColorIndicatorKey = useCallback((item: LegendDefinitionItem) => { return ( @@ -154,10 +214,37 @@ const LegendItem = memo( - {renderedOpacitySlider} {renderedLegend} {renderedChildren} + + + + + + + + <> + + {renderedOpacitySlider} + + {isAnalysis ? : layerDownloadOptions} + + + + + + + ); @@ -173,6 +260,25 @@ const styles = () => slider: { padding: '0 5px', }, + opacityBox: { + backgroundColor: '#fff', + width: 172, + overflow: 'hidden', + }, + opacitySliderRoot: { + color: '#4CA1AD', + flexGrow: 1, + padding: '18px 0', + }, + opacitySliderThumb: { + backgroundColor: '#4CA1AD', + }, + opacityText: { + color: '#4CA1AD', + marginRight: 5, + width: 28, + lineHeight: '36px', + }, }); interface LegendItemProps @@ -184,8 +290,9 @@ interface LegendItemProps legendUrl?: string; type?: LayerType['type']; opacity: LayerType['opacity']; - displayOpacitySlider?: boolean; + isAnalysis?: boolean; fillPattern?: 'left' | 'right'; + extent?: Extent; } export default withStyles(styles)(LegendItem); diff --git a/frontend/src/components/MapView/Legends/index.tsx b/frontend/src/components/MapView/Legends/index.tsx index 21742745a..b01149ede 100644 --- a/frontend/src/components/MapView/Legends/index.tsx +++ b/frontend/src/components/MapView/Legends/index.tsx @@ -1,7 +1,6 @@ import { Button, createStyles, - Divider, Grid, Hidden, List, @@ -22,12 +21,12 @@ import { import { LayerType } from 'config/types'; import { BaselineLayerResult } from 'utils/analysis-utils'; import { useSafeTranslation } from 'i18n'; +import { Extent } from 'components/MapView/Layers/raster-utils'; -import AnalysisDownloadButton from './AnalysisDownloadButton'; import LegendItem from './LegendItem'; import LegendImpactResult from './LegendImpactResult'; -const Legends = memo(({ classes, layers }: LegendsProps) => { +const Legends = memo(({ classes, extent, layers }: LegendsProps) => { // Selectors const isAnalysisLayerActive = useSelector(isAnalysisLayerActiveSelector); const analysisResult = useSelector(analysisResultSelector); @@ -75,12 +74,13 @@ const Legends = memo(({ classes, layers }: LegendsProps) => { type={layer.type} opacity={layer.opacity} fillPattern={layer.fillPattern} + extent={extent} > {t(layer.legendText)} ); }); - }, [getLayerLegendUrl, layers, t]); + }, [getLayerLegendUrl, layers, t, extent]); const renderedLegendImpactResult = useMemo(() => { if (!(analysisResult instanceof BaselineLayerResult)) { @@ -114,13 +114,9 @@ const Legends = memo(({ classes, layers }: LegendsProps) => { opacity={analysisLayerOpacity} // TODO: initial opacity value // Control opacity only for analysis // for the other layers it is controlled from the left panel - displayOpacitySlider={isAnalysisLayerActive && hasData} + isAnalysis={isAnalysisLayerActive && hasData} > {renderedLegendImpactResult} - - - - , ]; }, [ @@ -195,6 +191,7 @@ const styles = () => }); export interface LegendsProps extends WithStyles { + extent?: Extent; layers: LayerType[]; } diff --git a/frontend/src/components/MapView/index.tsx b/frontend/src/components/MapView/index.tsx index ecee060d5..bacff07f1 100644 --- a/frontend/src/components/MapView/index.tsx +++ b/frontend/src/components/MapView/index.tsx @@ -545,12 +545,13 @@ const MapView = memo(({ classes }: MapViewProps) => { - + ); }, [ + adminBoundariesExtent, classes.buttonContainer, isShowingExtraFeatures, renderedGridItemAlertForm, diff --git a/frontend/src/components/NavBar/__snapshots__/index.test.tsx.snap b/frontend/src/components/NavBar/__snapshots__/index.test.tsx.snap index 1f47a5e33..561eee67b 100644 --- a/frontend/src/components/NavBar/__snapshots__/index.test.tsx.snap +++ b/frontend/src/components/NavBar/__snapshots__/index.test.tsx.snap @@ -18,14 +18,16 @@ exports[`renders as expected 1`] = `
- - PRISM - + + PRISM + +
'mock-PrintImage'); test('renders as expected', () => { const { container } = render( - - - , + + + + + , ); expect(container).toMatchSnapshot(); }); diff --git a/frontend/src/components/NavBar/index.tsx b/frontend/src/components/NavBar/index.tsx index 49db6aad1..a27ca09fe 100644 --- a/frontend/src/components/NavBar/index.tsx +++ b/frontend/src/components/NavBar/index.tsx @@ -63,14 +63,11 @@ function NavBar({ classes }: NavBarProps) { {logo && logo} {title && ( - - {t(title)} - + + + {t(title)} + + )} {subtitle && ( diff --git a/frontend/src/types/custom.d.ts b/frontend/src/types/custom.d.ts index 4ce95f992..3b66a4fdb 100644 --- a/frontend/src/types/custom.d.ts +++ b/frontend/src/types/custom.d.ts @@ -4,6 +4,7 @@ // https://stackoverflow.com/questions/44717164/unable-to-import-svg-files-in-typescript declare module '*.svg' { import React = require('react'); + export const ReactComponent: React.FC>; const content: string; export default content; diff --git a/frontend/yarn.lock b/frontend/yarn.lock index 2b41ee19c..ba48e8905 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -2690,7 +2690,7 @@ dependencies: "@types/react" "*" -"@types/react@*", "@types/react@^16.9.0": +"@types/react@*": version "16.9.23" resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.23.tgz#1a66c6d468ba11a8943ad958a8cb3e737568271c" integrity sha512-SsGVT4E7L2wLN3tPYLiF20hmZTPGuzaayVunfgXzUn1x4uHVsKH6QDJQ/TdpHqwsTLd4CwrmQ2vOgxN7gE24gw== @@ -2698,6 +2698,20 @@ "@types/prop-types" "*" csstype "^2.2.0" +"@types/react@^16.13.0": + version "16.14.50" + resolved "https://registry.yarnpkg.com/@types/react/-/react-16.14.50.tgz#ec9c30f2f0c7d9aa748949536d88e3439526a25d" + integrity sha512-7TWZ/HjhXsRK3BbhSFxTinbSft3sUXJAU3ONngT0rpcKJaIOlxkRke4bidqQTopUbEv1ApC5nlSEkIpX43MkTg== + dependencies: + "@types/prop-types" "*" + "@types/scheduler" "*" + csstype "^3.0.2" + +"@types/scheduler@*": + version "0.16.5" + resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.5.tgz#4751153abbf8d6199babb345a52e1eb4167d64af" + integrity sha512-s/FPdYRmZR8SjLWGMCuax7r3qCWQw9QKHzXVukAuuIJkXkDRwp+Pu5LMIVFi0Fxbav35WURicYr8u1QsoybnQw== + "@types/stack-utils@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e" @@ -9313,13 +9327,6 @@ lru-cache@^5.1.1: dependencies: yallist "^3.0.2" -lru-cache@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" - integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== - dependencies: - yallist "^4.0.0" - make-cancellable-promise@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/make-cancellable-promise/-/make-cancellable-promise-1.1.0.tgz#b4e9fcb31db3a27417e44f80cffa598ec9ac9f4e" @@ -11813,9 +11820,9 @@ react-is@^16.8.4: integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== react-mapbox-gl@^4.8.2: - version "4.8.6" - resolved "https://registry.yarnpkg.com/react-mapbox-gl/-/react-mapbox-gl-4.8.6.tgz#c3841bac882a297f60efce50cac4060e3a1c3f81" - integrity sha512-e6rJ4GFye2AIu10I0a0OfleIWYkigIMIysoSKCA4Wg5YHa52JRHq2F3x0c0cnhqfz1txnUhXUbkx2qqs8B6kKQ== + version "4.8.2" + resolved "https://registry.yarnpkg.com/react-mapbox-gl/-/react-mapbox-gl-4.8.2.tgz#3814a42d35adc53194d3920eeac72910dbcebd65" + integrity sha512-NAN1dgVDpjxTtqQuhPX1OUkVhS1o8KJ+jRoAN0Q/8gSWLaQlYLkC1ZOYRRj8KcoRP3Px/ya0DJsORiStz0P+eA== dependencies: "@turf/bbox" "4.7.3" "@turf/helpers" "4.7.3" @@ -12668,11 +12675,11 @@ semver-regex@^2.0.0: integrity sha512-mUdIBBvdn0PLOeP3TEkMH7HHeUP3GjsXCwKarjv/kGmUFOYg1VqEemKhoQpWMu6X2I8kHeuVdGibLGkVK+/5Qw== "semver@2 || 3 || 4 || 5", semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0, semver@^5.7.0, semver@^5.7.1: - version "5.7.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" - integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== + version "5.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== -semver@6.3.0: +semver@6.3.0, semver@^6.0.0, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== @@ -12682,17 +12689,10 @@ semver@7.0.0: resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== -semver@^6.0.0, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0: - version "6.3.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" - integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== - semver@^7.3.2: - version "7.5.4" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" - integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== - dependencies: - lru-cache "^6.0.0" + version "7.3.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938" + integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ== send@0.18.0: version "0.18.0" @@ -14472,9 +14472,9 @@ which@^2.0.1: isexe "^2.0.0" word-wrap@~1.2.3: - version "1.2.4" - resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.4.tgz#cb4b50ec9aca570abd1f52f33cd45b6c61739a9f" - integrity sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA== + version "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== workbox-background-sync@^4.3.1: version "4.3.1"