@indiscale/linkahead-webui-ext-map 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/.eslintrc.json +45 -0
  2. package/.gitlab-ci.yml +44 -0
  3. package/CHANGELOG.md +78 -0
  4. package/README.md +97 -0
  5. package/RELEASE_GUIDELINES.md +45 -0
  6. package/__mocks__/fileMock.js +3 -0
  7. package/__mocks__/styleMock.js +1 -0
  8. package/babel.config.js +22 -0
  9. package/cypress/e2e/standalone-map.cy.js +55 -0
  10. package/cypress/support/commands.js +25 -0
  11. package/cypress/support/e2e.js +17 -0
  12. package/cypress.config.js +10 -0
  13. package/dist/2b3e1faf89f94a483539.png +0 -0
  14. package/dist/416d91365b44e4b4f477.png +0 -0
  15. package/dist/8f2c4d11474275fbc161.png +0 -0
  16. package/dist/index.html +1 -0
  17. package/dist/linkahead-webui-ext-map.js +3 -0
  18. package/dist/linkahead-webui-ext-map.js.LICENSE.txt +45 -0
  19. package/dist/linkahead-webui-ext-map.js.map +1 -0
  20. package/iframe/index.html +6 -0
  21. package/indiscale-linkahead-webui-ext-map-0.4.1.tgz +0 -0
  22. package/jest.config.js +23 -0
  23. package/jest.setup.js +2 -0
  24. package/package.json +105 -0
  25. package/public/favicon.ico +0 -0
  26. package/public/index.html +11 -0
  27. package/public/logo192.png +0 -0
  28. package/public/logo512.png +0 -0
  29. package/public/manifest.json +25 -0
  30. package/public/map_tile_caosdb_logo.png +0 -0
  31. package/public/mock.js +41 -0
  32. package/public/robots.txt +3 -0
  33. package/select_query.json +3 -0
  34. package/src/AllMapEntities.tsx +294 -0
  35. package/src/CurrentPageEntities.js +318 -0
  36. package/src/Map.helpers.css +8 -0
  37. package/src/Map.helpers.js +536 -0
  38. package/src/Map.js +288 -0
  39. package/src/Map.test.js +252 -0
  40. package/src/MapConfig.js +75 -0
  41. package/src/__snapshots__/Map.test.js.snap +1725 -0
  42. package/src/components/Coordinates.js +24 -0
  43. package/src/components/ErrorComponent.tsx +2 -0
  44. package/src/components/Graticule.js +27 -0
  45. package/src/components/Loader.module.css +17 -0
  46. package/src/components/Loader.tsx +36 -0
  47. package/src/components/PathDropDown.js +108 -0
  48. package/src/components/SearchControl.js +502 -0
  49. package/src/components/ToggleMapButton.js +194 -0
  50. package/src/components/ViewChangeControl.js +104 -0
  51. package/src/constants/index.js +1 -0
  52. package/src/context/ConfigProvider.test.js +232 -0
  53. package/src/context/ConfigProvider.tsx +189 -0
  54. package/src/context/LoadingProvider.test.js +124 -0
  55. package/src/context/LoadingProvider.tsx +117 -0
  56. package/src/context/PathIdProvider.js +102 -0
  57. package/src/contrib/latlnggraticule/LICENSE +20 -0
  58. package/src/contrib/latlnggraticule/README.md +68 -0
  59. package/src/contrib/latlnggraticule/leaflet.latlng-graticule.js +528 -0
  60. package/src/contrib/simplegraticule/L.Graticule.js +138 -0
  61. package/src/default_config.json +57 -0
  62. package/src/global.d.ts +8 -0
  63. package/src/index.js +6 -0
  64. package/src/index.scss +133 -0
  65. package/src/logging.js +7 -0
  66. package/src/renderHtmlTemplate.test.js +60 -0
  67. package/src/select-search.min.svg +1 -0
  68. package/src/select-search.svg +46 -0
  69. package/src/setupTests.js +5 -0
  70. package/src/utils/GenerateQueryString.js +200 -0
  71. package/src/utils/GenerateQueryString.test.js +304 -0
  72. package/src/utils/index.ts +3 -0
  73. package/standalone.config.js +5 -0
  74. package/static/map_tile_caosdb_logo.png +0 -0
  75. package/tsconfig.json +25 -0
  76. package/webpack.config.js +193 -0
package/.eslintrc.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "parser": "@babel/eslint-parser",
3
+ "env": {
4
+ "node": true,
5
+ "browser": true,
6
+ "es2021": true,
7
+ "jest/globals": true
8
+ },
9
+ "extends": [
10
+ "eslint:recommended",
11
+ "plugin:react/recommended",
12
+ "plugin:react-hooks/recommended",
13
+ "plugin:jsx-a11y/recommended"
14
+ ],
15
+ "parserOptions": {
16
+ "ecmaVersion": "latest",
17
+ "sourceType": "module",
18
+ "requireConfigFile": false
19
+ },
20
+ "ignorePatterns": ["*.scss", "**/*.test.js"],
21
+ "plugins": ["react", "jsx-a11y", "jest"],
22
+ "rules": {
23
+ "react/react-in-jsx-scope": "off",
24
+ "react/jsx-uses-react": "off"
25
+ },
26
+ "settings": {
27
+ "react": { "version": "detect" }
28
+ },
29
+ "overrides": [
30
+ {
31
+ "files": ["**/*.{ts,tsx}"],
32
+ "parser": "@typescript-eslint/parser",
33
+ "plugins": ["@typescript-eslint"],
34
+ "extends": ["plugin:@typescript-eslint/recommended"],
35
+ "rules": {
36
+ "@typescript-eslint/naming-convention": [
37
+ "error",
38
+ { "selector": "typeLike", "format": ["PascalCase"], "prefix": ["T"] }
39
+ ],
40
+ "react/prop-types": "off",
41
+ "@typescript-eslint/no-explicit-any": "off"
42
+ }
43
+ }
44
+ ]
45
+ }
package/.gitlab-ci.yml ADDED
@@ -0,0 +1,44 @@
1
+ default:
2
+ image: node:18
3
+ tags:
4
+ - docker
5
+
6
+ stages:
7
+ - build
8
+ - test
9
+
10
+ install:
11
+ stage: build
12
+ script:
13
+ - npm install --verbose
14
+ cache:
15
+ paths:
16
+ - node_modules/
17
+ artifacts:
18
+ expire_in: 1 days
19
+ when: on_success
20
+ paths:
21
+ - node_modules/
22
+
23
+ unittests:
24
+ stage: test
25
+ dependencies:
26
+ - install
27
+ script:
28
+ - npm test -- --coverage
29
+
30
+ linting:
31
+ stage: test
32
+ dependencies:
33
+ - install
34
+ script:
35
+ - npm run lint
36
+
37
+ audit:
38
+ stage: test
39
+ dependencies:
40
+ - install
41
+ script:
42
+ # Run audit and fail on vulnaribilities with high or critical severity, we
43
+ # accept moderate for now.
44
+ - npm audit --audit-level high
package/CHANGELOG.md ADDED
@@ -0,0 +1,78 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [0.5.0] - 2026-06-11
9
+
10
+ ### Changed
11
+
12
+ * Renamed to LinkAhead Ext Map
13
+
14
+ ## [0.4.0] - 2026-01-28
15
+
16
+ ### Added
17
+
18
+ - Loading Provider which shows spinner on layer change.
19
+ - The contents of the marker popup can now be configured for each select path by adding a config like
20
+
21
+ ```json
22
+ "entityPreview": {
23
+ "myPath": {
24
+ "query": "SELECT id, title, Publication year FROM Record WITH id = {id}",
25
+ "format": "<br><span><b>id: </b>{id}</span><span><b>title: </b>{title}</span><span><b>Publication year: </b>{Publication year}</span>"
26
+ }
27
+ }
28
+ ```
29
+
30
+ to your `ext_map.json` file where the `query` is executed for each pin upon clicking on the marker and the expressions in `{}` in the `format` string are replaced by the selector values.
31
+
32
+ - The preview also works in standalone mode when setting the preview path with the `iframeSettings.entityPreviewPath` variable (default is "same").
33
+ - Optional `default_view`, `zoom`, and `center` config keys to set default view, zoom, and center of standalone map independently from regular config
34
+
35
+ ### Changed
36
+
37
+ - Entity links now open in new tab for entities that are not on the same page as the current map view.
38
+ - Partial implementation of typescript.
39
+
40
+ ### Removed
41
+
42
+ - `tools/copy-map-into-webui.sh` Has been moved to a more generic helper script in linkahead-webui-legacy-adapter.
43
+
44
+ ### Fixed
45
+
46
+ - Environment variables are read-in correctly when running, e.g., `GRPC_API_URI="https://example.com" npm run build`
47
+ - Wrong CSS order in mock/standalone map which resulted in entity parent names being white on white background
48
+
49
+ ## [0.3.0] - 2025-09-15
50
+
51
+ ### Added
52
+
53
+ - Added query option so that in standalone mode, we can fetch and display the current page entities on the map i.e pins
54
+ using a query string which is produced using variables from the URL and a format string / template which we get from LinkAhead's map config `ext_map.json`.
55
+ - Updated npm run commands with dev options see README.md for details
56
+ - Added custom Spinner / Loader for the Map when loading pins and for when the stage before the map appears onscreen
57
+ - Added Cypress for End to End testing
58
+
59
+ ### Fixed
60
+
61
+ - [#257](https://gitlab.com/linkahead/linkahead-webui/-/issues/257) Fix to show spinner properly centred on the screen.
62
+
63
+ ## [0.2.0] - 2025-08-20
64
+
65
+ ### Added
66
+
67
+ - Added Standalone mode, whereby parts of the map can be hidden. e.g layers control, query search button and path switch.
68
+ - Added Script for MAC / Bash to automate the copying of the Map through the legacy-adapter, then into caosdb-webui and finally into the Docker container.
69
+
70
+ ### Fixed
71
+
72
+ - [https://gitlab.indiscale.com/caosdb/customers/leibniz-zmt/management/-/issues/265] Fix to hide map when entering Edit Mode. Also fixed that the map should show upon startup if in the config "show": true is set
73
+
74
+ ## [0.1.0]
75
+
76
+ ### Added
77
+
78
+ - Everything
package/README.md ADDED
@@ -0,0 +1,97 @@
1
+ # LinkAhead Webui Ext Map
2
+
3
+ Map extension for the CaosDB Webui based on Leaflet and React.
4
+
5
+ ## Available Scripts
6
+
7
+ In the project directory, you can run:
8
+
9
+ ### `npm run mock`
10
+
11
+ Runs the map in the development mode.\
12
+ Open [http://localhost:3000](http://localhost:3000) to view it in your browser.
13
+
14
+ The page will reload when you make changes.\
15
+ You may also see any lint errors in the console.
16
+
17
+ ### `npm run mock:standalone`
18
+
19
+ Shows the map component only configured in accordance with the standalone.config.js file in the root directory.
20
+
21
+ ### `npm run mock:dev:standalone`
22
+
23
+ As above but accesses Linkahead instance through defined URL in webpack.config.js
24
+
25
+ ### `npm run build:standalone`
26
+
27
+ Builds the map component configured in accordance with the standalone.config.js file in the root directory and without the toggle button.
28
+
29
+ ### `npm run build:dev:standalone`
30
+
31
+ As above but accesses Linkahead instance through defined URL in webpack.config.js
32
+
33
+ ### `npx serve -s dist -l 5000`
34
+
35
+ In order to test standalone iFrame
36
+
37
+ - Configure the /select_query.json file to have the appropriate format string
38
+ - Configure the src parameter in the Iframe - iframe/index.html - to be the url of the npx server and an appropriate query string
39
+ e.g http://localhost:5000?authorId=14104
40
+ - We support multiple and optional entries here if the FormatString is correctly specified e.g
41
+ `formatString: "SELECT id, name, parent, Event.latitude, Event.longitude FROM Dataset WITH AN authors=${authorId} [[ OR authors=${authorId} ]]",` Here we have one optional block so the authorId can be optionally included in the Url or not (and this supports multiple authorId's). The very first authorsId in the string is required ``[[ ]]` square brackets signify that this part is optional.
42
+ - To include multiple id's in the URL use as follows: http://localhost:5000?authorId=14104,1607,1908
43
+ - Run `npm run build:standalone` first, then the above npx command. This runs a web server of the built version of the standalone app.
44
+ - In the browser open ${YOUR_PATH_TO_THE \_CODE}/caosdb-webui-ext-map/iframe/index.html
45
+
46
+ ### `npm test`
47
+
48
+ Launches the test runner in the interactive watch mode.\
49
+ See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
50
+
51
+ ### `npm cypress`
52
+
53
+ Launches Cypress GUI. Info here from their website: https://docs.cypress.io/app/end-to-end-testing/testing-your-app
54
+
55
+ - Make sure `npm run build:dev:standalone` is running the app
56
+ - Open Cypress with above command
57
+ - To test select E2E Testing
58
+ - Select Test file which at the time of writing, only standalone-map is available
59
+
60
+ ### `npm cypress:run`
61
+
62
+ Runs all Cypress tests in commandline.
63
+
64
+ ### `npm cypress:cicd`
65
+
66
+ Command to run all Cypress tests in commandline when weburl is reachable and with addition of custom URL
67
+ e.g if Pipeline using Bash: URL=http://localhost:8082/?authorId=14104 npm run cypress:cicd
68
+
69
+ ### `npm run build`
70
+
71
+ Builds the app for production to the `build` folder.\
72
+ It correctly bundles React in production mode and optimizes the build for the best performance.
73
+
74
+ The build is minified and the filenames include the hashes.\
75
+ Your app is ready to be deployed!
76
+
77
+ See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
78
+
79
+ ### `npm run format`
80
+
81
+ Runs the formatter (prettier) on the `src/` directory.
82
+
83
+ ### `npm run lint`
84
+
85
+ Runs the linter (eslint) on the `src/` directory.
86
+
87
+ ### `npm run tsc`
88
+
89
+ Runs typescript test of all typescript files (excepting explicity ignored ones).
90
+
91
+ ## Deployment (with LinkAhead)
92
+
93
+ 1. Build the bundle in the react map repo with `npm run build`.
94
+ 2. Copy the build directory to `custom/caosdb-server/caosdb-webui/src/ext/include/reactmap`.
95
+ 3. Provide a `ext_map.json` under `custom/caosdb-server/caosdb-webui/conf/ext/json/ext_map.json`.
96
+ 4. Start linkahead with envoy enabled and with webui ref = `f-react-map`.
97
+ 5. Browse to localhost:8081. Optionally insert test data via `./misc/map_test_data.py`.
@@ -0,0 +1,45 @@
1
+ # Release guidelines for the CaosDB WebUI legacy adapter module
2
+
3
+ This document specifies release guidelines in addition to the general release
4
+ guidelines of the CaosDB Project
5
+ ([RELEASE_GUIDELINES.md](https://gitlab.com/caosdb/caosdb/blob/dev/RELEASE_GUIDELINES.md))
6
+
7
+ ## General Prerequisites
8
+
9
+ * All tests are passing.
10
+ * FEATURES.md is up-to-date and a public API is being declared in that document.
11
+ * CHANGELOG.md is up-to-date.
12
+ * dependencies in `package.json` are up-to-date.
13
+
14
+ ## Steps
15
+
16
+
17
+ 1. Create a release branch from the dev branch. This prevents further changes
18
+ to the code base and a never ending release process. Naming: `release-<VERSION>`
19
+
20
+ 2. Update CHANGELOG.md
21
+
22
+ 3. Check all general prerequisites.
23
+
24
+ 4. Update the version:
25
+ * The `version` variable in `package.json`
26
+
27
+ 5. Merge the release branch into the main branch.
28
+
29
+ 6. Tag the latest commit of the main branch with `v<VERSION>`.
30
+
31
+ 7. Delete the release branch.
32
+
33
+ 8. Publish the release by executing `npm publish` which uploads the caosdb
34
+ module to the node package repository [npmjs.com](https://www.npmjs.com).
35
+
36
+ 9. Merge the main branch back into the dev branch.
37
+
38
+ 10. After the merge of main to dev, start a new development version by
39
+ increasing at least the patch version of the `version` in
40
+ [package.json](./package.json) and preparing CHANGELOG.md by adding a new
41
+ "Unreleased" section on top.
42
+
43
+ 11. Create releases on gitlab.com and gitlab.indiscale.com that contain (at
44
+ least) the most recent section of the CHANGELOG as the description and link
45
+ to the NPM module.
@@ -0,0 +1,3 @@
1
+ // __mocks__/fileMock.js
2
+
3
+ module.exports = "test-file-stub";
@@ -0,0 +1 @@
1
+ module.exports = {};
@@ -0,0 +1,22 @@
1
+ // babel.config.js
2
+ module.exports = function (api) {
3
+ api.cache(true);
4
+
5
+ const presets = [
6
+ [
7
+ "@babel/preset-env",
8
+ {
9
+ targets: { node: "current" },
10
+
11
+ // IMPORTANT for Jest: transpile ESM -> CommonJS
12
+ modules: "commonjs",
13
+ },
14
+ ],
15
+ ["@babel/preset-react", { runtime: "automatic" }],
16
+ ["@babel/preset-typescript", { allExtensions: true, isTSX: true }],
17
+ ];
18
+
19
+ const plugins = [];
20
+
21
+ return { presets, plugins };
22
+ };
@@ -0,0 +1,55 @@
1
+ /// <reference types="cypress" />
2
+
3
+ const URL = "http://localhost:8082/?authorId=14104";
4
+
5
+ describe("Test standalone map", () => {
6
+ describe("fast checks (fresh visit each test)", () => {
7
+ beforeEach(() => {
8
+ cy.visit(URL);
9
+ });
10
+
11
+ it("displays loader initially while loading map", () => {
12
+ cy.get('[data-testid="mapLoader"]').should("exist");
13
+ });
14
+
15
+ it("loads Graticule Module", () => {
16
+ cy.window().then((win) => {
17
+ expect(win.L, "window.L exists").to.exist;
18
+ expect(win.L.latlngGraticule, "latlngGraticule registered").to.be.a(
19
+ "function"
20
+ );
21
+ });
22
+ });
23
+
24
+ it("displays map", () => {
25
+ cy.get(".leaflet-container").should("exist");
26
+ });
27
+
28
+ it("when map loads, loader appears while fetching pins", () => {
29
+ cy.get(".leaflet-container").should("exist");
30
+ cy.get('[data-testid="mapLoader"]').should("exist");
31
+ });
32
+ });
33
+
34
+ // Suite-level override (the only supported way)
35
+ // to stop upon each successive test that all state is re-rendered etc
36
+ describe(
37
+ "pins flow (reuse state from previous test)",
38
+ { testIsolation: false },
39
+ () => {
40
+ it("displays pins on map with query", () => {
41
+ cy.visit(URL);
42
+ cy.wait(20000);
43
+ cy.get('[data-testid="loader"]').should("not.exist");
44
+ cy.get(".leaflet-marker-icon").as("pins");
45
+ cy.get("@pins").should("have.length.greaterThan", 0);
46
+ });
47
+
48
+ it("click on pin shows popup (uses previous state)", () => {
49
+ // no visit here -> we reuse the same page/session from the previous test
50
+ cy.get(".leaflet-marker-icon").first().click({ force: true });
51
+ cy.get(".leaflet-popup-content-wrapper").should("exist");
52
+ });
53
+ }
54
+ );
55
+ });
@@ -0,0 +1,25 @@
1
+ // ***********************************************
2
+ // This example commands.js shows you how to
3
+ // create various custom commands and overwrite
4
+ // existing commands.
5
+ //
6
+ // For more comprehensive examples of custom
7
+ // commands please read more here:
8
+ // https://on.cypress.io/custom-commands
9
+ // ***********************************************
10
+ //
11
+ //
12
+ // -- This is a parent command --
13
+ // Cypress.Commands.add('login', (email, password) => { ... })
14
+ //
15
+ //
16
+ // -- This is a child command --
17
+ // Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
18
+ //
19
+ //
20
+ // -- This is a dual command --
21
+ // Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
22
+ //
23
+ //
24
+ // -- This will overwrite an existing command --
25
+ // Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
@@ -0,0 +1,17 @@
1
+ // ***********************************************************
2
+ // This example support/e2e.js is processed and
3
+ // loaded automatically before your test files.
4
+ //
5
+ // This is a great place to put global configuration and
6
+ // behavior that modifies Cypress.
7
+ //
8
+ // You can change the location of this file or turn off
9
+ // automatically serving support files with the
10
+ // 'supportFile' configuration option.
11
+ //
12
+ // You can read more here:
13
+ // https://on.cypress.io/configuration
14
+ // ***********************************************************
15
+
16
+ // Import commands.js using ES2015 syntax:
17
+ import './commands'
@@ -0,0 +1,10 @@
1
+ const { defineConfig } = require("cypress");
2
+
3
+ module.exports = defineConfig({
4
+ e2e: {
5
+ supportFile: "cypress/support/e2e.js",
6
+ setupNodeEvents(on, config) {
7
+ // implement node event listeners here
8
+ },
9
+ },
10
+ });
Binary file
Binary file
Binary file
@@ -0,0 +1 @@
1
+ <!doctype html><html lang="en"><head><meta charset="utf-8"/><script defer="defer" src="linkahead-webui-ext-map.js"></script></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="caosdb-f-map-panel"></div><div id="caosdb-f-toggle-map-button"></div></body></html>