Skip to content

Conversation

@anup39
Copy link
Member

@anup39 anup39 commented Nov 27, 2025

This PR add:

  • Documents Catalog Plugin

Remaining:

  • Filters to be applied for Documents Catalog.
  • Complete unit tests are remaining for this new plugin

Screenshots:
Image1:
Screenshot 2025-11-27 at 20 50 42

Image:2
Screenshot 2025-11-27 at 21 12 38

Image:3
Screenshot 2025-11-27 at 20 51 54

Image:4
Screenshot 2025-11-27 at 20 52 03

Image: 5

Screenshot 2025-11-28 at 13 53 18

@anup39 anup39 self-assigned this Nov 27, 2025
@anup39 anup39 added the enhancement New feature or request label Nov 27, 2025
@anup39 anup39 linked an issue Nov 27, 2025 that may be closed by this pull request
@gemini-code-assist
Copy link

Summary of Changes

Hello @anup39, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a significant new feature: the Documents Catalog Plugin. This plugin empowers users to discover and integrate various document types directly into their maps as interactive layers. The initial implementation provides core functionality for browsing and adding documents, enhancing the application's capability to visualize diverse geospatial and non-geospatial information. While the basic UI and data fetching are in place, future work will focus on completing advanced filtering capabilities and comprehensive unit testing.

Highlights

  • New Documents Catalog Plugin: Introduced a new 'Documents Catalog' plugin, allowing users to browse, select, and add documents as vector layers to the map. This enhances the application's ability to integrate various types of resources.
  • API Integration: Added a new getDocuments API function in geonode_mapstore_client/client/js/api/geonode/v2/index.js to fetch document resources from the backend, supporting search, pagination, and sorting.
  • UI Component: Developed DocumentsCompactCatalog.jsx, a new React component for displaying documents in a compact catalog view, featuring search input, infinite scroll, multi-selection, and placeholder filter UI elements.
  • Panel and Layout Management: Updated the gnresource.js epics to correctly manage the opening and closing of the new Documents Catalog panel alongside existing panels like Datasets Catalog and Annotations, and to adjust the map layout accordingly.
  • Document to Layer Conversion: Implemented utility functions in geonode_mapstore_client/client/js/plugins/DocumentsCatalog/utils/index.js to convert selected documents into a vector layer configuration, including feature properties, geometry (point representation), and a rich feature info template for display.
  • Map Save Filtering: Modified the mapSaveSelector to filter out temporary document layers (identified by IDs containing 'documents:') when saving a map, ensuring only persistent layers are stored.
  • Internationalization and Configuration: Added new translation keys across multiple languages for the Documents Catalog and updated localConfig.json to register and enable the new plugin within the application's UI.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

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

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 a new Documents Catalog Plugin, enabling users to browse documents and add them to the map as a new layer. The implementation is comprehensive, covering API integration, a new React component for the catalog UI, Redux epics for state management, and necessary configuration updates. While the overall structure is good, I've identified a critical security vulnerability related to potential Cross-Site Scripting (XSS) that must be addressed. Additionally, there are several opportunities for improvement in terms of code correctness, maintainability, and removing unused code. The PR description correctly notes that filter functionality and unit tests are still pending.

Comment on lines 111 to 116
<iframe
src="\${properties['embed_url']}"
style="width: 100%; height: 500px; border: 1px solid #ddd; border-radius: 4px;"
frameborder="0"
allowfullscreen>
</iframe>

Choose a reason for hiding this comment

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

critical

The featureInfo template creates an iframe with its src attribute set directly from properties['embed_url']. If an attacker can control the embed_url of a document, they can inject a malicious page, leading to a stored Cross-Site Scripting (XSS) vulnerability. You must add the sandbox attribute to the iframe to mitigate this risk. For example: sandbox="allow-scripts allow-same-origin". Adjust the sandbox permissions based on the minimum required functionality for the embedded content.

Suggested change
<iframe
src="\${properties['embed_url']}"
style="width: 100%; height: 500px; border: 1px solid #ddd; border-radius: 4px;"
frameborder="0"
allowfullscreen>
</iframe>
<iframe
src="\${properties['embed_url']}"
style="width: 100%; height: 500px; border: 1px solid #ddd; border-radius: 4px;"
frameborder="0"
sandbox="allow-scripts allow-same-origin"
allowfullscreen>
</iframe>

Comment on lines 239 to 244
<InputControl
placeholder={placeholderId}
value={q}
debounceTime={300}
onChange={(value) => setQ(value)}
/>

Choose a reason for hiding this comment

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

high

