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"
}
]
},