From 12245eb5d57035123320e2462b67350ca54c0657 Mon Sep 17 00:00:00 2001
From: David Quartey <42542676+DavidQuartz@users.noreply.github.com>
Date: Thu, 24 Mar 2022 10:50:50 +0000
Subject: [PATCH] Home and catalogue pages' layout breaks after multiple
successive resource deletions (#888)
---
.../js/components/CardGrid/CardGrid.jsx | 12 +---
.../js/components/FeaturedList/Cards.jsx | 12 +---
.../components/FeaturedList/FeaturedList.jsx | 1 +
.../__tests__/ActionButtons-test.jsx | 2 +-
.../js/routes/__tests__/UploadCard-test.jsx | 41 ++++++++++++++
.../client/js/routes/upload/UploadCard.jsx | 11 +++-
.../js/selectors/__tests__/search-test.js | 55 +++++++++++++++++++
.../client/js/selectors/search.js | 12 ++--
.../client/js/utils/ResourceUtils.js | 7 +++
.../js/utils/__tests__/ResourceUtils-test.js | 10 +++-
10 files changed, 134 insertions(+), 29 deletions(-)
create mode 100644 geonode_mapstore_client/client/js/routes/__tests__/UploadCard-test.jsx
create mode 100644 geonode_mapstore_client/client/js/selectors/__tests__/search-test.js
diff --git a/geonode_mapstore_client/client/js/components/CardGrid/CardGrid.jsx b/geonode_mapstore_client/client/js/components/CardGrid/CardGrid.jsx
index d5f0f6ad57..f993822b06 100644
--- a/geonode_mapstore_client/client/js/components/CardGrid/CardGrid.jsx
+++ b/geonode_mapstore_client/client/js/components/CardGrid/CardGrid.jsx
@@ -90,25 +90,17 @@ const Cards = withResizeDetector(({
style={cardLayoutStyle === 'list' ? {} : containerStyle}
>
{resources.map((resource, idx) => {
- const {
- isProcessing,
- isDeleted
- } = getResourceStatuses(resource);
+ const { isProcessing } = getResourceStatuses(resource);
// enable allowedOptions (menu cards)
const allowedOptions = !isProcessing ? options
.filter((opt) => hasPermissionsTo(resource?.perms, opt?.perms, 'resource')) : [];
- if (isDeleted) {
- return null;
- }
-
return (
download.pk === resource.pk) ? true : false}
/>
diff --git a/geonode_mapstore_client/client/js/components/FeaturedList/Cards.jsx b/geonode_mapstore_client/client/js/components/FeaturedList/Cards.jsx
index 89ee2ec044..6697d6b81e 100644
--- a/geonode_mapstore_client/client/js/components/FeaturedList/Cards.jsx
+++ b/geonode_mapstore_client/client/js/components/FeaturedList/Cards.jsx
@@ -68,14 +68,7 @@ const Cards = ({
style={containerStyle}
>
{resources.map((resource, idx) => {
- const {
- isProcessing,
- isDeleted
- } = getResourceStatuses(resource);
-
- if (isDeleted) {
- return null;
- }
+ const { isProcessing } = getResourceStatuses(resource);
return (
{
const [count, setCount] = useState();
+
const nextIconStyles = {
fontSize: '1rem',
...(!isNextPageAvailable || loading ? {color: 'grey', cursor: 'not-allowed'} : {cursor: 'pointer'})
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 8662d86a7a..36edec4d63 100644
--- a/geonode_mapstore_client/client/js/components/__tests__/ActionButtons-test.jsx
+++ b/geonode_mapstore_client/client/js/components/__tests__/ActionButtons-test.jsx
@@ -11,7 +11,7 @@ import ReactDOM from 'react-dom';
import expect from 'expect';
import ActionButtons from '../ActionButtons';
-describe('ALink test', () => {
+describe('ActionButtons test', () => {
beforeEach((done) => {
document.body.innerHTML = '';
setTimeout(done);
diff --git a/geonode_mapstore_client/client/js/routes/__tests__/UploadCard-test.jsx b/geonode_mapstore_client/client/js/routes/__tests__/UploadCard-test.jsx
new file mode 100644
index 0000000000..b0b9c12a60
--- /dev/null
+++ b/geonode_mapstore_client/client/js/routes/__tests__/UploadCard-test.jsx
@@ -0,0 +1,41 @@
+/*
+ * 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 React from 'react';
+import ReactDOM from 'react-dom';
+import expect from 'expect';
+import UploadCard from '../upload/UploadCard';
+
+describe('upload card tests', () => {
+ beforeEach((done) => {
+ document.body.innerHTML = '';
+ setTimeout(done);
+ });
+
+ afterEach((done) => {
+ ReactDOM.unmountComponentAtNode(document.getElementById('container'));
+ document.body.innerHTML = '';
+ setTimeout(done);
+ });
+
+ it('renders upload card with defaults', () => {
+ ReactDOM.render(, document.getElementById('container'));
+ const uploadCard = document.querySelector(
+ '.gn-upload-card'
+ );
+ expect(uploadCard).toExist();
+ });
+
+ it('renders error card', () => {
+ ReactDOM.render(, document.getElementById('container'));
+ const uploadCard = document.querySelector(
+ '.gn-upload-card-error-message'
+ );
+ expect(uploadCard).toExist();
+ });
+});
diff --git a/geonode_mapstore_client/client/js/routes/upload/UploadCard.jsx b/geonode_mapstore_client/client/js/routes/upload/UploadCard.jsx
index faf7404358..725af54627 100644
--- a/geonode_mapstore_client/client/js/routes/upload/UploadCard.jsx
+++ b/geonode_mapstore_client/client/js/routes/upload/UploadCard.jsx
@@ -39,7 +39,7 @@ function UploadCard({
type
}) {
- const { datasetMaxUploadSize, documentMaxUploadSize, maxParallelUploads } = getConfigProp('geoNodeSettings');
+ const { datasetMaxUploadSize, documentMaxUploadSize, maxParallelUploads } = getConfigProp('geoNodeSettings') || {};
const maxAllowedBytes = type !== 'document' ? datasetMaxUploadSize : documentMaxUploadSize;
const maxAllowedSize = Math.floor(maxAllowedBytes / (1024 * 1024));
@@ -89,7 +89,7 @@ function UploadCard({
: null}
{state === 'INVALID'
- ? } />
+ ? } />
: null}
@@ -113,4 +113,11 @@ function UploadCard({
);
}
+UploadCard.defaultProps = {
+ name: '',
+ state: '',
+ progress: 0,
+ type: 'document'
+};
+
export default UploadCard;
diff --git a/geonode_mapstore_client/client/js/selectors/__tests__/search-test.js b/geonode_mapstore_client/client/js/selectors/__tests__/search-test.js
new file mode 100644
index 0000000000..aecf19ff74
--- /dev/null
+++ b/geonode_mapstore_client/client/js/selectors/__tests__/search-test.js
@@ -0,0 +1,55 @@
+/*
+ * 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 expect from 'expect';
+import { getSearchResults, getFeaturedResults, getTotalResources } from '../search';
+
+describe('Search selectors tests', () => {
+
+ it('should getSearchResults', () => {
+ const testState = {
+ resourceservice: {
+ processes: [{ resource: { pk: 1 }, processType: 'deleteResource', output: { status: 'finished' }, completed: true }]
+ },
+ gnsearch: {
+ resources: [{ pk: 1, processed: true }, { pk: 2 }]
+ }
+ };
+ expect(getSearchResults(testState)).toEqual([{ pk: 2 }]);
+ });
+
+ it('should getFeaturedResults', () => {
+ const testState = {
+ resourceservice: {
+ processes: [{ resource: { pk: 1 }, processType: 'deleteResource', output: { status: 'finished' }, completed: true }]
+ },
+ gnsearch: {
+ featuredResources: {
+ resources: [{ pk: 1, processed: true }, { pk: 2 }]
+ }
+ }
+ };
+ expect(getFeaturedResults(testState)).toEqual([{ pk: 2 }]);
+ });
+
+ it('should getTotalResources', () => {
+ const testState = {
+ resourceservice: {
+ processes: [{ resource: { pk: 1 }, processType: 'deleteResource', output: { status: 'finished' }, completed: true }]
+ },
+ gnsearch: {
+ resources: [
+ { pk: 1, processed: true }, { pk: 2 }, {
+ pk: 3, '@temporary': true
+ }],
+ total: 1
+ }
+ };
+ expect(getTotalResources(testState)).toEqual(2);
+ });
+});
diff --git a/geonode_mapstore_client/client/js/selectors/search.js b/geonode_mapstore_client/client/js/selectors/search.js
index 05a38299f8..8aceef3c10 100644
--- a/geonode_mapstore_client/client/js/selectors/search.js
+++ b/geonode_mapstore_client/client/js/selectors/search.js
@@ -6,35 +6,37 @@
* LICENSE file in the root directory of this source tree.
*/
-import { getResourceStatuses } from '@js/utils/ResourceUtils';
+import { excludeDeletedResources } from '@js/utils/ResourceUtils';
export const getSearchResults = (state) => {
const resources = state?.gnsearch?.resources || [];
const processes = state?.resourceservice?.processes || [];
- return resources.map((resource) => {
+ const searchResources = resources.map((resource) => {
const resourceProcesses = processes.filter((process) => process?.resource?.pk === resource?.pk);
if (resourceProcesses.length > 0) {
return { ...resource, processes: resourceProcesses };
}
return resource;
});
+
+ return excludeDeletedResources(searchResources);
};
export const getFeaturedResults = (state) => {
const resources = state?.gnsearch?.featuredResources?.resources || [];
const processes = state?.resourceservice?.processes || [];
- return resources.map((resource) => {
+ const featuredResults = resources.map((resource) => {
const resourceProcesses = processes.filter((process) => process?.resource?.pk === resource?.pk);
if (resourceProcesses.length > 0) {
return { ...resource, processes: resourceProcesses };
}
return resource;
});
+ return excludeDeletedResources(featuredResults);
};
export const getTotalResources = (state) => {
const resources = getSearchResults(state);
- const deletedResourcesCount = resources.filter(resource => getResourceStatuses(resource).isDeleted).length;
const temporaryResourcesCount = resources.filter(resource => resource['@temporary']).length;
- return (state?.gnsearch?.total || 0) - deletedResourcesCount + temporaryResourcesCount;
+ return (state?.gnsearch?.total || 0) + temporaryResourcesCount;
};
diff --git a/geonode_mapstore_client/client/js/utils/ResourceUtils.js b/geonode_mapstore_client/client/js/utils/ResourceUtils.js
index 9376b057eb..dd4cd5abbc 100644
--- a/geonode_mapstore_client/client/js/utils/ResourceUtils.js
+++ b/geonode_mapstore_client/client/js/utils/ResourceUtils.js
@@ -587,3 +587,10 @@ export const canCopyResource = (resource, user) => {
const canCopy = resource?.is_copyable;
return (canAdd && canCopy) ? true : false;
};
+
+export const excludeDeletedResources = (suppliedResources) => {
+ return suppliedResources.filter((resource) => {
+ const { isDeleted } = getResourceStatuses(resource);
+ return !isDeleted && resource;
+ });
+};
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 20c34d27ea..9930544e7e 100644
--- a/geonode_mapstore_client/client/js/utils/__tests__/ResourceUtils-test.js
+++ b/geonode_mapstore_client/client/js/utils/__tests__/ResourceUtils-test.js
@@ -18,7 +18,8 @@ import {
compareBackgroundLayers,
toMapStoreMapConfig,
parseStyleName,
- canCopyResource
+ canCopyResource,
+ excludeDeletedResources
} from '../ResourceUtils';
describe('Test Resource Utils', () => {
@@ -423,4 +424,11 @@ describe('Test Resource Utils', () => {
expect(canCopyResource(resource, user)).toEqual(true);
});
+
+ it('should test excludeDeletedResources', () => {
+ const resources = [{ name: 'test-1', processes: [{ processType: 'deleteResource', output: { status: 'finished' } }] },
+ { name: 'test-2' }];
+
+ expect(excludeDeletedResources(resources)).toEqual([{ name: 'test-2' }]);
+ });
});