Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide geonode-mapstore-client package #1546

Open
ridoo opened this issue Sep 4, 2023 · 9 comments
Open

Provide geonode-mapstore-client package #1546

ridoo opened this issue Sep 4, 2023 · 9 comments
Labels
enhancement New feature or request

Comments

@ridoo
Copy link

ridoo commented Sep 4, 2023

npmjs does not list a (to be fair a very outdated) version of the geonode-mapstore-client. I understand that this repository is actually a python contrib app which provides single page UI (based on MapStore) as compiled static assets. However, the problem is, that there is no way* to add geonode-mapstore-client as JS dependency so that I import and re-use its modules.

(* of course I could link to a local working copy of geonode-mapstore-client, but this is not the idea how this should actually work, right?)

However, my plan is to extend existing plugins (i.e. DetailsViewer) and adjust localConfig.json to make my own changes which I can ship with another contrib module. This contrib module adds a new resource type which I want to configure on the UI side. Before, I had to make my adjustments in a geonode-mapstore-client fork, but now I want to challenge the stack (geonode => geonode-mapstore-client => contrib module) to ship the UI changes within the contrib module itself.

For more context, look here: geosolutions-it/MapStore2#9354

Expected Behavior

npm install @geonode/geonode-mapstore-client or the like works.

Other things I tried

Trying to npm install 'https://gitpkg.now.sh/geonode/geonode-mapstore-client/geonode_mapstore_client/client?4.1.1' runs into a gateway error. The repository is so big (due to the compiled JS assets), it becomes quite unhandy.

@ridoo
Copy link
Author

ridoo commented Sep 12, 2023

Regarding this issue I think it is worth to note, that the size of this repository has grown huge (around 1GB! already).

Probably, this is due to the fact, that this repo represents actually a Django app which ships all static files, i.e. the compiled JS assets. However, as the geonode_mapstore_client is installed from git repository anyway, it may become faster (depending on the fast your network is) to compile all JavaScript resource when GeoNode base image is being built.

@ridoo
Copy link
Author

ridoo commented Mar 14, 2024

Is there any advice how to deal with this problem? @mattiagiupponi is this a current limitation, that we cannot implement extensions/plugins separate from the geonode-mapstore-plugin, i.e. code laying somewhere else? Do you have any idea how to approach this? Otherwise I would have to fork the whole repository just for some simple plugins.

What I want to do is to separate plugin development:

  • use mapstore-project create extension
  • start development a plugin by re-using components of geonode-mapstore-client (e.g. Button)
  • add index.json to /static/mapstore/ which declares to load js from local dev server (started by npm start)
  • adding the plugin via _geonode_config.html (for example dataset_viewer.cfg)

