@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
@@ -0,0 +1,6 @@
1
+ <iframe
2
+ src="http://localhost:5000/?authorId=14104"
3
+ style="width: 100%; height: 500px; border: 1px solid #ccc"
4
+ referrerpolicy="strict-origin-when-cross-origin"
5
+ sandbox="allow-scripts allow-popups allow-same-origin"
6
+ ></iframe>
package/jest.config.js ADDED
@@ -0,0 +1,23 @@
1
+ // jest.config.js
2
+ module.exports = {
3
+ testEnvironment: "jsdom",
4
+
5
+ transform: {
6
+ "^.+\\.(t|j)sx?$": "babel-jest",
7
+ },
8
+
9
+ moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json"],
10
+
11
+ moduleNameMapper: {
12
+ "\\.module\\.(css|sass|scss)$": "identity-obj-proxy",
13
+ "\\.(css|less|scss|sass)$": "identity-obj-proxy",
14
+ "^.+\\.svg$": "jest-svg-transformer",
15
+ },
16
+
17
+ // Let Babel transform these ESM deps from node_modules
18
+ transformIgnorePatterns: [
19
+ "/node_modules/(?!(react-leaflet|@react-leaflet|leaflet)/)",
20
+ ],
21
+
22
+ setupFilesAfterEnv: ["<rootDir>/jest.setup.js"],
23
+ };
package/jest.setup.js ADDED
@@ -0,0 +1,2 @@
1
+ import "@testing-library/jest-dom";
2
+ import "regenerator-runtime/runtime";
package/package.json ADDED
@@ -0,0 +1,105 @@
1
+ {
2
+ "name": "@indiscale/linkahead-webui-ext-map",
3
+ "homepage": "webinterface/reactmap",
4
+ "version": "0.5.0",
5
+ "author": "Timm Fitschen",
6
+ "license": "AGPL-3.0-or-later",
7
+ "main": "dist/linkahead-webui-ext-map.js",
8
+ "src": "src/index.js",
9
+ "peerDependencies": {
10
+ "bootstrap": "^5.3.0",
11
+ "bootstrap-icons": "^1.10.3",
12
+ "react": "^18.2.0",
13
+ "react-dom": "^18.2.0"
14
+ },
15
+ "dependencies": {
16
+ "@indiscale/linkahead-webui-core-components": "^0.4.3",
17
+ "@indiscale/linkahead-webui-entity-service": "^0.1.0",
18
+ "core-js": "^3.31.1",
19
+ "leaflet": "^1.9.3",
20
+ "leaflet-graticule": "^0.0.1",
21
+ "leaflet.coordinates": "^0.1.5",
22
+ "lodash": "^4.17.21",
23
+ "loglevel": "^1.8.1",
24
+ "proj4leaflet": "^1.0.2",
25
+ "react-leaflet": "^4.2.1"
26
+ },
27
+ "devDependencies": {
28
+ "@babel/core": "^7.28.5",
29
+ "@babel/eslint-parser": "^7.21.3",
30
+ "@babel/plugin-transform-modules-commonjs": "^7.21.2",
31
+ "@babel/preset-env": "^7.28.5",
32
+ "@babel/preset-react": "^7.28.5",
33
+ "@babel/preset-typescript": "^7.28.5",
34
+ "@testing-library/cypress": "^10.1.0",
35
+ "@testing-library/jest-dom": "^5.16.5",
36
+ "@testing-library/react": "^14.0.0",
37
+ "@testing-library/user-event": "^14.4.3",
38
+ "@types/leaflet": "^1.9.1",
39
+ "@types/react": "^19.2.7",
40
+ "@types/react-dom": "^19.2.3",
41
+ "@typescript-eslint/eslint-plugin": "^8.61.0",
42
+ "@typescript-eslint/parser": "^8.61.0",
43
+ "babel-jest": "^29.7.0",
44
+ "babel-loader": "^9.1.2",
45
+ "bootstrap": "^5.3.0",
46
+ "bootstrap-icons": "^1.10.3",
47
+ "css-loader": "^6.7.3",
48
+ "cypress": "^15.2.0",
49
+ "eslint": "^8.36.0",
50
+ "eslint-plugin-jest": "^29.15.2",
51
+ "eslint-plugin-jsx-a11y": "^6.7.1",
52
+ "eslint-plugin-react": "^7.32.2",
53
+ "eslint-plugin-react-hooks": "^4.6.0",
54
+ "fork-ts-checker-webpack-plugin": "^9.1.0",
55
+ "html-webpack-plugin": "^5.5.0",
56
+ "identity-obj-proxy": "^3.0.0",
57
+ "jest": "^29.5.0",
58
+ "jest-environment-jsdom": "^29.5.0",
59
+ "jest-svg-transformer": "^1.0.0",
60
+ "jsdoc": "^4.0.2",
61
+ "prettier": "^2.8.4",
62
+ "process": "^0.11.10",
63
+ "react": "^18.2.0",
64
+ "react-dom": "^18.2.0",
65
+ "regenerator-runtime": "^0.13.11",
66
+ "sass": "^1.58.3",
67
+ "sass-loader": "^13.2.0",
68
+ "start-server-and-test": "^2.1.0",
69
+ "style-loader": "^3.3.1",
70
+ "svg-url-loader": "^8.0.0",
71
+ "typescript": "^5.9.3",
72
+ "webpack": "^5.75.0",
73
+ "webpack-cli": "^5.0.1",
74
+ "webpack-dev-server": "^5.2.4"
75
+ },
76
+ "scripts": {
77
+ "lint": "eslint src/",
78
+ "format": "prettier -w src/",
79
+ "build": "webpack --mode production",
80
+ "build:standalone": "webpack --mode production --env standalone",
81
+ "build:dev:standalone": "webpack --mode development --env standalone",
82
+ "prepare": "rm -rf ./dist && npm run build",
83
+ "build:dev": "webpack --mode development",
84
+ "mock": "webpack serve --mode development --env include-peer-deps",
85
+ "mock:standalone": "webpack serve --mode production --env standalone",
86
+ "mock:dev:standalone": "webpack serve --mode development --env standalone",
87
+ "test": "jest --env=jsdom",
88
+ "cypress": "cypress open",
89
+ "cypress:run": "cypress run",
90
+ "cypress:cicd": "start-server-and-test start \"$URL\" cypress:run",
91
+ "tsc": "tsc --noEmit"
92
+ },
93
+ "browserslist": {
94
+ "production": [
95
+ ">0.2%",
96
+ "not dead",
97
+ "not op_mini all"
98
+ ],
99
+ "development": [
100
+ "last 1 chrome version",
101
+ "last 1 firefox version",
102
+ "last 1 safari version"
103
+ ]
104
+ }
105
+ }
Binary file
@@ -0,0 +1,11 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ </head>
6
+ <body>
7
+ <noscript>You need to enable JavaScript to run this app.</noscript>
8
+ <div id="caosdb-f-map-panel"></div>
9
+ <div id="caosdb-f-toggle-map-button"></div>
10
+ </body>
11
+ </html>
Binary file
Binary file
@@ -0,0 +1,25 @@
1
+ {
2
+ "short_name": "React App",
3
+ "name": "Create React App Sample",
4
+ "icons": [
5
+ {
6
+ "src": "favicon.ico",
7
+ "sizes": "64x64 32x32 24x24 16x16",
8
+ "type": "image/x-icon"
9
+ },
10
+ {
11
+ "src": "logo192.png",
12
+ "type": "image/png",
13
+ "sizes": "192x192"
14
+ },
15
+ {
16
+ "src": "logo512.png",
17
+ "type": "image/png",
18
+ "sizes": "512x512"
19
+ }
20
+ ],
21
+ "start_url": ".",
22
+ "display": "standalone",
23
+ "theme_color": "#000000",
24
+ "background_color": "#ffffff"
25
+ }
Binary file
package/public/mock.js ADDED
@@ -0,0 +1,41 @@
1
+ import React from "react";
2
+ import ReactDOM from "react-dom/client";
3
+ import "bootstrap/scss/bootstrap.scss";
4
+ import "bootstrap-icons/font/bootstrap-icons.css";
5
+ import "../src/index.scss";
6
+ import "regenerator-runtime/runtime";
7
+ import { Map } from "../src/Map";
8
+ import { ToggleMapButton } from "../src/components/ToggleMapButton";
9
+ import { standaloneConfig } from "../standalone.config";
10
+
11
+ window.getEntities = () => [];
12
+
13
+ // Custom config of map components in standalone mode.
14
+ // using standalone.config.js and run using npm run mock:standalone
15
+ const standaloneConfigObj =
16
+ process.env.STANDALONE_MODE === true ? standaloneConfig : {};
17
+
18
+ const caosdb_webui_ext_map = {
19
+ init: (container, toggle_button) => {
20
+ const root = ReactDOM.createRoot(container);
21
+ root.render(
22
+ <React.StrictMode>
23
+ <Map standaloneConfig={standaloneConfigObj} />
24
+ </React.StrictMode>
25
+ );
26
+
27
+ const root2 = ReactDOM.createRoot(toggle_button);
28
+ // If standalone mode, show map without toggle button
29
+ !process.env.STANDALONE_MODE === true &&
30
+ root2.render(
31
+ <React.StrictMode>
32
+ <ToggleMapButton mapContainer="#caosdb-f-map-panel" />
33
+ </React.StrictMode>
34
+ );
35
+ },
36
+ };
37
+
38
+ caosdb_webui_ext_map.init(
39
+ document.getElementById("caosdb-f-map-panel"),
40
+ document.getElementById("caosdb-f-toggle-map-button")
41
+ );
@@ -0,0 +1,3 @@
1
+ # https://www.robotstxt.org/robotstxt.html
2
+ User-agent: *
3
+ Disallow:
@@ -0,0 +1,3 @@
1
+ {
2
+ "formatString": "SELECT id, name, latitude, longitude FROM Event WHICH IS REFERENCED BY Dataset WITH AN authors=${authorId}"
3
+ }
@@ -0,0 +1,294 @@
1
+ import { useEffect, useState, type FC } from "react";
2
+ import { logger } from "./logging";
3
+ import { LayerGroup, LayersControl } from "react-leaflet";
4
+ import { useConfig, type TIframeSettings } from "./context/ConfigProvider";
5
+ import { usePathId } from "./context/PathIdProvider";
6
+ import { useLoading } from "./context/LoadingProvider";
7
+ import {
8
+ get_select_results,
9
+ get_transaction_service,
10
+ EntityMarkers,
11
+ get_selector,
12
+ make_layer_chooser_html,
13
+ get_select_with_path,
14
+ } from "./Map.helpers";
15
+ import { ErrorComponent } from "./components/ErrorComponent";
16
+ import { generateQueryString } from "./utils/GenerateQueryString";
17
+ import { isStandaloneMode } from "./utils";
18
+
19
+ type TAllMapEntitiesProps = {
20
+ hideLayerSwitch?: boolean;
21
+ };
22
+
23
+ type TEntity = {
24
+ parents?: unknown;
25
+ id: string | number;
26
+ name?: string;
27
+ lat?: number;
28
+ lng?: number;
29
+ [key: string]: unknown;
30
+ };
31
+
32
+ type TCurrentPath = string[];
33
+
34
+ type TControlOptions = {
35
+ name: string;
36
+ checked: boolean;
37
+ };
38
+
39
+ /**
40
+ * Build the SELECT query for "all map entities".
41
+ * - If a path is selected: use helper that builds a path-based query.
42
+ * - Otherwise: build a generic query using the datamodel fields.
43
+ */
44
+ function _make_all_map_entities_query(datamodel: any, path: string[]) {
45
+ if (path?.length) {
46
+ // NOTE:
47
+ // get_select_with_path is currently untyped in Map.helpers,
48
+ // so TS can't validate the signature yet.
49
+ // @ts-expect-error function is not typed yet
50
+ return get_select_with_path(datamodel, path);
51
+ }
52
+
53
+ let ret = `SELECT id,name,parent,${datamodel.lat},${datamodel.lng} FROM ${datamodel.role}`;
54
+ if (datamodel.entity) {
55
+ ret += ` "${datamodel.entity}"`;
56
+ }
57
+ ret += ` WITH "${datamodel.lat}" AND "${datamodel.lng}"`;
58
+ return ret;
59
+ }
60
+
61
+ /**
62
+ * Fetch all displayable entities for the current map context.
63
+ * - Standalone mode uses a query string generated from iframeSettings.
64
+ * - Embedded mode uses the normal datamodel/path-based query.
65
+ */
66
+ async function get_all_map_entities(
67
+ datamodel: any,
68
+ path: string[],
69
+ iframeSettings: TIframeSettings = {}
70
+ ): Promise<TEntity[]> {
71
+ const service = get_transaction_service() as any;
72
+
73
+ const query = isStandaloneMode()
74
+ ? (generateQueryString(iframeSettings as TIframeSettings) as string)
75
+ : _make_all_map_entities_query(datamodel, path);
76
+
77
+ logger.debug(`get_all_map_entities query: ${query}`, datamodel, path);
78
+
79
+ const response = await service.executeQuery(query);
80
+
81
+ try {
82
+ const selectResult = response
83
+ ?.getResponsesList?.()?.[0]
84
+ ?.getRetrieveResponse?.()
85
+ ?.getSelectResult?.();
86
+
87
+ const entitiesRes = (await get_select_results(selectResult)) as any[];
88
+
89
+ const entities: TEntity[] = entitiesRes.map((obj: any) => {
90
+ // Selector differs depending on standalone vs embedded mode:
91
+ // - Standalone: selector comes from config (iframeSettings)
92
+ // - Embedded: selector is derived from the current path
93
+ const selector = isStandaloneMode()
94
+ ? iframeSettings?.selector || ""
95
+ : get_selector(path) ?? "";
96
+
97
+ return {
98
+ parents: obj["parent"],
99
+ id: obj.id,
100
+ name: obj.name,
101
+ lat: obj[`${selector}${datamodel.lat}`],
102
+ lng: obj[`${selector}${datamodel.lng}`],
103
+ };
104
+ });
105
+
106
+ logger.debug("get_all_map_entities entities: ", entities);
107
+ return entities;
108
+ } catch (err) {
109
+ logger.error(err, response);
110
+ }
111
+
112
+ return [];
113
+ }
114
+
115
+ /**
116
+ * AllMapEntities
117
+ * -------------
118
+ * Renders the "All entities" overlay layer and fetches entity data when the
119
+ * *data-driving* inputs change (path/datamodel/iframeSettings).
120
+ *
121
+ * Key idea:
122
+ * - We store only raw entity data in state (entities: TEntity[]),
123
+ * NOT a React element, so presentation-only changes (like zIndexOffset or icon_options)
124
+ * don't automatically refetch data.
125
+ */
126
+ export const AllMapEntities: FC<TAllMapEntitiesProps> = ({
127
+ hideLayerSwitch,
128
+ }) => {
129
+ const { startLoading, stopLoading } = useLoading() as {
130
+ startLoading: () => void;
131
+ stopLoading: () => void;
132
+ };
133
+
134
+ const { pathId } = usePathId() as { pathId: string };
135
+
136
+ // State holds only data + error
137
+ const [entities, setEntities] = useState<TEntity[] | null>(null);
138
+ const [error, setError] = useState<unknown>(null);
139
+
140
+ const { config } = useConfig();
141
+
142
+ const {
143
+ iframeSettings = {},
144
+ datamodel,
145
+ entityLayers: {
146
+ all_map_entities: {
147
+ zIndexOffset = 0,
148
+ icon_options,
149
+ name,
150
+ description,
151
+ active,
152
+ },
153
+ },
154
+ select,
155
+ } = config;
156
+
157
+ const currentPath: TCurrentPath = select.paths[pathId] || [];
158
+
159
+ logger.trace(
160
+ "AllMapEntities",
161
+ currentPath,
162
+ zIndexOffset,
163
+ icon_options,
164
+ datamodel
165
+ );
166
+
167
+ /**
168
+ * We intentionally derive "stable keys" used by the effect dependencies.
169
+ *
170
+ * Why?
171
+ * - `currentPath`, `datamodel`, `iframeSettings` may be new object references
172
+ * on each render even when values are the same (depending on upstream code).
173
+ * - Depending on raw objects would trigger unnecessary refetches.
174
+ *
175
+ * Here, we reduce dependencies to *value-based* keys:
176
+ * - currentPathKey: stable string representation of the path
177
+ * - datamodelKey: stable string representation (only if datamodel is JSON-safe)
178
+ * - iFrameKey: stable string representation (same caveat)
179
+ *
180
+ * This makes the effect run only when the underlying values actually change.
181
+ */
182
+ const currentPathKey = Array.isArray(currentPath)
183
+ ? currentPath.join("/")
184
+ : "";
185
+ const iFrameKey = JSON.stringify(iframeSettings);
186
+ const datamodelKey = JSON.stringify(datamodel);
187
+
188
+ useEffect(() => {
189
+ /**
190
+ * Cancellation guard:
191
+ * If the component unmounts or the effect re-runs due to dependency changes
192
+ * while an async request is still in flight, we avoid calling setState on an
193
+ * unmounted component / stale effect instance.
194
+ */
195
+ let cancelled = false;
196
+
197
+ /**
198
+ * Loading counter correctness:
199
+ * Our LoadingProvider uses an in-flight counter.
200
+ * We must call stopLoading() *exactly once* for each startLoading().
201
+ *
202
+ * We therefore track whether we already stopped to prevent:
203
+ * - double stop on .finally + cleanup
204
+ * - or missing stop when unmounting early
205
+ */
206
+ let stopped = false;
207
+
208
+ // Mark "one async operation started"
209
+ startLoading();
210
+
211
+ // Reset state for this fetch cycle
212
+ // Which will also cause the current pins to dissapear from the map
213
+ setEntities(null);
214
+ setError(null);
215
+
216
+ get_all_map_entities(datamodel, currentPath, iframeSettings)
217
+ .then((resolved) => {
218
+ if (cancelled) return;
219
+ setEntities(resolved);
220
+ })
221
+ .catch((err) => {
222
+ if (cancelled) return;
223
+ logger.error("[AllMapEntities] error fetching entities", err);
224
+ setError(err || new Error("Unknown error"));
225
+ })
226
+ .finally(() => {
227
+ // Ensure we decrement the loading counter once
228
+ if (stopped) return;
229
+ stopped = true;
230
+ stopLoading();
231
+ });
232
+
233
+ /**
234
+ * Cleanup:
235
+ * Runs when:
236
+ * - component unmounts OR
237
+ * - dependencies change and effect re-runs
238
+ *
239
+ * We mark cancelled and ensure the loading counter is decremented once.
240
+ */
241
+ return () => {
242
+ cancelled = true;
243
+
244
+ if (stopped) return;
245
+ stopped = true;
246
+ stopLoading();
247
+ };
248
+
249
+ /**
250
+ * Dependency rationale:
251
+ * We *do not* depend on the raw objects, but on their stable keys.
252
+ * This avoids refetching due to referential changes only.
253
+ *
254
+ * We keep startLoading/stopLoading in deps because they are callbacks
255
+ * from context (and should be stable anyway, but including them is correct).
256
+ *
257
+ * NOTE:
258
+ * react-hooks/exhaustive-deps will suggest adding currentPath/datamodel/iframeSettings.
259
+ * We intentionally do not, because that would defeat the key-based approach.
260
+ */
261
+ // eslint-disable-next-line react-hooks/exhaustive-deps
262
+ }, [currentPathKey, datamodelKey, iFrameKey, startLoading, stopLoading]);
263
+
264
+ const isChecked =
265
+ Boolean(active) || (isStandaloneMode() && Boolean(hideLayerSwitch));
266
+
267
+ // Prefer building the object immutably instead of mutating after creation
268
+ const control_options: TControlOptions = {
269
+ name: make_layer_chooser_html(
270
+ icon_options.html,
271
+ name,
272
+ description
273
+ ) as string,
274
+ checked: isChecked,
275
+ };
276
+
277
+ return (
278
+ <LayersControl.Overlay {...control_options}>
279
+ <ErrorComponent error={error} />
280
+ {entities && (
281
+ <LayerGroup>
282
+ <EntityMarkers
283
+ path={currentPath}
284
+ entities={entities}
285
+ zIndexOffset={zIndexOffset as number}
286
+ icon_options={icon_options}
287
+ />
288
+ </LayerGroup>
289
+ )}
290
+ </LayersControl.Overlay>
291
+ );
292
+ };
293
+
294
+ export default AllMapEntities;