diff --git a/geonode_mapstore_client/client/js/actions/gnresource.js b/geonode_mapstore_client/client/js/actions/gnresource.js index 2d86d374c2..3b9a73c3aa 100644 --- a/geonode_mapstore_client/client/js/actions/gnresource.js +++ b/geonode_mapstore_client/client/js/actions/gnresource.js @@ -30,6 +30,7 @@ export const UPDATE_RESOURCE_COMPACT_PERMISSIONS = 'GEONODE:UPDATE_RESOURCE_COMP export const RESET_GEO_LIMITS = 'GEONODE:RESET_GEO_LIMITS'; export const PROCESS_RESOURCES = 'GEONODE:PROCESS_RESOURCES'; export const SET_RESOURCE_THUMBNAIL = 'GEONODE_SET_RESOURCE_THUMBNAIL'; +export const ENABLE_MAP_THUMBNAIL_VIEWER = 'GEONODE_ENABLE_MAP_THUMBNAIL_VIEWER'; /** * Actions for GeoNode resource @@ -194,6 +195,16 @@ export function setFavoriteResource(favorite) { }; } +/** +* Enable or disable map thumbnail viewer +*/ + +export function enableMapThumbnailViewer(enabled) { + return { + type: ENABLE_MAP_THUMBNAIL_VIEWER, + enabled + }; +} /** * Set map like thumbnail to map or layer (trigger epic gnSaveDirectContent) diff --git a/geonode_mapstore_client/client/js/components/DetailsPanel/DetailsPanel.jsx b/geonode_mapstore_client/client/js/components/DetailsPanel/DetailsPanel.jsx index a0e6d1a06f..a41adacddb 100644 --- a/geonode_mapstore_client/client/js/components/DetailsPanel/DetailsPanel.jsx +++ b/geonode_mapstore_client/client/js/components/DetailsPanel/DetailsPanel.jsx @@ -27,7 +27,8 @@ import mapTypeHOC from '@mapstore/framework/components/map/enhancers/mapType'; import AuthorInfo from '@js/components/AuthorInfo/AuthorInfo'; import Loader from '@mapstore/framework/components/misc/Loader'; import { getUserName } from '@js/utils/SearchUtils'; -import FitBounds from '@mapstore/framework/components/geostory/common/map/FitBounds'; +import ZoomTo from '@js/components/ZoomTo'; +import { boundsToExtentString } from '@js/utils/CoordinatesUtils'; const Map = mapTypeHOC(BaseMap); Map.displayName = 'Map'; @@ -124,16 +125,13 @@ const DefinitionListContainer = ({itemslist}) => { const MapThumbnailView = ({ initialBbox, layers, onMapThumbnail, onClose, savingThumbnailMap } ) => { const [currentBbox, setCurrentBbox] = useState(); + const { bounds, crs } = initialBbox; + const extent = boundsToExtentString(bounds, crs); function handleOnMapViewChanges(center, zoom, bbox) { setCurrentBbox(bbox); } - const { bounds, crs } = initialBbox; - const { minx, miny, maxx, maxy } = bounds; - const extent = [minx, miny, maxx, maxy]; - const projection = crs; - return (
- + {savingThumbnailMap &&
}
-
-
+
+
); @@ -208,7 +200,9 @@ function DetailsPanel({ isThumbnailChanged, onResourceThumbnail, resourceThumbnailUpdating, - initialBbox + initialBbox, + enableMapViewer, + onClose }) { const detailsContainerNode = useRef(); const isMounted = useRef(); @@ -255,16 +249,6 @@ function DetailsPanel({ const documentDownloadUrl = (resource?.href && resource?.href.includes('download')) ? resource?.href : undefined; const metadataDetailUrl = resource?.pk && getMetadataDetailUrl(resource); - const [enableMapViewer, setEnableMapViewer] = useState(false); - - const handleEnableMapViewer = () => { - setEnableMapViewer(false); - }; - - const handleMapViewer = () => { - setEnableMapViewer(!enableMapViewer); - }; - const validateDataType = (data) => { let dataType; @@ -504,7 +488,7 @@ function DetailsPanel({ (resource.resource_type === ResourceTypes.MAP || resource.resource_type === ResourceTypes.DATASET) && ( <> onClose(!enableMapViewer)} className="map-thumbnail" tooltip={} tooltipPosition={"top"} @@ -520,7 +504,7 @@ function DetailsPanel({ : @@ -532,16 +516,9 @@ function DetailsPanel({
-
-
- + - -
-
- -
-
+ {
@@ -586,6 +563,7 @@ function DetailsPanel({
+ {

{resource?.owner &&

{resource?.owner.avatar && {getUserName(resource?.owner)} diff --git a/geonode_mapstore_client/client/js/components/FiltersForm/FilterByExtent.jsx b/geonode_mapstore_client/client/js/components/FiltersForm/FilterByExtent.jsx index 6b39a7f3fa..c946b0e00e 100644 --- a/geonode_mapstore_client/client/js/components/FiltersForm/FilterByExtent.jsx +++ b/geonode_mapstore_client/client/js/components/FiltersForm/FilterByExtent.jsx @@ -7,56 +7,20 @@ * LICENSE file in the root directory of this source tree. */ -import React, { useState, useRef, useEffect } from 'react'; +import React, { useState, useRef } from 'react'; import { FormGroup, Checkbox } from 'react-bootstrap'; import BaseMap from '@mapstore/framework/components/map/BaseMap'; import mapType from '@mapstore/framework/components/map/enhancers/mapType'; import Message from '@mapstore/framework/components/I18N/Message'; -import { reprojectBbox } from '@mapstore/framework/utils/CoordinatesUtils'; import { boundsToExtentString, getFeatureFromExtent } from '@js/utils/CoordinatesUtils'; +import ZoomTo from '@js/components/ZoomTo'; const Map = mapType(BaseMap); Map.displayName = 'Map'; -function ZoomTo({ - map, - extent -}) { - const once = useRef(); - useEffect(() => { - if (map && extent && !once.current) { - const [ - aMinx, aMiny, aMaxx, aMaxy, - bMinx, bMiny, bMaxx, bMaxy - ] = extent.split(','); - const projection = map.getView().getProjection().getCode(); - let bounds; - const aBounds = reprojectBbox([aMinx, aMiny, aMaxx, aMaxy], 'EPSG:4326', projection); - if (bMinx !== undefined && bMiny !== undefined && bMaxx !== undefined && bMaxy !== undefined) { - const bBounds = reprojectBbox([bMinx, bMiny, bMaxx, bMaxy], 'EPSG:4326', projection); - // if there is the second bbox we should shift the minimum x value to correctly center the view - // the x of the [A] bounds needs to be shifted by the width of the [B] bounds - const minx = aBounds[0] - (bBounds[2] - bBounds[0]); - bounds = [minx, aBounds[1], aBounds[2], aBounds[3]]; - } else { - bounds = aBounds; - } - map.getView().fit(bounds, { - size: map.getSize(), - duration: 300, - nearest: true - }); - // ensure to avoid other fit action by setting once to true - once.current = true; - } - }, [ extent ]); - - return null; -} - function FilterByExtent({ id, extent, diff --git a/geonode_mapstore_client/client/js/components/ZoomTo/ZoomTo.jsx b/geonode_mapstore_client/client/js/components/ZoomTo/ZoomTo.jsx new file mode 100644 index 0000000000..7d90e85004 --- /dev/null +++ b/geonode_mapstore_client/client/js/components/ZoomTo/ZoomTo.jsx @@ -0,0 +1,48 @@ +/* + * Copyright 2022, GeoSolutions Sas. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. + */ + +import { useRef, useEffect } from 'react'; +import { reprojectBbox } from '@mapstore/framework/utils/CoordinatesUtils'; + +const ZoomTo = ({ + map, + extent +}) => { + const once = useRef(); + useEffect(() => { + if (map && extent && !once.current) { + const [ + aMinx, aMiny, aMaxx, aMaxy, + bMinx, bMiny, bMaxx, bMaxy + ] = extent.split(','); + const projection = map.getView().getProjection().getCode(); + let bounds; + const aBounds = reprojectBbox([aMinx, aMiny, aMaxx, aMaxy], 'EPSG:4326', projection); + if (bMinx !== undefined && bMiny !== undefined && bMaxx !== undefined && bMaxy !== undefined) { + const bBounds = reprojectBbox([bMinx, bMiny, bMaxx, bMaxy], 'EPSG:4326', projection); + // if there is the second bbox we should shift the minimum x value to correctly center the view + // the x of the [A] bounds needs to be shifted by the width of the [B] bounds + const minx = aBounds[0] - (bBounds[2] - bBounds[0]); + bounds = [minx, aBounds[1], aBounds[2], aBounds[3]]; + } else { + bounds = aBounds; + } + map.getView().fit(bounds, { + size: map.getSize(), + duration: 300, + nearest: true + }); + // ensure to avoid other fit action by setting once to true + once.current = true; + } + }, [extent]); + + return null; +}; + +export default ZoomTo; diff --git a/geonode_mapstore_client/client/js/components/ZoomTo/index.js b/geonode_mapstore_client/client/js/components/ZoomTo/index.js new file mode 100644 index 0000000000..a8016ed328 --- /dev/null +++ b/geonode_mapstore_client/client/js/components/ZoomTo/index.js @@ -0,0 +1,3 @@ +import ZoomTo from "./ZoomTo"; + +export default ZoomTo; diff --git a/geonode_mapstore_client/client/js/epics/gnsave.js b/geonode_mapstore_client/client/js/epics/gnsave.js index 389279bb38..628a181514 100644 --- a/geonode_mapstore_client/client/js/epics/gnsave.js +++ b/geonode_mapstore_client/client/js/epics/gnsave.js @@ -30,7 +30,8 @@ import { resetGeoLimits, setResourceCompactPermissions, updateResourceProperties, - loadingResourceConfig + loadingResourceConfig, + enableMapThumbnailViewer } from '@js/actions/gnresource'; import { getResourceByPk, @@ -184,10 +185,12 @@ export const gnSetMapThumbnail = (action$, store) => Object.values(action.bbox.bounds)[1] ] }; + return Observable.defer(() => setMapThumbnail(resourceIDThumbnail, body, contentType)) .switchMap((res) => { return Observable.of( updateResourceProperties({ ...currentResource, thumbnail_url: `${res.thumbnail_url}?${Math.random()}` }), + enableMapThumbnailViewer(false), clearSave(), ...([successNotification({ title: "gnviewer.thumbnailsaved", message: "gnviewer.thumbnailsaved" })]) diff --git a/geonode_mapstore_client/client/js/plugins/DetailViewer.jsx b/geonode_mapstore_client/client/js/plugins/DetailViewer.jsx index 62360c76b6..5c5618f796 100644 --- a/geonode_mapstore_client/client/js/plugins/DetailViewer.jsx +++ b/geonode_mapstore_client/client/js/plugins/DetailViewer.jsx @@ -18,7 +18,8 @@ import { editThumbnailResource, setFavoriteResource, setMapThumbnail, - setResourceThumbnail + setResourceThumbnail, + enableMapThumbnailViewer } from '@js/actions/gnresource'; import FaIcon from '@js/components/FaIcon/FaIcon'; import controls from '@mapstore/framework/reducers/controls'; @@ -50,8 +51,9 @@ const ConnectedDetailsPanel = connect( layersSelector, isThumbnailChanged, updatingThumbnailResource, - mapSelector - ], (resource, loading, favorite, savingThumbnailMap, layers, thumbnailChanged, resourceThumbnailUpdating, mapData) => ({ + mapSelector, + state => state?.gnresource?.showMapThumbnail || false + ], (resource, loading, favorite, savingThumbnailMap, layers, thumbnailChanged, resourceThumbnailUpdating, mapData, showMapThumbnail) => ({ layers: layers, resource, loading, @@ -59,13 +61,15 @@ const ConnectedDetailsPanel = connect( favorite, isThumbnailChanged: thumbnailChanged, resourceThumbnailUpdating, - initialBbox: mapData?.bbox + initialBbox: mapData?.bbox, + enableMapViewer: showMapThumbnail })), { closePanel: setControlProperty.bind(null, 'rightOverlay', 'enabled', false), onFavorite: setFavoriteResource, onMapThumbnail: setMapThumbnail, - onResourceThumbnail: setResourceThumbnail + onResourceThumbnail: setResourceThumbnail, + onClose: enableMapThumbnailViewer } )(DetailsPanel); diff --git a/geonode_mapstore_client/client/js/reducers/__tests__/gnresource-test.js b/geonode_mapstore_client/client/js/reducers/__tests__/gnresource-test.js index 2e1a15e0bf..808103f18f 100644 --- a/geonode_mapstore_client/client/js/reducers/__tests__/gnresource-test.js +++ b/geonode_mapstore_client/client/js/reducers/__tests__/gnresource-test.js @@ -18,7 +18,8 @@ import { setResourceId, setResourcePermissions, editThumbnailResource, - setResourceThumbnail + setResourceThumbnail, + enableMapThumbnailViewer } from '@js/actions/gnresource'; describe('gnresource reducer', () => { @@ -127,4 +128,12 @@ describe('gnresource reducer', () => { } }); }); + + it('should test enableMapThumbnailViewer', () => { + const state = gnresource({}, enableMapThumbnailViewer(true)); + + expect(state).toEqual({ + showMapThumbnail: true + }); + }); }); diff --git a/geonode_mapstore_client/client/js/reducers/gnresource.js b/geonode_mapstore_client/client/js/reducers/gnresource.js index 7556bd36b5..6d881fe6af 100644 --- a/geonode_mapstore_client/client/js/reducers/gnresource.js +++ b/geonode_mapstore_client/client/js/reducers/gnresource.js @@ -26,7 +26,8 @@ import { RESOURCE_CONFIG_ERROR, SET_RESOURCE_COMPACT_PERMISSIONS, UPDATE_RESOURCE_COMPACT_PERMISSIONS, - RESET_GEO_LIMITS + RESET_GEO_LIMITS, + ENABLE_MAP_THUMBNAIL_VIEWER } from '@js/actions/gnresource'; import { @@ -161,6 +162,13 @@ function gnresource(state = defaultState, action) { }; } + case ENABLE_MAP_THUMBNAIL_VIEWER: { + return { + ...state, + showMapThumbnail: action.enabled + }; + } + case SET_SELECTED_DATASET_PERMISSIONS: return { ...state,