diff --git a/geonode_mapstore_client/client/js/components/ActionButtons/ActionButtons.jsx b/geonode_mapstore_client/client/js/components/ActionButtons/ActionButtons.jsx
index 722471ca1e..68a63b258d 100644
--- a/geonode_mapstore_client/client/js/components/ActionButtons/ActionButtons.jsx
+++ b/geonode_mapstore_client/client/js/components/ActionButtons/ActionButtons.jsx
@@ -5,12 +5,21 @@
* 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 React, { useRef } from 'react';
import PropTypes from 'prop-types';
import Dropdown from '@js/components/Dropdown';
import Message from '@mapstore/framework/components/I18N/Message';
import FaIcon from '@js/components/FaIcon';
+import { canCopyResource } from '@js/utils/ResourceUtils';
+// this is a workaround based on the current structure of actions in card options
+// new version will centralize this logic inside the correspondent plugins
+const checkAction = {
+ 'delete': (resource) => !!resource?.perms?.includes('delete_resourcebase'),
+ // we assume tha the add_resource check has been checked in parent elements
+ 'copy': (resource) => canCopyResource(resource, { perms: ['add_resource'] }),
+ 'download': (resource) => !!(resource?.download_url && resource?.perms?.includes('download_resourcebase'))
+};
function ActionButtons({
options,
actions,
@@ -20,16 +29,18 @@ function ActionButtons({
onDownload
}) {
- // 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;
- }
- }
-
+ const containerNode = useRef();
+ const dropdownClassName = 'gn-card-dropdown';
+ const dropdownNode = containerNode?.current?.querySelector(`.${dropdownClassName}`);
+ const isDropdownEmpty = (dropdownNode?.children?.length || 0) === 0;
return (
-
+
event.stopPropagation()}
+ style={isDropdownEmpty ? { display: 'none' } : {}}
+ >
-
+
{options.map((opt) => {
if ((opt.type === 'button' && actions[opt.action]) || opt.action === 'download') {
- return (
- ((opt.action === 'download' && resource.download_url) || (opt.action !== 'copy' && opt.action !== 'download') || (resource?.is_copyable && opt.action !== 'download')) &&
opt.action !== 'download' ? onAction(actions[opt.action], [
@@ -53,8 +65,8 @@ function ActionButtons({
>
{' '}
-
- );
+ )
+ : null;
}
return (
diff --git a/geonode_mapstore_client/client/js/plugins/SaveAs.jsx b/geonode_mapstore_client/client/js/plugins/SaveAs.jsx
index 645e4ceb9d..61ac1e3266 100644
--- a/geonode_mapstore_client/client/js/plugins/SaveAs.jsx
+++ b/geonode_mapstore_client/client/js/plugins/SaveAs.jsx
@@ -12,9 +12,8 @@ import { createSelector } from 'reselect';
import { createPlugin } from '@mapstore/framework/utils/PluginsUtils';
import { setControlProperty } from '@mapstore/framework/actions/controls';
import Message from '@mapstore/framework/components/I18N/Message';
-import { Glyphicon } from 'react-bootstrap';
import { mapInfoSelector } from '@mapstore/framework/selectors/map';
-import { isLoggedIn } from '@mapstore/framework/selectors/security';
+import { userSelector } from '@mapstore/framework/selectors/security';
import Button from '@js/components/Button';
import {
saveContent,
@@ -33,6 +32,7 @@ import {
getResourceDirtyState
} from '@js/selectors/resource';
import { ProcessTypes } from '@js/utils/ResourceServiceUtils';
+import { canCopyResource } from '@js/utils/ResourceUtils';
import { processResources } from '@js/actions/gnresource';
import { getCurrentResourceCopyLoading } from '@js/selectors/resourceservice';
@@ -133,15 +133,28 @@ function SaveAsButton({
;
}
+const canCopyResourceFunction = (state) => {
+ return (resource) => {
+ const user = userSelector(state);
+ if (!user) {
+ return false;
+ }
+ const isResourceNew = isNewResource(state);
+ const canAdd = canAddResource(state);
+ if (isResourceNew && canAdd) {
+ return true;
+ }
+ return canCopyResource(resource, user);
+ };
+};
+
const ConnectedSaveAsButton = connect(
createSelector(
- isLoggedIn,
- canAddResource,
getResourceData,
getResourceDirtyState,
- isNewResource,
- (loggedIn, userCanAddResource, resource, dirtyState, isResourceNew) => ({
- enabled: loggedIn && userCanAddResource && (resource?.is_copyable || isResourceNew),
+ canCopyResourceFunction,
+ (resource, dirtyState, canCopy) => ({
+ enabled: !!canCopy(resource),
resource,
disabled: !!dirtyState
})
@@ -154,20 +167,6 @@ const ConnectedSaveAsButton = connect(
export default createPlugin('SaveAs', {
component: SaveAsPlugin,
containers: {
- BurgerMenu: {
- name: 'saveAs',
- position: 30,
- text: ,
- icon: ,
- action: setControlProperty.bind(null, 'saveAs', null),
- selector: createSelector(
- isLoggedIn,
- canAddResource,
- (loggedIn, userCanAddResource) => ({
- style: (loggedIn && userCanAddResource) ? {} : { display: 'none' }
- })
- )
- },
ActionNavbar: {
name: 'SaveAs',
Component: ConnectedSaveAsButton
diff --git a/geonode_mapstore_client/client/js/utils/ResourceUtils.js b/geonode_mapstore_client/client/js/utils/ResourceUtils.js
index 8a8d0069af..26b039aa06 100644
--- a/geonode_mapstore_client/client/js/utils/ResourceUtils.js
+++ b/geonode_mapstore_client/client/js/utils/ResourceUtils.js
@@ -585,13 +585,19 @@ export const parseMapConfig = (mapResponse, resource = {}) => {
};
};
-/**
-* Util to check if resosurce can be cloned (Save As)
+/*
+* Util to check if resource can be cloned (Save As)
* Requirements for copying are 'add_resource' permission and is_copyable property on resource
+* the dataset and document need also the download_resourcebase permission
*/
export const canCopyResource = (resource, user) => {
const canAdd = user?.perms?.includes('add_resource');
const canCopy = resource?.is_copyable;
+ const resourceType = resource?.resource_type;
+ if ([ResourceTypes.DATASET, ResourceTypes.DOCUMENT].includes(resourceType)) {
+ const canDownload = !!resource?.perms?.includes('download_resourcebase');
+ return (canAdd && canCopy && canDownload) ? true : false;
+ }
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 f81327b28f..c68a88097c 100644
--- a/geonode_mapstore_client/client/js/utils/__tests__/ResourceUtils-test.js
+++ b/geonode_mapstore_client/client/js/utils/__tests__/ResourceUtils-test.js
@@ -422,11 +422,19 @@ describe('Test Resource Utils', () => {
expect(pasrsedStyleName).toBe('test:testName');
});
- it('should test canCopyResource', () => {
- const resource = { is_copyable: true };
+ it('should test canCopyResource with different resource type', () => {
const user = { perms: ['add_resource'] };
+ expect(canCopyResource({ resource_type: 'dataset', perms: ['download_resourcebase'], is_copyable: true }, user)).toBe(true);
+ expect(canCopyResource({ resource_type: 'document', perms: ['download_resourcebase'], is_copyable: true }, user)).toBe(true);
+ expect(canCopyResource({ resource_type: 'map', perms: [], is_copyable: true }, user)).toBe(true);
+ expect(canCopyResource({ resource_type: 'geostory', perms: [], is_copyable: true }, user)).toBe(true);
+ expect(canCopyResource({ resource_type: 'dashboard', perms: [], is_copyable: true }, user)).toBe(true);
- expect(canCopyResource(resource, user)).toEqual(true);
+ expect(canCopyResource({ resource_type: 'dataset', perms: [], is_copyable: true }, user)).toBe(false);
+ expect(canCopyResource({ resource_type: 'document', perms: [], is_copyable: true }, user)).toBe(false);
+ expect(canCopyResource({ resource_type: 'map', perms: [] }, user)).toBe(false);
+ expect(canCopyResource({ resource_type: 'geostory', perms: [] }, user)).toBe(false);
+ expect(canCopyResource({ resource_type: 'dashboard', perms: [] }, user)).toBe(false);
});
it('should test excludeDeletedResources', () => {
diff --git a/geonode_mapstore_client/client/static/mapstore/configs/localConfig.json b/geonode_mapstore_client/client/static/mapstore/configs/localConfig.json
index 3bfaf8b52a..9385067f4f 100644
--- a/geonode_mapstore_client/client/static/mapstore/configs/localConfig.json
+++ b/geonode_mapstore_client/client/static/mapstore/configs/localConfig.json
@@ -450,10 +450,6 @@
{
"type": "user",
"value": "add_resource"
- },
- {
- "type": "resource",
- "value": "download_resourcebase"
}
]
},