From f825b9d87c6bd5eb627a1a404c218f79bfdfbf1a Mon Sep 17 00:00:00 2001 From: Suren Date: Thu, 30 Jan 2025 13:22:40 +0530 Subject: [PATCH] #1947: Harmonization of download actions inside the GeoNode client --- .../js/components/Menu/DropdownList.jsx | 6 +- .../client/js/epics/index.js | 28 +++--- .../client/js/plugins/DatasetDownload.jsx | 87 +++++++++++++++++++ .../client/js/plugins/DownloadResource.jsx | 19 ++-- .../client/js/plugins/VisualStyleEditor.jsx | 4 +- .../js/plugins/actionnavbar/buttons.jsx | 2 +- .../client/js/plugins/index.js | 10 +++ .../client/js/utils/ResourceUtils.js | 9 +- .../themes/geonode/less/_layer-settings.less | 28 ++++++ .../static/mapstore/configs/localConfig.json | 16 ++++ .../mapstore/gn-translations/data.de-DE.json | 3 +- .../mapstore/gn-translations/data.en-US.json | 1 + .../mapstore/gn-translations/data.es-ES.json | 1 + .../mapstore/gn-translations/data.fi-FI.json | 1 + .../mapstore/gn-translations/data.fr-FR.json | 1 + .../mapstore/gn-translations/data.hr-HR.json | 1 + .../mapstore/gn-translations/data.it-IT.json | 1 + .../mapstore/gn-translations/data.nl-NL.json | 1 + .../mapstore/gn-translations/data.pt-PT.json | 1 + .../mapstore/gn-translations/data.sk-SK.json | 1 + .../mapstore/gn-translations/data.sv-SE.json | 1 + .../mapstore/gn-translations/data.vi-VN.json | 1 + .../mapstore/gn-translations/data.zh-ZH.json | 1 + 23 files changed, 196 insertions(+), 28 deletions(-) create mode 100644 geonode_mapstore_client/client/js/plugins/DatasetDownload.jsx diff --git a/geonode_mapstore_client/client/js/components/Menu/DropdownList.jsx b/geonode_mapstore_client/client/js/components/Menu/DropdownList.jsx index f311c81a8f..faefe61a5d 100644 --- a/geonode_mapstore_client/client/js/components/Menu/DropdownList.jsx +++ b/geonode_mapstore_client/client/js/components/Menu/DropdownList.jsx @@ -28,10 +28,10 @@ const itemElement = ({ labelId, href, badge, target }) => ( const itemsList = (items) => (items && items.map((item) => { - const { labelId, href, badge, target, type, Component, className } = item; + const { labelId, href, badge, target, type, Component, className, cfg } = item; if (type === 'plugin' && Component) { - return (
  • ); + return (
  • ); } return itemElement({ labelId, href, badge, target }); @@ -97,7 +97,7 @@ const DropdownList = ({ .map((itm, idx) => { if (itm.type === 'plugin' && itm.Component) { - return (
  • ); + return (
  • ); } if (itm.type === 'divider') { return ; diff --git a/geonode_mapstore_client/client/js/epics/index.js b/geonode_mapstore_client/client/js/epics/index.js index f62d92d87d..0dff15eef2 100644 --- a/geonode_mapstore_client/client/js/epics/index.js +++ b/geonode_mapstore_client/client/js/epics/index.js @@ -68,23 +68,23 @@ export const gnFetchMissingLayerData = (action$, { getState } = {}) => const layerResourceId = layer?.extendedParams?.pk; const layerResourceDataset = state.gnresource.data?.maplayers?.find(mapLayer => mapLayer.dataset?.pk === parseInt(layerResourceId, 10))?.dataset; return layerResourceDataset - ? isEmpty(layerResourceDataset?.linkedResources) - ? Rx.Observable.defer(() => - getDatasetByPk(layerResourceId) - .then((layerDataset) => layerDataset) - .catch(() => []) - ).switchMap((layerDataset) => - Rx.Observable.of( - updateLayerDataset(layerDataset), + ? isEmpty(layerResourceDataset?.linkedResources) + ? Rx.Observable.defer(() => + getDatasetByPk(layerResourceId) + .then((layerDataset) => layerDataset) + .catch(() => []) + ).switchMap((layerDataset) => + Rx.Observable.of( + updateLayerDataset(layerDataset), + setLayerDataset(layerResourceId) + ) + ).startWith(setLayerDataset()) + : Rx.Observable.of( setLayerDataset(layerResourceId) ) - ) : Rx.Observable.of( - setLayerDataset(layerResourceId) - ) - : Rx.Observable.of( - setLayerDataset() - ) + setLayerDataset() + ); }); diff --git a/geonode_mapstore_client/client/js/plugins/DatasetDownload.jsx b/geonode_mapstore_client/client/js/plugins/DatasetDownload.jsx new file mode 100644 index 0000000000..c698afaff2 --- /dev/null +++ b/geonode_mapstore_client/client/js/plugins/DatasetDownload.jsx @@ -0,0 +1,87 @@ +/* + * Copyright 2025, 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 React from "react"; +import { connect } from 'react-redux'; +import { createSelector } from 'reselect'; + +import { createPlugin } from "@mapstore/framework/utils/PluginsUtils"; + +import Dropdown from '@js/components/Dropdown'; +import FaIcon from '@js/components/FaIcon/FaIcon'; +import { getSelectedLayerDataset } from '@js/selectors/resource'; +import { SOURCE_TYPES } from "@js/utils/ResourceUtils"; + +const DatasetDownload = connect( + createSelector([ + getSelectedLayerDataset + ], (resource) => ({ + resource + })) +)(({ + items, + selectedNodes, + status, + statusTypes, + resource, // the selected layer's dataset resource + allowedSources = [SOURCE_TYPES.LOCAL] // allowed sources for download +}) => { + const toolbarItems = items?.filter(item => item.target === "toolbar"); + const layer = selectedNodes?.[0]?.node; + if ([statusTypes?.LAYER].includes(status) && layer && !layer?.error && toolbarItems.length > 0) { + return ( +
    + + + + + + {toolbarItems.map(({Component, name}, idx) => ( + + + + ))} + + +
    + ); + } + return null; +}); + +/** + * Plugin for downloading the dataset resource + * via direct download or export the data associated + * @name DatasetDownload + * @example + * { + * "name": "DatasetDownload" + * } + */ +export default createPlugin('DatasetDownload', { + component: DatasetDownload, + containers: { + TOC: { + doNotHide: true, + name: "DatasetDownload", + target: 'toolbar', + Component: DatasetDownload, + position: 11 + } + }, + epics: {}, + reducers: {} +}); diff --git a/geonode_mapstore_client/client/js/plugins/DownloadResource.jsx b/geonode_mapstore_client/client/js/plugins/DownloadResource.jsx index 9b2b8e2594..8ec3917c14 100644 --- a/geonode_mapstore_client/client/js/plugins/DownloadResource.jsx +++ b/geonode_mapstore_client/client/js/plugins/DownloadResource.jsx @@ -11,7 +11,7 @@ import { connect } from 'react-redux'; import { createSelector } from 'reselect'; import isEmpty from 'lodash/isEmpty'; import { createPlugin } from '@mapstore/framework/utils/PluginsUtils'; -import { getDownloadUrlInfo, isDocumentExternalSource, GXP_PTYPES } from '@js/utils/ResourceUtils'; +import { getDownloadUrlInfo, isDocumentExternalSource, GXP_PTYPES, SOURCE_TYPES } from '@js/utils/ResourceUtils'; import Message from '@mapstore/framework/components/I18N/Message'; import Button from '@js/components/Button'; import tooltip from '@mapstore/framework/components/misc/enhancers/tooltip'; @@ -38,6 +38,8 @@ const DownloadButton = ({ onAction = () => {}, renderType = "button", showIcon, + downloadMsgId = "gnviewer.download", + allowedSources = [SOURCE_TYPES.LOCAL, SOURCE_TYPES.REMOTE], downloading }) => { const Component = RENDER_TYPE[renderType]; @@ -51,6 +53,7 @@ const DownloadButton = ({ || !_resource?.perms?.includes('download_resourcebase') || (!isButton && isNotAjaxSafe) || [GXP_PTYPES.REST_MAP, GXP_PTYPES.REST_IMG].includes(_resource?.ptype) // exclude arcgis remote layers from direct download + || !allowedSources.includes(_resource?.sourcetype) ) { return null; } @@ -59,7 +62,7 @@ const DownloadButton = ({ return downloadInfo.url ? ( {showIcon ? - : + : } ) : null; @@ -78,11 +81,11 @@ const DownloadButton = ({ disabled={!!downloading} onClick={() => downloading ? null : onAction(_resource)} {...isButton && { variant, size}} - {...showIcon && { tooltipId: "gnviewer.download" }} + {...showIcon && { tooltipId: downloadMsgId }} > {showIcon ? - : + : } ); @@ -133,6 +136,12 @@ export default createPlugin('DownloadResource', { target: 'toolbar', Component: DownloadResource, priority: 1 + }, + DatasetDownload: { + name: 'DownloadResource', + target: 'toolbar', + Component: DownloadResource, + priority: 1 } }, epics: {}, diff --git a/geonode_mapstore_client/client/js/plugins/VisualStyleEditor.jsx b/geonode_mapstore_client/client/js/plugins/VisualStyleEditor.jsx index 5bd712f9ad..5f2ea97af5 100644 --- a/geonode_mapstore_client/client/js/plugins/VisualStyleEditor.jsx +++ b/geonode_mapstore_client/client/js/plugins/VisualStyleEditor.jsx @@ -52,7 +52,7 @@ import tooltip from '@mapstore/framework/components/misc/enhancers/tooltip'; import { getSelectedLayer, layersSelector } from '@mapstore/framework/selectors/layers'; import useLocalStorage from '@js/hooks/useLocalStorage'; import TemplateSelector from '@js/plugins/visualstyleeditor/TemplateSelector'; -import { isDefaultDatasetSubtype } from '@js/utils/ResourceUtils'; +import { isDefaultDatasetSubtype, SOURCE_TYPES } from '@js/utils/ResourceUtils'; const Button = tooltip(GNButton); @@ -318,7 +318,7 @@ function StyleEditorTocButton({ if (hide || status !== statusTypes.LAYER || !mapLayer?.dataset - || mapLayer?.dataset?.sourcetype === 'REMOTE' + || mapLayer?.dataset?.sourcetype === SOURCE_TYPES.REMOTE || !changeResource || isNew || !isDefaultDatasetSubtype(mapLayer?.dataset?.subtype)) { diff --git a/geonode_mapstore_client/client/js/plugins/actionnavbar/buttons.jsx b/geonode_mapstore_client/client/js/plugins/actionnavbar/buttons.jsx index a443d49ab8..62c07a975e 100644 --- a/geonode_mapstore_client/client/js/plugins/actionnavbar/buttons.jsx +++ b/geonode_mapstore_client/client/js/plugins/actionnavbar/buttons.jsx @@ -78,7 +78,7 @@ export const LayerDownloadActionButton = connect( size={size} onClick={() => onClick()} > - + ); }); diff --git a/geonode_mapstore_client/client/js/plugins/index.js b/geonode_mapstore_client/client/js/plugins/index.js index 24075395da..94192b9e4b 100644 --- a/geonode_mapstore_client/client/js/plugins/index.js +++ b/geonode_mapstore_client/client/js/plugins/index.js @@ -69,15 +69,25 @@ export const plugins = { OperationPlugin, MetadataEditorPlugin, MetadataViewerPlugin, + DatasetDownloadPlugin: toModulePlugin( + 'DatasetDownload', + () => import(/* webpackChunkName: 'plugins/dataset-download' */ '@js/plugins/DatasetDownload') + ), LayerDownloadPlugin: toModulePlugin( 'LayerDownload', () => import(/* webpackChunkName: 'plugins/layer-download' */ '@mapstore/framework/plugins/LayerDownload'), { overrides: { containers: { + TOC: {}, ActionNavbar: { name: 'LayerDownload', Component: LayerDownloadActionButton + }, + DatasetDownload: { + name: 'LayerDownload', + Component: LayerDownloadActionButton, + target: 'toolbar' } } } diff --git a/geonode_mapstore_client/client/js/utils/ResourceUtils.js b/geonode_mapstore_client/client/js/utils/ResourceUtils.js index f16927d58d..c848db7abb 100644 --- a/geonode_mapstore_client/client/js/utils/ResourceUtils.js +++ b/geonode_mapstore_client/client/js/utils/ResourceUtils.js @@ -84,6 +84,11 @@ export const isDefaultDatasetSubtype = (subtype) => !subtype || ['vector', 'rast export const FEATURE_INFO_FORMAT = 'TEMPLATE'; +export const SOURCE_TYPES = { + LOCAL: 'LOCAL', + REMOTE: 'REMOTE' +}; + const datasetAttributeSetToFields = ({ attribute_set: attributeSet = [] }) => { return attributeSet .filter(({ attribute_type: type }) => !type.includes('gml:')) @@ -221,7 +226,7 @@ export const resourceToLayerConfig = (resource) => { ...(dimensions.length > 0 && ({ dimensions })), extendedParams, ...(fields && { fields }), - ...(sourcetype === 'REMOTE' && !wmsUrl.includes('/geoserver/') && { + ...(sourcetype === SOURCE_TYPES.REMOTE && !wmsUrl.includes('/geoserver/') && { serverType: ServerTypes.NO_VENDOR }) }; @@ -327,7 +332,7 @@ export const ResourceTypes = { }; export const isDocumentExternalSource = (resource) => { - return resource && resource.resource_type === ResourceTypes.DOCUMENT && resource.sourcetype === 'REMOTE'; + return resource && resource.resource_type === ResourceTypes.DOCUMENT && resource.sourcetype === SOURCE_TYPES.REMOTE; }; export const getResourceTypesInfo = () => ({ diff --git a/geonode_mapstore_client/client/themes/geonode/less/_layer-settings.less b/geonode_mapstore_client/client/themes/geonode/less/_layer-settings.less index 98b8fd5512..8aec2331cd 100644 --- a/geonode_mapstore_client/client/themes/geonode/less/_layer-settings.less +++ b/geonode_mapstore_client/client/themes/geonode/less/_layer-settings.less @@ -66,3 +66,31 @@ } } + +.ms-toc-container { + .ms-toc-toolbar-content { + .gn-layer-download { + width: 30px; + .download-dropdown { + position: absolute; + top: 0; + width: inherit; + button.dropdown-toggle{ + width: inherit; + } + ul.dropdown-menu { + width: 120px; + li { + a[role="menuitem"] { + padding: 0; + } + button { + width: 100%; + text-align: left; + } + } + } + } + } + } +} \ No newline at end of file diff --git a/geonode_mapstore_client/static/mapstore/configs/localConfig.json b/geonode_mapstore_client/static/mapstore/configs/localConfig.json index 84b4f0f3fb..4b6b86b01a 100644 --- a/geonode_mapstore_client/static/mapstore/configs/localConfig.json +++ b/geonode_mapstore_client/static/mapstore/configs/localConfig.json @@ -629,6 +629,14 @@ "disableIf": "{!state('selectedLayerPermissions').includes('download_resourcebase') || context.isDocumentExternalSource(state('gnResourceData'))}", "type": "dropdown", "items": [ + { + "type": "plugin", + "name": "DownloadResource", + "cfg": { + "downloadMsgId": "gnhome.dataset", + "allowedSources": ["LOCAL"] + } + }, { "type": "plugin", "name": "LayerDownload" @@ -1610,6 +1618,14 @@ } } }, + { + "name": "DatasetDownload", + "mandatory": true + }, + { + "name": "DownloadResource", + "mandatory": true + }, { "name": "MapThumbnail" }, diff --git a/geonode_mapstore_client/static/mapstore/gn-translations/data.de-DE.json b/geonode_mapstore_client/static/mapstore/gn-translations/data.de-DE.json index 3dd6a45409..31e487aa52 100644 --- a/geonode_mapstore_client/static/mapstore/gn-translations/data.de-DE.json +++ b/geonode_mapstore_client/static/mapstore/gn-translations/data.de-DE.json @@ -175,7 +175,8 @@ }, "gnviewer": { "edit": "Bearbeiten", - "export": "Export", + "export": "Exportieren", + "exportData": "Daten exportieren", "editInfo": "Informationen anzeigen", "editMetadata": "Metadaten bearbeiten", "editStyle": "Stil bearbeiten", diff --git a/geonode_mapstore_client/static/mapstore/gn-translations/data.en-US.json b/geonode_mapstore_client/static/mapstore/gn-translations/data.en-US.json index f453a940f2..aa81fec222 100644 --- a/geonode_mapstore_client/static/mapstore/gn-translations/data.en-US.json +++ b/geonode_mapstore_client/static/mapstore/gn-translations/data.en-US.json @@ -176,6 +176,7 @@ "gnviewer": { "edit": "Edit", "export": "Export", + "exportData": "Export Data", "editInfo": "Edit Info", "editMetadata": "Edit Metadata", "editStyle": "Edit Style", diff --git a/geonode_mapstore_client/static/mapstore/gn-translations/data.es-ES.json b/geonode_mapstore_client/static/mapstore/gn-translations/data.es-ES.json index 32da967118..0f0acabfea 100644 --- a/geonode_mapstore_client/static/mapstore/gn-translations/data.es-ES.json +++ b/geonode_mapstore_client/static/mapstore/gn-translations/data.es-ES.json @@ -176,6 +176,7 @@ "gnviewer": { "edit": "Editar", "export": "Exportar", + "exportData": "Exportar datos", "editInfo": "Editar información", "editMetadata": "Editar Metadatos", "editStyle": "Editar Estilo", diff --git a/geonode_mapstore_client/static/mapstore/gn-translations/data.fi-FI.json b/geonode_mapstore_client/static/mapstore/gn-translations/data.fi-FI.json index fc6cdde0a7..c17696ace1 100644 --- a/geonode_mapstore_client/static/mapstore/gn-translations/data.fi-FI.json +++ b/geonode_mapstore_client/static/mapstore/gn-translations/data.fi-FI.json @@ -174,6 +174,7 @@ "gnviewer": { "edit": "Edit", "export": "Export", + "exportData": "Export Data", "editInfo": "Edit Info", "editMetadata": "Edit Metadata", "editStyle": "Edit Style", diff --git a/geonode_mapstore_client/static/mapstore/gn-translations/data.fr-FR.json b/geonode_mapstore_client/static/mapstore/gn-translations/data.fr-FR.json index 4a962c91cd..ce35634292 100644 --- a/geonode_mapstore_client/static/mapstore/gn-translations/data.fr-FR.json +++ b/geonode_mapstore_client/static/mapstore/gn-translations/data.fr-FR.json @@ -176,6 +176,7 @@ "gnviewer": { "edit": "Éditer", "export": "Exportation", + "exportData": "Exporter les données", "editMetadata": "Modifier les Métadonnées", "view": "Vue", "viewMetadata": "Afficher les métadonnées", diff --git a/geonode_mapstore_client/static/mapstore/gn-translations/data.hr-HR.json b/geonode_mapstore_client/static/mapstore/gn-translations/data.hr-HR.json index d30f63792f..4b348b8b8f 100644 --- a/geonode_mapstore_client/static/mapstore/gn-translations/data.hr-HR.json +++ b/geonode_mapstore_client/static/mapstore/gn-translations/data.hr-HR.json @@ -174,6 +174,7 @@ "gnviewer": { "edit": "Edit", "export": "Export", + "exportData": "Export Data", "editInfo": "Edit Info", "editMetadata": "Edit Metadata", "editStyle": "Edit Style", diff --git a/geonode_mapstore_client/static/mapstore/gn-translations/data.it-IT.json b/geonode_mapstore_client/static/mapstore/gn-translations/data.it-IT.json index 385d85b06a..db934ebfc0 100644 --- a/geonode_mapstore_client/static/mapstore/gn-translations/data.it-IT.json +++ b/geonode_mapstore_client/static/mapstore/gn-translations/data.it-IT.json @@ -178,6 +178,7 @@ "gnviewer": { "edit": "Modifica", "export": "Esporta", + "exportData": "Esporta Dati", "editMetadata": "Modifica Metadati", "view": "Visualizza", "viewMetadata": "Visualizza i metadati", diff --git a/geonode_mapstore_client/static/mapstore/gn-translations/data.nl-NL.json b/geonode_mapstore_client/static/mapstore/gn-translations/data.nl-NL.json index d85c317460..cfcc251b12 100644 --- a/geonode_mapstore_client/static/mapstore/gn-translations/data.nl-NL.json +++ b/geonode_mapstore_client/static/mapstore/gn-translations/data.nl-NL.json @@ -174,6 +174,7 @@ "gnviewer": { "edit": "Edit", "export": "Export", + "exportData": "Export Data", "editInfo": "Edit Info", "editMetadata": "Edit Metadata", "editStyle": "Edit Style", diff --git a/geonode_mapstore_client/static/mapstore/gn-translations/data.pt-PT.json b/geonode_mapstore_client/static/mapstore/gn-translations/data.pt-PT.json index c97af1a453..13bc9711fd 100644 --- a/geonode_mapstore_client/static/mapstore/gn-translations/data.pt-PT.json +++ b/geonode_mapstore_client/static/mapstore/gn-translations/data.pt-PT.json @@ -174,6 +174,7 @@ "gnviewer": { "edit": "Edit", "export": "Export", + "exportData": "Export Data", "editInfo": "Edit Info", "editMetadata": "Edit Metadata", "editStyle": "Edit Style", diff --git a/geonode_mapstore_client/static/mapstore/gn-translations/data.sk-SK.json b/geonode_mapstore_client/static/mapstore/gn-translations/data.sk-SK.json index fedece922e..b2a855cf13 100644 --- a/geonode_mapstore_client/static/mapstore/gn-translations/data.sk-SK.json +++ b/geonode_mapstore_client/static/mapstore/gn-translations/data.sk-SK.json @@ -174,6 +174,7 @@ "gnviewer": { "edit": "Edit", "export": "Export", + "exportData": "Export Data", "editInfo": "Edit Info", "editMetadata": "Edit Metadata", "editStyle": "Edit Style", diff --git a/geonode_mapstore_client/static/mapstore/gn-translations/data.sv-SE.json b/geonode_mapstore_client/static/mapstore/gn-translations/data.sv-SE.json index c6f23f56a6..3abd2efd58 100644 --- a/geonode_mapstore_client/static/mapstore/gn-translations/data.sv-SE.json +++ b/geonode_mapstore_client/static/mapstore/gn-translations/data.sv-SE.json @@ -175,6 +175,7 @@ "gnviewer": { "edit": "Edit", "export": "Export", + "exportData": "Export Data", "editInfo": "Edit Info", "editMetadata": "Edit Metadata", "editStyle": "Edit Style", diff --git a/geonode_mapstore_client/static/mapstore/gn-translations/data.vi-VN.json b/geonode_mapstore_client/static/mapstore/gn-translations/data.vi-VN.json index 582ececc1a..38703b7f26 100644 --- a/geonode_mapstore_client/static/mapstore/gn-translations/data.vi-VN.json +++ b/geonode_mapstore_client/static/mapstore/gn-translations/data.vi-VN.json @@ -174,6 +174,7 @@ "gnviewer": { "edit": "Edit", "export": "Export", + "exportData": "Export Data", "editInfo": "Edit Info", "editMetadata": "Edit Metadata", "editStyle": "Edit Style", diff --git a/geonode_mapstore_client/static/mapstore/gn-translations/data.zh-ZH.json b/geonode_mapstore_client/static/mapstore/gn-translations/data.zh-ZH.json index 4e8373b383..cd7f6e3d11 100644 --- a/geonode_mapstore_client/static/mapstore/gn-translations/data.zh-ZH.json +++ b/geonode_mapstore_client/static/mapstore/gn-translations/data.zh-ZH.json @@ -174,6 +174,7 @@ "gnviewer": { "edit": "Edit", "export": "Export", + "exportData": "Export Data", "editInfo": "Edit Info", "editMetadata": "Edit Metadata", "editStyle": "Edit Style",