diff --git a/geonode_mapstore_client/client/js/components/ActionButtons/ActionButtons.jsx b/geonode_mapstore_client/client/js/components/ActionButtons/ActionButtons.jsx index 31c677525e..722471ca1e 100644 --- a/geonode_mapstore_client/client/js/components/ActionButtons/ActionButtons.jsx +++ b/geonode_mapstore_client/client/js/components/ActionButtons/ActionButtons.jsx @@ -20,8 +20,11 @@ function ActionButtons({ onDownload }) { - if (options?.length === 1 && options?.[0].action === 'download' && !resource.download_url) { - return null; + // do not render if the options only contain download or copy or both without meeting their requirements + if (options?.every(({action}) => action !== 'delete')) { + if (options?.every(({action}) => (action === 'download' && !resource.download_url) || (['copy'].includes(action) && !resource.is_copyable & !resource.download_url))) { + return null; + } } diff --git a/geonode_mapstore_client/client/js/components/__tests__/ActionButtons-test.jsx b/geonode_mapstore_client/client/js/components/__tests__/ActionButtons-test.jsx index 0726a33a5f..8662d86a7a 100644 --- a/geonode_mapstore_client/client/js/components/__tests__/ActionButtons-test.jsx +++ b/geonode_mapstore_client/client/js/components/__tests__/ActionButtons-test.jsx @@ -24,7 +24,7 @@ describe('ALink test', () => { }); it('render Action Button with defaults', () => { - ReactDOM.render(, document.getElementById('container')); + ReactDOM.render(, document.getElementById('container')); const actionButton = document.querySelector( '.gn-resource-action-buttons' ); diff --git a/geonode_mapstore_client/client/js/plugins/SaveAs.jsx b/geonode_mapstore_client/client/js/plugins/SaveAs.jsx index 105a7aa6d4..3f5b107df9 100644 --- a/geonode_mapstore_client/client/js/plugins/SaveAs.jsx +++ b/geonode_mapstore_client/client/js/plugins/SaveAs.jsx @@ -140,7 +140,7 @@ const ConnectedSaveAsButton = connect( getResourceData, getResourceDirtyState, (loggedIn, userCanAddResource, resource, dirtyState) => ({ - enabled: loggedIn && userCanAddResource, + enabled: loggedIn && userCanAddResource && resource?.is_copyable, resource, disabled: !!dirtyState }) diff --git a/geonode_mapstore_client/client/js/plugins/index.js b/geonode_mapstore_client/client/js/plugins/index.js index 495a73743d..fe9e84214a 100644 --- a/geonode_mapstore_client/client/js/plugins/index.js +++ b/geonode_mapstore_client/client/js/plugins/index.js @@ -20,7 +20,8 @@ import { } from '@js/plugins/actionnavbar/buttons'; import { getMetadataUrl, getMetadataDetailUrl, - resourceHasPermission } from '@js/utils/ResourceUtils'; + resourceHasPermission, + canCopyResource } from '@js/utils/ResourceUtils'; const EXCLUDED_EPICS_NAMES = [ 'loadGeostoryEpic', @@ -414,7 +415,8 @@ const pluginsDefinition = { requires: { getMetadataUrl, getMetadataDetailUrl, - resourceHasPermission + resourceHasPermission, + canCopyResource }, epics: {}, reducers: {} diff --git a/geonode_mapstore_client/client/js/plugins/save/SaveModal.jsx b/geonode_mapstore_client/client/js/plugins/save/SaveModal.jsx index 7df9bd1621..3055331066 100644 --- a/geonode_mapstore_client/client/js/plugins/save/SaveModal.jsx +++ b/geonode_mapstore_client/client/js/plugins/save/SaveModal.jsx @@ -70,7 +70,7 @@ function SaveModal({ if (copy && currentModal?.current) { currentModal?.current?.addEventListener('keyup', (event) => { if (event.keyCode === 13) { - event.preventDefault(); + event.stopPropagation(); onSave( update ? contentId : undefined, { diff --git a/geonode_mapstore_client/client/js/utils/ResourceUtils.js b/geonode_mapstore_client/client/js/utils/ResourceUtils.js index 1548a3b7bc..9376b057eb 100644 --- a/geonode_mapstore_client/client/js/utils/ResourceUtils.js +++ b/geonode_mapstore_client/client/js/utils/ResourceUtils.js @@ -577,3 +577,13 @@ export const parseMapConfig = (mapResponse, resource = {}) => { type: 'map' }; }; + +/** +* Util to check if resosurce can be cloned (Save As) +* Requirements for copying are 'add_resource' permission and is_copyable property on resource +*/ +export const canCopyResource = (resource, user) => { + const canAdd = user?.perms?.includes('add_resource'); + const canCopy = resource?.is_copyable; + return (canAdd && canCopy) ? true : false; +}; diff --git a/geonode_mapstore_client/client/js/utils/__tests__/ResourceUtils-test.js b/geonode_mapstore_client/client/js/utils/__tests__/ResourceUtils-test.js index 716af4b544..20c34d27ea 100644 --- a/geonode_mapstore_client/client/js/utils/__tests__/ResourceUtils-test.js +++ b/geonode_mapstore_client/client/js/utils/__tests__/ResourceUtils-test.js @@ -17,7 +17,8 @@ import { toGeoNodeMapConfig, compareBackgroundLayers, toMapStoreMapConfig, - parseStyleName + parseStyleName, + canCopyResource } from '../ResourceUtils'; describe('Test Resource Utils', () => { @@ -415,4 +416,11 @@ describe('Test Resource Utils', () => { expect(pasrsedStyleName).toBe('test:testName'); }); + + it('should test canCopyResource', () => { + const resource = { is_copyable: true }; + const user = { perms: ['add_resource'] }; + + expect(canCopyResource(resource, user)).toEqual(true); + }); }); diff --git a/geonode_mapstore_client/client/static/mapstore/configs/localConfig.json b/geonode_mapstore_client/client/static/mapstore/configs/localConfig.json index 2de5165ce4..089b7bb4e2 100644 --- a/geonode_mapstore_client/client/static/mapstore/configs/localConfig.json +++ b/geonode_mapstore_client/client/static/mapstore/configs/localConfig.json @@ -449,13 +449,7 @@ "action": "copy", "labelId": "gnviewer.clone", "icon": "copy", - "authenticated": true, - "perms": [ - { - "type": "resource", - "value": "change_resourcebase" - } - ] + "authenticated": true }, { "type": "button", @@ -852,7 +846,7 @@ { "labelId": "gnviewer.save", "showPendingChangesIcon": true, - "disableIf": "{!context.resourceHasPermission(state('gnResourceData'), 'change_resourcebase')}", + "disableIf": "{!context.resourceHasPermission(state('gnResourceData'), 'change_resourcebase') && !context.canCopyResource(state('gnResourceData'), state('user'))}", "type": "dropdown", "items": [ { @@ -861,8 +855,7 @@ }, { "type": "plugin", - "name": "SaveAs", - "disableIf": "{state('gnResourceData') && state('gnResourceData').is_copyable ? false : true}" + "name": "SaveAs" } ] }, @@ -1571,7 +1564,7 @@ { "labelId": "gnviewer.save", "showPendingChangesIcon": true, - "disableIf": "{!state('isNewResource') && !context.resourceHasPermission(state('gnResourceData'), 'change_resourcebase')}", + "disableIf": "{!context.resourceHasPermission(state('gnResourceData'), 'change_resourcebase') && !context.canCopyResource(state('gnResourceData'), state('user'))}", "type": "dropdown", "items": [ { @@ -2030,7 +2023,7 @@ { "labelId": "gnviewer.save", "showPendingChangesIcon": true, - "disableIf": "{!state('isNewResource') && !context.resourceHasPermission(state('gnResourceData'), 'change_resourcebase')}", + "disableIf": "{!context.resourceHasPermission(state('gnResourceData'), 'change_resourcebase') && !context.canCopyResource(state('gnResourceData'), state('user'))}", "type": "dropdown", "items": [ { @@ -2215,7 +2208,7 @@ "labelId": "gnviewer.save", "type": "dropdown", "showPendingChangesIcon": true, - "disableIf": "{!context.resourceHasPermission(state('gnResourceData'), 'change_resourcebase')}", + "disableIf": "{!context.resourceHasPermission(state('gnResourceData'), 'change_resourcebase') && !context.canCopyResource(state('gnResourceData'), state('user'))}", "items": [ { "type": "plugin", @@ -2223,8 +2216,7 @@ }, { "type": "plugin", - "name": "SaveAs", - "disableIf": "{state('gnResourceData') && state('gnResourceData').is_copyable ? false : true}" + "name": "SaveAs" } ] },