Skip to content

Feature/publish data collection#2591

Closed
mwallschlaeger wants to merge 241 commits into
GeoNode:masterfrom
zalf-rdm:feature/publish-data-collection
Closed

Feature/publish data collection#2591
mwallschlaeger wants to merge 241 commits into
GeoNode:masterfrom
zalf-rdm:feature/publish-data-collection

Conversation

@mwallschlaeger

Copy link
Copy Markdown
Member

No description provided.

allyoucanmap and others added 30 commits September 20, 2024 18:37
)

* updates to improve templates customizations

* review delete redirect

(cherry picked from commit 6533619)

Co-authored-by: stefano bovio <stefano.bovio@geosolutionsgroup.com>
Co-authored-by: allyoucanmap <allyoucanmap@users.noreply.github.com>
(cherry picked from commit bab3b5b)

Co-authored-by: stefano bovio <stefano.bovio@geosolutionsgroup.com>
Co-authored-by: giohappy <giohappy@users.noreply.github.com>
Co-authored-by: giohappy <giohappy@users.noreply.github.com>
* Update 4.4.x MS submodule to release 2024.02.xx

* update module
Co-authored-by: giohappy <giohappy@users.noreply.github.com>
…) (GeoNode#1917)

* Added table of content to open layer details in map view. Fixes issue#1660.

* Updated to the newer version.

* Code refactor

* Fixed instability issues for info button on TOC.

* Fixed linked resources for info button on TOC and code cleanup.

* Avoided repeating calls to get layer dataset fields including linked resources for info button on TOC.

* Fixed localConfig json file for the info button.

* Reverted api changes to include linked resources, because they are already included for 'viewer_common' api_preset.

* Fixed getDatasetByPk definition.

* Fixed linting issues.

* Fixed bug where info button was misbehaving when any maplayer had no dataset.

* Fixed a bug where the title of the dataset was not changing on the details panel.

---------

Co-authored-by: Suren <dsuren1@gmail.com>
(cherry picked from commit 9b1dcb4)

Co-authored-by: ahmdthr <116570171+ahmdthr@users.noreply.github.com>
Co-authored-by: giohappy <giohappy@users.noreply.github.com>
…eoNode#1924)

(cherry picked from commit d05f04a)

Co-authored-by: Suren <dsuren1@gmail.com>
Co-authored-by: allyoucanmap <allyoucanmap@users.noreply.github.com>
…eoNode#1932)

(cherry picked from commit 9e79006)

Co-authored-by: Suren <dsuren1@gmail.com>
Co-authored-by: allyoucanmap <allyoucanmap@users.noreply.github.com>
Co-authored-by: allyoucanmap <allyoucanmap@users.noreply.github.com>
…GeoNode#1942) (GeoNode#1950)

(cherry picked from commit a9f2cfd)

Co-authored-by: Suren <dsuren1@gmail.com>
…eoNode#1953)

(cherry picked from commit 89a25af)

Co-authored-by: Suren <dsuren1@gmail.com>
…1955)

(cherry picked from commit 089c557)

Co-authored-by: Gleb Kilichenko <149377579+kilichenko-pixida@users.noreply.github.com>
Co-authored-by: giohappy <giohappy@users.noreply.github.com>
silvadealmeida and others added 28 commits January 7, 2026 09:49
…n.jsx

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
…/geonode-mapstore-client into feature/publish-data-collection

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces support for tabular datasets and tabular collections in the GeoNode MapStore client by adding new routes, components, and plugins (such as TabularPreview, TabularCollectionViewer, ApproveDataCollection, PublishDataCollection, and Footer), and integrating DataCite publishing configurations. It also refactors the card grid container layout to use CSS container queries instead of react-resize-detector. The review feedback highlights several critical areas for improvement, primarily focusing on preventing potential TypeError and AttributeError crashes through optional chaining and safety guards when handling potentially null or undefined resources, layers, or user objects. Additionally, the feedback points out a test suite failure caused by commented-out configuration items, recommends replacing HTML 'class' attributes with React's 'className' in the new Footer component, suggests URL query parameter handling improvements in ShareEmbedLink, and advises cleaning up unused props and speculative comments.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