The InputControl component's placeholder prop is being assigned placeholderId, which is a message ID string. This will display the ID itself (e.g., "gnviewer.resourcesCatalogFilterPlaceholder") instead of the translated message. You should use the localizedProps enhancer on InputControl or otherwise ensure the translated string is passed.

...(sort && { sort: isArray(sort) ? sort : [ sort ]}),
page,
page_size: pageSize,
// api_preset: API_PRESET.DOCUMENTS

Choose a reason for hiding this comment

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

medium

The api_preset: API_PRESET.DOCUMENTS is commented out. Is this intentional? If it's for future work, consider adding a // TODO: comment explaining why it's currently disabled. If it's no longer needed, it should be removed to avoid confusion.

Comment on lines 601 to 628
const oneOfTheOther = (control) => {
if (control === 'rightOverlay') return null;

// Handle three-way alternates
if (control === 'annotations') {
return {
control,
alternates: ['datasetsCatalog', 'documentsCatalog']
};
}
if (control === 'datasetsCatalog') {
return {
control,
alternates: ['annotations', 'documentsCatalog']
};
}
if (control === 'documentsCatalog') {
return {
control,
alternates: ['annotations', 'datasetsCatalog']
};
}

return {
control,
alternate: control === 'annotations' ? 'datasetsCatalog' : 'annotations'
alternates: []
};
};

Choose a reason for hiding this comment

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

medium

The oneOfTheOther function contains several repetitive if blocks. This can be refactored to be more concise and easier to maintain, especially if more panels are added in the future.

const oneOfTheOther = (control) => {
    if (control === 'rightOverlay') return null;
    const panels = ['annotations', 'datasetsCatalog', 'documentsCatalog'];
    if (panels.includes(control)) {
        return {
            control,
            alternates: panels.filter(p => p !== control)
        };
    }
    return {
        control,
        alternates: []
    };
};

* LICENSE file in the root directory of this source tree.
*/

import React, { useRef, useState, useEffect, Component } from 'react';

Choose a reason for hiding this comment

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

medium

The Component is imported from React but is not used in this functional component. It should be removed to keep the imports clean.

Suggested change
import React, { useRef, useState, useEffect, Component } from 'react';
import React, { useRef, useState, useEffect } from 'react';

Comment on lines +289 to +301
style={{
position: 'absolute',
top: '10px',
left: '10px',
zIndex: 10,
backgroundColor: 'white',
borderRadius: '4px',
padding: '4px',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
boxShadow: '0 2px 4px rgba(0,0,0,0.1)'
}}

Choose a reason for hiding this comment

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

medium

There are several inline styles applied to this div. It's better to move these styles to a LESS file (e.g., _resources-catalog.less) to improve maintainability and allow for easier theming. You could create a new class like .gn-resources-catalog-item-checkbox and move the styles there.

Comment on lines 360 to 371
DocumentsCompactCatalog.propTypes = {
request: PropTypes.func,
responseToEntries: PropTypes.func,
pageSize: PropTypes.number,
placeholderId: PropTypes.string,
addSearchAsLayer: PropTypes.string,
selectAll: PropTypes.string,
onClose: PropTypes.func,
onSelect: PropTypes.func,
titleId: PropTypes.string,
noResultId: PropTypes.string
};

Choose a reason for hiding this comment

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

medium

The component is missing propTypes validation for style, loading (as resourceLoading), and params. Please add them for better component contract and debugging.

DocumentsCompactCatalog.propTypes = {
    // ... existing propTypes
    style: PropTypes.object,
    loading: PropTypes.bool,
    params: PropTypes.object
    // ...
};

Comment on lines 27 to 33
function DocumentsCatalog({
onAdd,
onUpdate,
onZoomTo,
existingLayers,
...props
}) {

Choose a reason for hiding this comment

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

medium

The DocumentsCatalog component receives onUpdate and existingLayers as props, but they are not used within the component. If they are not needed, they should be removed from the component's props and from the connect call to avoid passing down unused properties.

const unId= uuid();

return Promise.all(documentPromises).then(fullDocs => {
const extendedParams = {};

Choose a reason for hiding this comment

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

medium

The extendedParams variable is initialized as an empty object and passed to the layer configuration, but it's never modified. It appears to be unused and should be removed.

@anup39 anup39 requested a review from allyoucanmap November 27, 2025 15:36
Copy link
Collaborator

@allyoucanmap allyoucanmap left a comment

Choose a reason for hiding this comment

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

Review for the UI:

image image
  • lets use a simple checkbox
image

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

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implementation of new documents catalog plugin.

2 participants