The default extension (from the template) loads ok and I can see the message. However, importing common components (like the Button) I get compiler errors like this (in the Browser's development console):

Error loading MapStore extension "MyPlugin": Error: Cannot find module '@js/components/Button'

And this from the npm start output:

ERROR in ./js/extension/plugins/Extension.jsx 31:0-163
Module not found: Error: Can't resolve '@js/selectors/resource' in '/home/ridoo/data/coding/projects/plasticops/geonode-plasticops/geonode/apps/litter_assessment/client/js/extension/plugins'
 @ container entry ./plugin[0]

@giohappy
Copy link

giohappy commented Mar 14, 2024

hi @ridoo, @allyoucanmap could answer your questions.
At the moment there isn't an "official" way. We have experimented with various alternatives.
The latest one was building a MapStore Extensions.

In general, what we did was to develop and build an extension (with MapStore as the only dependency) with the mapstore-project compile extension command, place it under the geonode-project/tree/master/src/project_name/static/mapstore/extensions path, and configure it inside the index.json file, which is the index of the available MapStore extensions.

Extensions is the approach that we will continue to pursue since it also goes in the direction of uploading and configuring extensions at runtime. MapStore already supports this with the Application Contexts. The GeoNode client will soon have them, along with an updated version of MapStore itself. The development is at a good point. What will remain to be done is implementing the backend in GeoNode to support the upload of the extensions.

@ridoo
Copy link
Author

ridoo commented Mar 14, 2024

@giohappy That sound good. I saw @dsuren1 is working on that, right? To me uploading plugins is not important. I just want to implement plugins/extensions re-using stuff from geonode-mapstore-client without placing everything inside a whole fork. Would this even be possible with Application Contexts and do you have a plan, when it becomes usable?

At the moment there isn't an "official" way. We have experimented with various alternatives.
The latest one was building a MapStore Extensions.

In fact, this is what I am trying to do. The challenge is to get the geonode-mapstore-client imports right. What I tried to describe is, that there's no good dependency for the extension's package.json from where I can import. The build (prod and dev) complain about the missing imports.

However, I tried some things. For example, I linked the geonode-mapstore-client project into my node_modules folder and added the path to webpack's aliases, making @js map to multiple paths:

alias: {
    "@mapstore/framework": projectConfig.frameworkPath,
    "@js": [
        path.resolve(appDirectory, "node_modules/geonode-mapstore-client/js"),
        path.resolve(appDirectory, "js")
    ]
}

Maybe the mapstore-project could be made more flexible with regard passing some webpack overrides from the extension's package.json scripts (@offtherailz @afabiani what do you think?). But, for no surprise, the build includes all the geonode-mapstore-client code and results in an Extension/index.js which is around half a Mega-byte.

Another hack was to comment out the cesium/index.css import in Map.jsx as it raised another error. I saw, the imports are different in master but this would result in a similar error, I guess.

All these are quite hacky try-arounds. If you do not see any other option, I fear, forking geonode-mapstore-client is the way I have to go.

@giohappy
Copy link

@allyoucanmap will probably be able to give some feedback and guidance on this.
In one of our activities we configured the following package.json, but I'm not sure if it would work for you.

{
  "name": "client",
  "version": "1.0.0",
  "description": "mapstore extension",
  "eslintConfig": {
    "extends": [
      "@mapstore/eslint-config-mapstore"
    ],
    "parserOptions": {
      "babelOptions": {
        "configFile": "./node_modules/mapstore/build/babel.config.js"
      }
    },
    "globals": {
      "__MAPSTORE_PROJECT_CONFIG__": false,
      "__MAPSTORE_EXTENSION_CONFIG__": false
    }
  },
  "browserslist": {
    "production": [
      ">0.5%",
      "not dead",
      "not op_mini all",
      "not IE 11",
      "not UCAndroid 12.12"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  },
  "scripts": {
    "compile": "mapstore-project compile extension && node ./postCompile.js",
    "lint": "eslint js --ext .jsx,.js",
    "start": "mapstore-project start extension",
    "test": "mapstore-project test extension",
    "test:watch": "mapstore-project test:watch extension"
  },
  "devDependencies": {
    "@mapstore/project": "1.0.22"
  },
  "dependencies": {
    "mapstore": "git+https://github.com/geosolutions-it/MapStore2.git#2022.01.xx"
  },
  "mapstore": {
    "extensionName": "EmpiricalEquationCalculator"
  }
}

ridoo added a commit to 52North/geonode-plasticops that referenced this issue Mar 15, 2024
See also GeoNode/geonode-mapstore-client#1546

Need to link local geonode-mapstore-client and add the path to webpack's `@js` alias mapping within the geonode-project.

See the limitations in my comment GeoNode/geonode-mapstore-client#1546 (comment)
ridoo added a commit to 52North/geonode-plasticops that referenced this issue Apr 3, 2024
See also GeoNode/geonode-mapstore-client#1546

Need to link local geonode-mapstore-client and add the path to webpack's `@js` alias mapping within the geonode-project.

See the limitations in my comment GeoNode/geonode-mapstore-client#1546 (comment)
@ridoo
Copy link
Author

ridoo commented Apr 4, 2024

@giohappy @allyoucanmap In fact, this is exactly what I am doing. However, with this I am only able to create the MapStore extension. But how to integrate the extension with geonode-mapstore-client (components, state, etc.)? For example, a simple button in the dataset_view which triggers some kind of action based on the shown resource.

As described, I have tried to push the limits but it seems that I have to create another fork for such a simple extension/plugin. Am I wrong here?

FWIW is to have some importable geonode-mapstore-client API which I can use to seemlessly implement plugins for geonode-mapstore-client. As far I can see, having just a mere MapStore plugin fells short if you want to (re-)use components and state of the geonode-mapstore-client.

I guess, this is not an easy task and would need deeper thoughts how to make this possible.

Edit: I added the enhancement label an did minor edits on the description (e.g. removed the bug title)

@ridoo ridoo added the enhancement New feature or request label Apr 4, 2024
@giohappy
Copy link

giohappy commented Apr 4, 2024

We will need ideas from @allyoucanmap here :)

@allyoucanmap
Copy link
Collaborator

allyoucanmap commented Apr 4, 2024

@ridoo @giohappy

But how to integrate the extension with geonode-mapstore-client (components, state, etc.)? For example, a simple button in the dataset_view which triggers some kind of action based on the shown resource.

We have some training documentation where it's described how to include a mapstore extension inside geonode-mapstore-client. The approach described in the training doc does not allow to access directly the custom modules/components from the geonode-mapstore-client but it allows to interact with the geonode-mapstore-client state and inject components inside pages.
We could think on a way to package/expose only the specific modules/methods of the geonode-mapstore-client project such as actions, api and selectors. I'm not sure about the component yet, probably for the most common ones it could be better to port them in the mapstore core and remove from geonode-mapstore-client.

@ridoo
Copy link
Author

ridoo commented Apr 4, 2024

... but it allows to interact with the geonode-mapstore-client state and inject components inside pages.

Interesting. Still limited, but may be enough for my simple case. Do you have a simple example, how to interact with the state inside the extension?

We could think on a way to package/expose only the specific modules/methods of the geonode-mapstore-client project such as actions, api and selectors. I'm not sure about the component yet, probably for the most common ones it could be better to port them in the mapstore core and remove from geonode-mapstore-client.

To be honest, I did not expect you are thinking of making geonode-mapstore-client client part of the MapStore project itself. I always thought of it as an actual client implementation using the MapStore framework. Not sure, if moving everything to MapStore is convoluting the framework. Does MapStore organize code to separate framework from specific implementations?

However, if this would be possible, I think the geonode-mapstore-client repository could be thinned to contain the python integration only.

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

No branches or pull requests

3 participants