(state) => state?.gnsettings?.geoserverUrl,
(state) => state?.gnresource?.data
], (geoserverUrl, resource) => {
if (!resource.subtype || !geoserverUrl) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

If resource is null or undefined, accessing resource.subtype will throw a TypeError. Please use optional chaining to safely access subtype.

Suggested change
if (!resource.subtype || !geoserverUrl) {
if (!resource?.subtype || !geoserverUrl) {

Comment on lines +16 to +32
function headerFromFeatures(data) {
const feature = data.features[0] || []
const properties = feature.properties;
return Object.keys(properties).map((p, index) => ({ value: p, key: propertyToKey(p, index) }));
};

function rowsFromFeatures(data) {
const features = data.features || []
// [{col1: "value"}]
return features.map((feature, index) => {
const row = {}
const properties = feature.properties
Object.keys(properties)
.forEach(name => Object.assign(row, { [propertyToKey(name, index)]: properties[name] }))
return row;
});
};

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

If data is undefined, or data.features is empty, or feature.properties is undefined, both headerFromFeatures and rowsFromFeatures will throw a TypeError when calling Object.keys(properties). Please add safety guards and default values to prevent these crashes.

Suggested change
function headerFromFeatures(data) {
const feature = data.features[0] || []
const properties = feature.properties;
return Object.keys(properties).map((p, index) => ({ value: p, key: propertyToKey(p, index) }));
};
function rowsFromFeatures(data) {
const features = data.features || []
// [{col1: "value"}]
return features.map((feature, index) => {
const row = {}
const properties = feature.properties
Object.keys(properties)
.forEach(name => Object.assign(row, { [propertyToKey(name, index)]: properties[name] }))
return row;
});
};
function headerFromFeatures(data) {
const feature = data?.features?.[0];
const properties = feature?.properties || {};
return Object.keys(properties).map((p, index) => ({ value: p, key: propertyToKey(p, index) }));
};
function rowsFromFeatures(data) {
const features = data?.features || [];
// [{col1: "value"}]
return features.map((feature, index) => {
const row = {};
const properties = feature?.properties || {};
Object.keys(properties)
.forEach(name => Object.assign(row, { [propertyToKey(name, index)]: properties[name] }));
return row;
});
};

Comment on lines 38 to +41
setTextValue(evt.target.value);
onEdit(evt.target.value);
}}
value={textValue}
value={onEdit ? textValue : title}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

If onEdit is not provided (which is possible since value conditionally checks onEdit ? textValue : title), typing in the input will throw a TypeError: onEdit is not a function because it is called unconditionally in onChange. Please add a guard check before calling onEdit.

                    setTextValue(evt.target.value);
                    if (onEdit) {
                        onEdit(evt.target.value);
                    }
                }}
                value={onEdit ? textValue : title}

Comment on lines +237 to +239
...(sourcetype === SOURCE_TYPES.REMOTE && !wmsUrl.includes('/geoserver/') && {
serverType: ServerTypes.NO_VENDOR
})

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

If wmsUrl is undefined, calling wmsUrl.includes('/geoserver/') will throw a TypeError. Please add a check to ensure wmsUrl is defined before calling includes.

Suggested change
...(sourcetype === SOURCE_TYPES.REMOTE && !wmsUrl.includes('/geoserver/') && {
serverType: ServerTypes.NO_VENDOR
})
...(sourcetype === SOURCE_TYPES.REMOTE && wmsUrl && !wmsUrl.includes('/geoserver/') && {
serverType: ServerTypes.NO_VENDOR
})

Comment on lines +32 to +34
const ApproveDataCollectionComponent = (props) => {
const { open, onClose, style=DEFAULT_DIALOG_STYLE, closeGlyph, dispatch } = props;
const { title, owner } = props.resourceData;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

If props.resourceData is null or undefined, destructuring title and owner will throw a TypeError. Additionally, owner.pk on line 44 can crash if owner is null. Please add a safety guard to return null if resourceData is not available, and use optional chaining for owner?.pk.

Suggested change
const ApproveDataCollectionComponent = (props) => {
const { open, onClose, style=DEFAULT_DIALOG_STYLE, closeGlyph, dispatch } = props;
const { title, owner } = props.resourceData;
const ApproveDataCollectionComponent = (props) => {
const { open, onClose, style=DEFAULT_DIALOG_STYLE, closeGlyph, dispatch } = props;
if (!props.resourceData) {
return null;
}
const { title, owner } = props.resourceData;

Comment on lines +54 to +63
<Cards
featured
resources={resources}
formatHref={formatHref}
isCardActive={isCardActive}
buildHrefByTemplate={buildHrefByTemplate}
containerWidth={width}
downloading={downloading}
getDetailHref={getDetailHref}
/>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The Cards component no longer accepts or uses the containerWidth prop. You should remove containerWidth={width} from the <Cards /> component. Additionally, since width is no longer used anywhere else in FeaturedList, you can remove the width prop and the withResizeDetector wrapper from FeaturedList entirely to clean up the code.

Suggested change
<Cards
featured
resources={resources}
formatHref={formatHref}
isCardActive={isCardActive}
buildHrefByTemplate={buildHrefByTemplate}
containerWidth={width}
downloading={downloading}
getDetailHref={getDetailHref}
/>
<Cards
featured
resources={resources}
formatHref={formatHref}
isCardActive={isCardActive}
buildHrefByTemplate={buildHrefByTemplate}
downloading={downloading}
getDetailHref={getDetailHref}
/>


/* this function adds plugin based on the current query, used mainly for embed pages*/
export const addQueryPlugins = (pluginsConfig, query) => {
if (isArray(pluginsConfig)) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using Array.isArray is safer and standard, as it does not rely on any external imports (like lodash's isArray) and avoids potential ReferenceError if the import is missing.

Suggested change
if (isArray(pluginsConfig)) {
if (Array.isArray(pluginsConfig)) {

Comment on lines +20 to +61
<nav class="col-6 col-md-6 col-lg-3" aria-label="Quick Links">
<h3 class="fs-5 fw-bold mb-3 text-light">Quick Links</h3>
<ul class="list-unstyled fs-6 fw-normal m-0">
<li class="mb-2">
<a href="/about" class="link-light text-decoration-none">About</a>
</li>
<li class="mb-2">
<a href="/upload" class="link-light text-decoration-none">Upload</a>
</li>
<li class="mb-2">
<a href="/ogc_and_api" class="link-light text-decoration-none">OGC Services and API</a>
</li>
<li class="mb-2">
<a href="https://www.zalf.de/en/struktur/cdp/fdm/Pages/default.aspx" class="link-light text-decoration-none">Research Data Management</a>
</li>
</ul>
</nav>




{/* Resources */}
<nav class="col-6 col-md-6 col-lg-3" aria-label="Resources">
<h3 class="fs-5 fw-bold mb-3 text-light">Resources</h3>
<ul class="list-unstyled fs-6 fw-normal m-0">
<li class="mb-2">
<a href="/publications" class="link-light">Publications</a>
</li>
<li class="mb-2">
<a href="/data_policy" class="link-light">Data Policy</a>
</li>
<li class="mb-2">
<a href="/how_to_cite" class="link-light">How to Cite Us</a>
</li>
<li class="mb-2">
<a href="/imprint" class="link-light">Imprint</a>
</li>
<li class="mb-2">
<a href="/privacy" class="link-light">Privacy</a>
</li>
</ul>
</nav>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

In React, you must use className instead of class for styling elements. Using class will trigger console warnings and may prevent styles from being applied correctly. Please replace all occurrences of class with className in this file.

                    <nav className="col-6 col-md-6 col-lg-3" aria-label="Quick Links">
                        <h3 className="fs-5 fw-bold mb-3 text-light">Quick Links</h3>
                        <ul className="list-unstyled fs-6 fw-normal m-0">
                            <li className="mb-2">
                                <a href="/about" className="link-light text-decoration-none">About</a>
                            </li>
                            <li className="mb-2">
                                <a href="/upload" className="link-light text-decoration-none">Upload</a>
                            </li>
                            <li className="mb-2">
                                <a href="/ogc_and_api" className="link-light text-decoration-none">OGC Services and API</a>
                            </li>
                            <li className="mb-2">
                                <a href="https://www.zalf.de/en/struktur/cdp/fdm/Pages/default.aspx" className="link-light text-decoration-none">Research Data Management</a>
                            </li>
                        </ul>
                    </nav>




                    {/* Resources */}
                    <nav className="col-6 col-md-6 col-lg-3" aria-label="Resources">
                        <h3 className="fs-5 fw-bold mb-3 text-light">Resources</h3>
                        <ul className="list-unstyled fs-6 fw-normal m-0">
                            <li className="mb-2">
                                <a href="/publications" className="link-light">Publications</a>
                            </li>
                            <li className="mb-2">
                                <a href="/data_policy" className="link-light">Data Policy</a>
                            </li>
                            <li className="mb-2">
                                <a href="/how_to_cite" className="link-light">How to Cite Us</a>
                            </li>
                            <li className="mb-2">
                                <a href="/imprint" className="link-light">Imprint</a>
                            </li>
                            <li className="mb-2">
                                <a href="/privacy" className="link-light">Privacy</a>
                            </li>
                        </ul>
                    </nav>

: resource.resource_type === ResourceTypes.DATASET
&& ![GXP_PTYPES.REST_IMG, GXP_PTYPES.REST_MAP].includes(resource.ptype)
&& isDefaultDatasetSubtype(resource.subtype)
&& resource.subtype !== "tabular" // obsolete by above line?!

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Please remove the speculative comment // obsolete by above line?! to keep the codebase clean and maintainable.

Suggested change
&& resource.subtype !== "tabular" // obsolete by above line?!
&& resource.subtype !== "tabular"

if user is None or not user.is_authenticated:
return {"can_publish": False, "prefixes": []}

can_publish = user.can_publish_data_collection()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

To prevent potential AttributeError crashes (e.g., in environments or tests where the custom user model or monkey-patching is not fully loaded), please check if the can_publish_data_collection attribute exists on the user object before calling it.

Suggested change
can_publish = user.can_publish_data_collection()
can_publish = hasattr(user, "can_publish_data_collection") and user.can_publish_data_collection()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants