This is an automated email from the ASF dual-hosted git repository.

riemer pushed a commit to branch support-vector-maps
in repository https://gitbox.apache.org/repos/asf/streampipes.git

commit a63edefa6910f37370b1663bd115462c8c3bfb4c
Author: Dominik Riemer <[email protected]>
AuthorDate: Thu Dec 4 17:43:54 2025 +0100

    feat: Support vector maps in addition to tile servers
---
 .../model/configuration/LocationConfig.java        |   9 +-
 .../{LocationConfig.java => MapLayerType.java}     |  10 +-
 .../model/configuration/SpCoreConfiguration.java   |   2 +-
 ui/package-lock.json                               | 280 ++++++++++++++++++++-
 ui/package.json                                    |   2 +
 .../src/lib/model/gen/streampipes-model.ts         |  35 ++-
 .../manage-site/manage-site-dialog.component.ts    |   5 +-
 .../location-features-configuration.component.html |  23 +-
 .../location-features-configuration.component.ts   |   7 +
 .../core-ui/services/map-layer-provider.service.ts |  47 ++++
 .../single-marker-map.component.ts                 |  20 +-
 11 files changed, 414 insertions(+), 26 deletions(-)

diff --git 
a/streampipes-model/src/main/java/org/apache/streampipes/model/configuration/LocationConfig.java
 
b/streampipes-model/src/main/java/org/apache/streampipes/model/configuration/LocationConfig.java
index 573e9abe70..c4d59615ea 100644
--- 
a/streampipes-model/src/main/java/org/apache/streampipes/model/configuration/LocationConfig.java
+++ 
b/streampipes-model/src/main/java/org/apache/streampipes/model/configuration/LocationConfig.java
@@ -22,5 +22,12 @@ import 
org.apache.streampipes.model.shared.annotation.TsModel;
 
 @TsModel
 public record LocationConfig(boolean locationEnabled,
+                             MapLayerType mapLayerType,
                              String tileServerUrl,
-                             String attributionText) {}
+                             String attributionText) {
+
+  @Override
+  public MapLayerType mapLayerType() {
+    return mapLayerType != null ? this.mapLayerType : MapLayerType.TILE;
+  }
+}
diff --git 
a/streampipes-model/src/main/java/org/apache/streampipes/model/configuration/LocationConfig.java
 
b/streampipes-model/src/main/java/org/apache/streampipes/model/configuration/MapLayerType.java
similarity index 78%
copy from 
streampipes-model/src/main/java/org/apache/streampipes/model/configuration/LocationConfig.java
copy to 
streampipes-model/src/main/java/org/apache/streampipes/model/configuration/MapLayerType.java
index 573e9abe70..c512d25b71 100644
--- 
a/streampipes-model/src/main/java/org/apache/streampipes/model/configuration/LocationConfig.java
+++ 
b/streampipes-model/src/main/java/org/apache/streampipes/model/configuration/MapLayerType.java
@@ -18,9 +18,7 @@
 
 package org.apache.streampipes.model.configuration;
 
-import org.apache.streampipes.model.shared.annotation.TsModel;
-
-@TsModel
-public record LocationConfig(boolean locationEnabled,
-                             String tileServerUrl,
-                             String attributionText) {}
+public enum MapLayerType {
+  TILE,
+  VECTOR
+}
diff --git 
a/streampipes-model/src/main/java/org/apache/streampipes/model/configuration/SpCoreConfiguration.java
 
b/streampipes-model/src/main/java/org/apache/streampipes/model/configuration/SpCoreConfiguration.java
index 788ecbf1e7..88c8a56e1e 100644
--- 
a/streampipes-model/src/main/java/org/apache/streampipes/model/configuration/SpCoreConfiguration.java
+++ 
b/streampipes-model/src/main/java/org/apache/streampipes/model/configuration/SpCoreConfiguration.java
@@ -45,7 +45,7 @@ public class SpCoreConfiguration {
   private List<ExportProviderSettings> exportProviderSettings;
 
   public SpCoreConfiguration() {
-    this.locationConfig = new LocationConfig(false, "", "");
+    this.locationConfig = new LocationConfig(false, MapLayerType.TILE, "", "");
   }
 
   public String getRev() {
diff --git a/ui/package-lock.json b/ui/package-lock.json
index 1049ed3bb5..3822857d85 100644
--- a/ui/package-lock.json
+++ b/ui/package-lock.json
@@ -25,6 +25,7 @@
         "@fortawesome/fontawesome-free": "6.5.1",
         "@gradle-tech/develocity-agent": "^2.0.2",
         "@jsplumb/browser-ui": "^6.2.10",
+        "@maplibre/maplibre-gl-leaflet": "^0.1.3",
         "@ngbracket/ngx-layout": "^19.0.0",
         "@ngx-loading-bar/core": "6.0.2",
         "@ngx-loading-bar/http-client": "6.0.2",
@@ -46,6 +47,7 @@
         "jshint": "^2.13.6",
         "leaflet": "1.9.3",
         "lodash.clonedeep": "^4.5.0",
+        "maplibre-gl": "^5.14.0",
         "marked": "^15.0.12",
         "material-icons": "^1.13.1",
         "ngx-color-picker": "^19.0.0",
@@ -4766,6 +4768,132 @@
         "win32"
       ]
     },
+    "node_modules/@mapbox/geojson-rewind": {
+      "version": "0.5.2",
+      "resolved": 
"https://registry.npmjs.org/@mapbox/geojson-rewind/-/geojson-rewind-0.5.2.tgz";,
+      "integrity": 
"sha512-tJaT+RbYGJYStt7wI3cq4Nl4SXxG8W7JDG5DMJu97V25RnbNg3QtQtf+KD+VLjNpWKYsRvXDNmNrBgEETr1ifA==",
+      "license": "ISC",
+      "dependencies": {
+        "get-stream": "^6.0.1",
+        "minimist": "^1.2.6"
+      },
+      "bin": {
+        "geojson-rewind": "geojson-rewind"
+      }
+    },
+    "node_modules/@mapbox/geojson-rewind/node_modules/get-stream": {
+      "version": "6.0.1",
+      "resolved": 
"https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz";,
+      "integrity": 
"sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus";
+      }
+    },
+    "node_modules/@mapbox/jsonlint-lines-primitives": {
+      "version": "2.0.2",
+      "resolved": 
"https://registry.npmjs.org/@mapbox/jsonlint-lines-primitives/-/jsonlint-lines-primitives-2.0.2.tgz";,
+      "integrity": 
"sha512-rY0o9A5ECsTQRVhv7tL/OyDpGAoUB4tTvLiW1DSzQGq4bvTPhNw1VpSNjDJc5GFZ2XuyOtSWSVN05qOtcD71qQ==",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/@mapbox/point-geometry": {
+      "version": "1.1.0",
+      "resolved": 
"https://registry.npmjs.org/@mapbox/point-geometry/-/point-geometry-1.1.0.tgz";,
+      "integrity": 
"sha512-YGcBz1cg4ATXDCM/71L9xveh4dynfGmcLDqufR+nQQy3fKwsAZsWd/x4621/6uJaeB9mwOHE6hPeDgXz9uViUQ==",
+      "license": "ISC"
+    },
+    "node_modules/@mapbox/tiny-sdf": {
+      "version": "2.0.7",
+      "resolved": 
"https://registry.npmjs.org/@mapbox/tiny-sdf/-/tiny-sdf-2.0.7.tgz";,
+      "integrity": 
"sha512-25gQLQMcpivjOSA40g3gO6qgiFPDpWRoMfd+G/GoppPIeP6JDaMMkMrEJnMZhKyyS6iKwVt5YKu02vCUyJM3Ug==",
+      "license": "BSD-2-Clause"
+    },
+    "node_modules/@mapbox/unitbezier": {
+      "version": "0.0.1",
+      "resolved": 
"https://registry.npmjs.org/@mapbox/unitbezier/-/unitbezier-0.0.1.tgz";,
+      "integrity": 
"sha512-nMkuDXFv60aBr9soUG5q+GvZYL+2KZHVvsqFCzqnkGEf46U2fvmytHaEVc1/YZbiLn8X+eR3QzX1+dwDO1lxlw==",
+      "license": "BSD-2-Clause"
+    },
+    "node_modules/@mapbox/vector-tile": {
+      "version": "2.0.4",
+      "resolved": 
"https://registry.npmjs.org/@mapbox/vector-tile/-/vector-tile-2.0.4.tgz";,
+      "integrity": 
"sha512-AkOLcbgGTdXScosBWwmmD7cDlvOjkg/DetGva26pIRiZPdeJYjYKarIlb4uxVzi6bwHO6EWH82eZ5Nuv4T5DUg==",
+      "license": "BSD-3-Clause",
+      "dependencies": {
+        "@mapbox/point-geometry": "~1.1.0",
+        "@types/geojson": "^7946.0.16",
+        "pbf": "^4.0.1"
+      }
+    },
+    "node_modules/@mapbox/whoots-js": {
+      "version": "3.1.0",
+      "resolved": 
"https://registry.npmjs.org/@mapbox/whoots-js/-/whoots-js-3.1.0.tgz";,
+      "integrity": 
"sha512-Es6WcD0nO5l+2BOQS4uLfNPYQaNDfbot3X1XUoloz+x0mPDS3eeORZJl06HXjwBG1fOGwCRnzK88LMdxKRrd6Q==",
+      "license": "ISC",
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@maplibre/maplibre-gl-leaflet": {
+      "version": "0.1.3",
+      "resolved": 
"https://registry.npmjs.org/@maplibre/maplibre-gl-leaflet/-/maplibre-gl-leaflet-0.1.3.tgz";,
+      "integrity": 
"sha512-9+hp1PSJcxuuj5/Zta9zbQ8+ZvN4doWXPtlY7ikNtUZY1VbkamY0uTqzHp9kxRPqpgeKGrI7MjzXvwzU88wWCw==",
+      "license": "ISC",
+      "peerDependencies": {
+        "@types/leaflet": "^1.9.0",
+        "leaflet": "^1.9.3",
+        "maplibre-gl": "^2.4.0 || ^3.3.1 || ^4.3.2 || ^5.0.0"
+      }
+    },
+    "node_modules/@maplibre/maplibre-gl-style-spec": {
+      "version": "24.3.1",
+      "resolved": 
"https://registry.npmjs.org/@maplibre/maplibre-gl-style-spec/-/maplibre-gl-style-spec-24.3.1.tgz";,
+      "integrity": 
"sha512-TUM5JD40H2mgtVXl5IwWz03BuQabw8oZQLJTmPpJA0YTYF+B+oZppy5lNMO6bMvHzB+/5mxqW9VLG3wFdeqtOw==",
+      "license": "ISC",
+      "dependencies": {
+        "@mapbox/jsonlint-lines-primitives": "~2.0.2",
+        "@mapbox/unitbezier": "^0.0.1",
+        "json-stringify-pretty-compact": "^4.0.0",
+        "minimist": "^1.2.8",
+        "quickselect": "^3.0.0",
+        "rw": "^1.3.3",
+        "tinyqueue": "^3.0.0"
+      },
+      "bin": {
+        "gl-style-format": "dist/gl-style-format.mjs",
+        "gl-style-migrate": "dist/gl-style-migrate.mjs",
+        "gl-style-validate": "dist/gl-style-validate.mjs"
+      }
+    },
+    "node_modules/@maplibre/mlt": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/@maplibre/mlt/-/mlt-1.1.2.tgz";,
+      "integrity": 
"sha512-SQKdJ909VGROkA6ovJgtHNs9YXV4YXUPS+VaZ50I2Mt951SLlUm2Cv34x5Xwc1HiFlsd3h2Yrs5cn7xzqBmENw==",
+      "license": "(MIT OR Apache-2.0)",
+      "dependencies": {
+        "@mapbox/point-geometry": "^1.1.0"
+      }
+    },
+    "node_modules/@maplibre/vt-pbf": {
+      "version": "4.1.0",
+      "resolved": 
"https://registry.npmjs.org/@maplibre/vt-pbf/-/vt-pbf-4.1.0.tgz";,
+      "integrity": 
"sha512-9LjFAoWtxdGRns8RK9vG3Fcw/fb3eHMxvAn2jffwn3jnVO1k49VOv6+FEza70rK7WzF8GnBiKa0K39RyfevKUw==",
+      "license": "MIT",
+      "dependencies": {
+        "@mapbox/point-geometry": "^1.1.0",
+        "@mapbox/vector-tile": "^2.0.4",
+        "@types/geojson-vt": "3.2.5",
+        "@types/supercluster": "^7.1.3",
+        "geojson-vt": "^4.0.2",
+        "pbf": "^4.0.1",
+        "supercluster": "^8.0.1"
+      }
+    },
     "node_modules/@mermaid-js/parser": {
       "version": "0.3.0",
       "resolved": 
"https://registry.npmjs.org/@mermaid-js/parser/-/parser-0.3.0.tgz";,
@@ -6867,9 +6995,17 @@
       "version": "7946.0.16",
       "resolved": 
"https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.16.tgz";,
       "integrity": 
"sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==",
-      "devOptional": true,
       "license": "MIT"
     },
+    "node_modules/@types/geojson-vt": {
+      "version": "3.2.5",
+      "resolved": 
"https://registry.npmjs.org/@types/geojson-vt/-/geojson-vt-3.2.5.tgz";,
+      "integrity": 
"sha512-qDO7wqtprzlpe8FfQ//ClPV9xiuoh2nkIgiouIptON9w5jvD/fA4szvP9GBlDVdJ5dldAl0kX/sy3URbWwLx0g==",
+      "license": "MIT",
+      "dependencies": {
+        "@types/geojson": "*"
+      }
+    },
     "node_modules/@types/http-errors": {
       "version": "2.0.4",
       "resolved": 
"https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz";,
@@ -6932,7 +7068,6 @@
       "version": "1.9.16",
       "resolved": 
"https://registry.npmjs.org/@types/leaflet/-/leaflet-1.9.16.tgz";,
       "integrity": 
"sha512-wzZoyySUxkgMZ0ihJ7IaUIblG8Rdc8AbbZKLneyn+QjYsj5q1QU7TEKYqwTr10BGSzY5LI7tJk9Ifo+mEjdFRw==",
-      "dev": true,
       "license": "MIT",
       "dependencies": {
         "@types/geojson": "*"
@@ -7203,6 +7338,15 @@
       "dev": true,
       "license": "MIT"
     },
+    "node_modules/@types/supercluster": {
+      "version": "7.1.3",
+      "resolved": 
"https://registry.npmjs.org/@types/supercluster/-/supercluster-7.1.3.tgz";,
+      "integrity": 
"sha512-Z0pOY34GDFl3Q6hUFYf3HkTwKEE02e7QgtJppBt+beEAxnyOpJua+voGFvxINBHa06GwLFFym7gRPY2SiKIfIA==",
+      "license": "MIT",
+      "dependencies": {
+        "@types/geojson": "*"
+      }
+    },
     "node_modules/@types/tern": {
       "version": "0.23.9",
       "resolved": "https://registry.npmjs.org/@types/tern/-/tern-0.23.9.tgz";,
@@ -10879,6 +11023,12 @@
         "node": ">= 0.4"
       }
     },
+    "node_modules/earcut": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/earcut/-/earcut-3.0.2.tgz";,
+      "integrity": 
"sha512-X7hshQbLyMJ/3RPhyObLARM2sNxxmRALLKx1+NVFFnQ9gKzmCrxm9+uLIAdBcvc8FNLpctqlQ2V6AE92Ol9UDQ==",
+      "license": "ISC"
+    },
     "node_modules/eastasianwidth": {
       "version": "0.2.0",
       "resolved": 
"https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz";,
@@ -12312,6 +12462,12 @@
         "node": ">=6.9.0"
       }
     },
+    "node_modules/geojson-vt": {
+      "version": "4.0.2",
+      "resolved": 
"https://registry.npmjs.org/geojson-vt/-/geojson-vt-4.0.2.tgz";,
+      "integrity": 
"sha512-AV9ROqlNqoZEIJGfm1ncNjEXfkz2hdFlZf0qkVfmkwdKa8vj7H16YUOT81rJw1rdFhyEDlN2Tds91p/glzbl5A==",
+      "license": "ISC"
+    },
     "node_modules/get-caller-file": {
       "version": "2.0.5",
       "resolved": 
"https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz";,
@@ -12423,6 +12579,12 @@
         "safe-buffer": "^5.2.1"
       }
     },
+    "node_modules/gl-matrix": {
+      "version": "3.4.4",
+      "resolved": "https://registry.npmjs.org/gl-matrix/-/gl-matrix-3.4.4.tgz";,
+      "integrity": 
"sha512-latSnyDNt/8zYUB6VIJ6PCh2jBjJX6gnDsoCZ7LyW7GkqrD51EWwa9qCoGixj8YqBtETQK/xY7OmpTF8xz1DdQ==",
+      "license": "MIT"
+    },
     "node_modules/glob": {
       "version": "10.4.5",
       "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz";,
@@ -14035,6 +14197,12 @@
       "dev": true,
       "license": "MIT"
     },
+    "node_modules/json-stringify-pretty-compact": {
+      "version": "4.0.0",
+      "resolved": 
"https://registry.npmjs.org/json-stringify-pretty-compact/-/json-stringify-pretty-compact-4.0.0.tgz";,
+      "integrity": 
"sha512-3CNZ2DnrpByG9Nqj6Xo8vqbjT4F6N+tb4Gb28ESAZjYZ5yqvmc56J+/kuIwkaAMOyblTQhUW7PxMkUb8Q36N3Q==",
+      "license": "MIT"
+    },
     "node_modules/json-stringify-safe": {
       "version": "5.0.1",
       "resolved": 
"https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz";,
@@ -14507,6 +14675,12 @@
         "node": ">= 12"
       }
     },
+    "node_modules/kdbush": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/kdbush/-/kdbush-4.0.2.tgz";,
+      "integrity": 
"sha512-WbCVYJ27Sz8zi9Q7Q0xHC+05iwkm3Znipc2XTlrnJbsHMYktW4hPhXUE8Ys1engBrvffoSCqbil1JQAa7clRpA==",
+      "license": "ISC"
+    },
     "node_modules/keyv": {
       "version": "4.5.4",
       "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz";,
@@ -15487,6 +15661,44 @@
         "node": "^18.17.0 || >=20.5.0"
       }
     },
+    "node_modules/maplibre-gl": {
+      "version": "5.14.0",
+      "resolved": 
"https://registry.npmjs.org/maplibre-gl/-/maplibre-gl-5.14.0.tgz";,
+      "integrity": 
"sha512-O2ok6N/bQ9NA9nJ22r/PRQQYkUe9JwfDMjBPkQ+8OwsVH4TpA5skIAM2wc0k+rni5lVbAVONVyBvgi1rF2vEPA==",
+      "license": "BSD-3-Clause",
+      "dependencies": {
+        "@mapbox/geojson-rewind": "^0.5.2",
+        "@mapbox/jsonlint-lines-primitives": "^2.0.2",
+        "@mapbox/point-geometry": "^1.1.0",
+        "@mapbox/tiny-sdf": "^2.0.7",
+        "@mapbox/unitbezier": "^0.0.1",
+        "@mapbox/vector-tile": "^2.0.4",
+        "@mapbox/whoots-js": "^3.1.0",
+        "@maplibre/maplibre-gl-style-spec": "^24.3.1",
+        "@maplibre/mlt": "^1.1.2",
+        "@maplibre/vt-pbf": "^4.1.0",
+        "@types/geojson": "^7946.0.16",
+        "@types/geojson-vt": "3.2.5",
+        "@types/supercluster": "^7.1.3",
+        "earcut": "^3.0.2",
+        "geojson-vt": "^4.0.2",
+        "gl-matrix": "^3.4.4",
+        "kdbush": "^4.0.2",
+        "murmurhash-js": "^1.0.0",
+        "pbf": "^4.0.1",
+        "potpack": "^2.1.0",
+        "quickselect": "^3.0.0",
+        "supercluster": "^8.0.1",
+        "tinyqueue": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=16.14.0",
+        "npm": ">=8.1.0"
+      },
+      "funding": {
+        "url": "https://github.com/maplibre/maplibre-gl-js?sponsor=1";
+      }
+    },
     "node_modules/marked": {
       "version": "15.0.12",
       "resolved": "https://registry.npmjs.org/marked/-/marked-15.0.12.tgz";,
@@ -15772,7 +15984,6 @@
       "version": "1.2.8",
       "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz";,
       "integrity": 
"sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
-      "dev": true,
       "license": "MIT",
       "funding": {
         "url": "https://github.com/sponsors/ljharb";
@@ -16114,6 +16325,12 @@
         "multicast-dns": "cli.js"
       }
     },
+    "node_modules/murmurhash-js": {
+      "version": "1.0.0",
+      "resolved": 
"https://registry.npmjs.org/murmurhash-js/-/murmurhash-js-1.0.0.tgz";,
+      "integrity": 
"sha512-TvmkNhkv8yct0SVBSy+o8wYzXjE4Zz3PCesbfs8HiCXXdcTuocApFv11UWlNFWKYsP2okqrhb7JNlSm9InBhIw==",
+      "license": "MIT"
+    },
     "node_modules/mustache": {
       "version": "4.2.0",
       "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz";,
@@ -17384,6 +17601,18 @@
       "license": "MIT",
       "optional": true
     },
+    "node_modules/pbf": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/pbf/-/pbf-4.0.1.tgz";,
+      "integrity": 
"sha512-SuLdBvS42z33m8ejRbInMapQe8n0D3vN/Xd5fmWM3tufNgRQFBpaW2YVJxQZV4iPNqb0vEFvssMEo5w9c6BTIA==",
+      "license": "BSD-3-Clause",
+      "dependencies": {
+        "resolve-protobuf-schema": "^2.1.0"
+      },
+      "bin": {
+        "pbf": "bin/pbf"
+      }
+    },
     "node_modules/pend": {
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz";,
@@ -17747,6 +17976,12 @@
       "dev": true,
       "license": "MIT"
     },
+    "node_modules/potpack": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/potpack/-/potpack-2.1.0.tgz";,
+      "integrity": 
"sha512-pcaShQc1Shq0y+E7GqJqvZj8DTthWV1KeHGdi0Z6IAin2Oi3JnLCOfwnCo84qc+HAp52wT9nK9H7FAJp5a44GQ==",
+      "license": "ISC"
+    },
     "node_modules/prelude-ls": {
       "version": "1.2.1",
       "resolved": 
"https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz";,
@@ -17837,6 +18072,12 @@
         "node": ">=10"
       }
     },
+    "node_modules/protocol-buffers-schema": {
+      "version": "3.6.0",
+      "resolved": 
"https://registry.npmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-3.6.0.tgz";,
+      "integrity": 
"sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw==",
+      "license": "MIT"
+    },
     "node_modules/proxy-addr": {
       "version": "2.0.7",
       "resolved": 
"https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz";,
@@ -17941,6 +18182,12 @@
       ],
       "license": "MIT"
     },
+    "node_modules/quickselect": {
+      "version": "3.0.0",
+      "resolved": 
"https://registry.npmjs.org/quickselect/-/quickselect-3.0.0.tgz";,
+      "integrity": 
"sha512-XdjUArbK4Bm5fLLvlm5KpTFOiOThgfWWI4axAZDWg4E/0mKdZyI9tNEfds27qCi1ze/vwTR16kvmmGhRra3c2g==",
+      "license": "ISC"
+    },
     "node_modules/quill": {
       "version": "2.0.3",
       "resolved": "https://registry.npmjs.org/quill/-/quill-2.0.3.tgz";,
@@ -18219,6 +18466,15 @@
         "node": ">=4"
       }
     },
+    "node_modules/resolve-protobuf-schema": {
+      "version": "2.1.0",
+      "resolved": 
"https://registry.npmjs.org/resolve-protobuf-schema/-/resolve-protobuf-schema-2.1.0.tgz";,
+      "integrity": 
"sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ==",
+      "license": "MIT",
+      "dependencies": {
+        "protocol-buffers-schema": "^3.3.1"
+      }
+    },
     "node_modules/resolve-url-loader": {
       "version": "5.0.0",
       "resolved": 
"https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-5.0.0.tgz";,
@@ -18479,8 +18735,7 @@
       "version": "1.3.3",
       "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz";,
       "integrity": 
"sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==",
-      "license": "BSD-3-Clause",
-      "optional": true
+      "license": "BSD-3-Clause"
     },
     "node_modules/rxjs": {
       "version": "7.8.1",
@@ -19707,6 +19962,15 @@
       "license": "MIT",
       "optional": true
     },
+    "node_modules/supercluster": {
+      "version": "8.0.1",
+      "resolved": 
"https://registry.npmjs.org/supercluster/-/supercluster-8.0.1.tgz";,
+      "integrity": 
"sha512-IiOea5kJ9iqzD2t7QJq/cREyLHTtSmUT6gQsweojg9WH2sYJqZK9SswTu6jrscO6D1G5v5vYZ9ru/eq85lXeZQ==",
+      "license": "ISC",
+      "dependencies": {
+        "kdbush": "^4.0.2"
+      }
+    },
     "node_modules/supports-color": {
       "version": "7.2.0",
       "resolved": 
"https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz";,
@@ -19989,6 +20253,12 @@
         "url": "https://github.com/sponsors/SuperchupuDev";
       }
     },
+    "node_modules/tinyqueue": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/tinyqueue/-/tinyqueue-3.0.0.tgz";,
+      "integrity": 
"sha512-gRa9gwYU3ECmQYv3lslts5hxuIa90veaEcxDYuu3QGOIAEM2mOZkVHp48ANJuu1CURtRdHKUBY5Lm1tHV+sD4g==",
+      "license": "ISC"
+    },
     "node_modules/tldts": {
       "version": "6.1.86",
       "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.86.tgz";,
diff --git a/ui/package.json b/ui/package.json
index de4d772674..e10fe12949 100644
--- a/ui/package.json
+++ b/ui/package.json
@@ -46,6 +46,7 @@
     "@fortawesome/fontawesome-free": "6.5.1",
     "@gradle-tech/develocity-agent": "^2.0.2",
     "@jsplumb/browser-ui": "^6.2.10",
+    "@maplibre/maplibre-gl-leaflet": "^0.1.3",
     "@ngbracket/ngx-layout": "^19.0.0",
     "@ngx-loading-bar/core": "6.0.2",
     "@ngx-loading-bar/http-client": "6.0.2",
@@ -69,6 +70,7 @@
     "lodash.clonedeep": "^4.5.0",
     "marked": "^15.0.12",
     "material-icons": "^1.13.1",
+    "maplibre-gl": "^5.14.0",
     "ngx-color-picker": "^19.0.0",
     "ngx-echarts": "^19.0.0",
     "ngx-markdown": "^19.1.1",
diff --git 
a/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model.ts
 
b/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model.ts
index c9e29a27a6..edb971862f 100644
--- 
a/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model.ts
+++ 
b/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model.ts
@@ -16,10 +16,11 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+
 /* tslint:disable */
 /* eslint-disable */
 // @ts-nocheck
-// Generated using typescript-generator version 3.2.1263 on 2025-12-02 
15:38:14.
+// Generated using typescript-generator version 3.2.1263 on 2025-12-04 
17:41:18.
 
 export class NamedStreamPipesEntity implements Storable {
     '@class':
@@ -179,6 +180,23 @@ export class AdapterEventPreview {
     }
 }
 
+export class AdapterType {
+    code: string;
+    description: string;
+    label: string;
+
+    static fromData(data: AdapterType, target?: AdapterType): AdapterType {
+        if (!data) {
+            return data;
+        }
+        const instance = target || new AdapterType();
+        instance.code = data.code;
+        instance.description = data.description;
+        instance.label = data.label;
+        return instance;
+    }
+}
+
 export class TransformationRuleDescription {
     '@class':
         | 
'org.apache.streampipes.model.connect.rules.value.ValueTransformationRuleDescription'
@@ -1180,11 +1198,18 @@ export class DashboardEntity implements Storable, 
SpResource {
 export class DashboardItem {
     cols: number;
     component: string;
+    dataViewElementId: string;
+    h: number;
     id: string;
     name: string;
     rows: number;
     settings: string[];
     timeSettings: { [index: string]: any };
+    w: number;
+    /**
+     * @deprecated since 0.99.0, for removal
+     */
+    widgetId: string;
     x: number;
     y: number;
 
@@ -1198,6 +1223,8 @@ export class DashboardItem {
         const instance = target || new DashboardItem();
         instance.cols = data.cols;
         instance.component = data.component;
+        instance.dataViewElementId = data.dataViewElementId;
+        instance.h = data.h;
         instance.id = data.id;
         instance.name = data.name;
         instance.rows = data.rows;
@@ -1207,6 +1234,8 @@ export class DashboardItem {
         instance.timeSettings = __getCopyObjectFn(__identity<any>())(
             data.timeSettings,
         );
+        instance.w = data.w;
+        instance.widgetId = data.widgetId;
         instance.x = data.x;
         instance.y = data.y;
         return instance;
@@ -2419,6 +2448,7 @@ export class ListOutputStrategy extends OutputStrategy {
 export class LocationConfig {
     attributionText: string;
     locationEnabled: boolean;
+    mapLayerType: MapLayerType;
     tileServerUrl: string;
 
     static fromData(
@@ -2431,6 +2461,7 @@ export class LocationConfig {
         const instance = target || new LocationConfig();
         instance.attributionText = data.attributionText;
         instance.locationEnabled = data.locationEnabled;
+        instance.mapLayerType = data.mapLayerType;
         instance.tileServerUrl = data.tileServerUrl;
         return instance;
     }
@@ -4471,6 +4502,8 @@ export type Isa95Type =
     | 'STORAGE_UNIT'
     | 'OTHER';
 
+export type MapLayerType = 'TILE' | 'VECTOR';
+
 export type MappingPropertyUnion = MappingPropertyNary | MappingPropertyUnary;
 
 export type OneOfStaticPropertyUnion = RuntimeResolvableOneOfStaticProperty;
diff --git 
a/ui/src/app/configuration/dialog/manage-site/manage-site-dialog.component.ts 
b/ui/src/app/configuration/dialog/manage-site/manage-site-dialog.component.ts
index 389c9bd5e0..cf89f35901 100644
--- 
a/ui/src/app/configuration/dialog/manage-site/manage-site-dialog.component.ts
+++ 
b/ui/src/app/configuration/dialog/manage-site/manage-site-dialog.component.ts
@@ -65,7 +65,10 @@ export class ManageSiteDialogComponent implements OnInit {
             appDocType: AssetConstants.ASSET_SITES_APP_DOC_NAME,
             _id: undefined,
             label: '',
-            location: { coordinates: { latitude: 0, longitude: 0 }, zoom: 10 },
+            location: {
+                coordinates: { latitude: 49.00689, longitude: 8.40365 },
+                zoom: 10,
+            },
             areas: [],
         };
         this.createMode = true;
diff --git 
a/ui/src/app/configuration/sites-configuration/location-features-configuration/location-features-configuration.component.html
 
b/ui/src/app/configuration/sites-configuration/location-features-configuration/location-features-configuration.component.html
index cb2faae401..b8c61d46a7 100644
--- 
a/ui/src/app/configuration/sites-configuration/location-features-configuration/location-features-configuration.component.html
+++ 
b/ui/src/app/configuration/sites-configuration/location-features-configuration/location-features-configuration.component.html
@@ -33,8 +33,29 @@
                 @if (showLocationDetails) {
                     <div class="mt-10">
                         <div class="subsection-title">
+                            {{ 'Layer type' | translate }}
+                        </div>
+                        <mat-radio-group
+                            formControlName="mapLayerType"
+                            fxLayout="row"
+                        >
+                            <mat-radio-button
+                                value="TILE"
+                                data-cy="sites-location-config-layer-type-tile"
+                            >
+                                {{ 'Tile' | translate }}
+                            </mat-radio-button>
+                            <mat-radio-button
+                                value="VECTOR"
+                                class="ml-20"
+                                
data-cy="sites-location-config-layer-type-vector"
+                            >
+                                {{ 'Vector' | translate }}
+                            </mat-radio-button>
+                        </mat-radio-group>
+                        <div class="subsection-title mt-10">
                             {{
-                                'Tile server URL(use placeholders for x, y and 
z coordinates)'
+                                'Style/Tile server URL (for tile server, use 
placeholders for x, y and z coordinates)'
                                     | translate
                             }}
                         </div>
diff --git 
a/ui/src/app/configuration/sites-configuration/location-features-configuration/location-features-configuration.component.ts
 
b/ui/src/app/configuration/sites-configuration/location-features-configuration/location-features-configuration.component.ts
index 68583fd1df..1189cb87a3 100644
--- 
a/ui/src/app/configuration/sites-configuration/location-features-configuration/location-features-configuration.component.ts
+++ 
b/ui/src/app/configuration/sites-configuration/location-features-configuration/location-features-configuration.component.ts
@@ -60,6 +60,10 @@ export class LocationFeaturesConfigurationComponent
             'locationFeaturesEnabled',
             new UntypedFormControl(this.locationConfig.locationEnabled),
         );
+        this.locationForm.addControl(
+            'mapLayerType',
+            new UntypedFormControl(this.locationConfig.mapLayerType),
+        );
         this.locationForm.addControl(
             'tileServerUrl',
             new UntypedFormControl(
@@ -67,6 +71,7 @@ export class LocationFeaturesConfigurationComponent
                 this.showLocationDetails ? Validators.required : [],
             ),
         );
+
         this.locationForm.addControl(
             'attributionText',
             new UntypedFormControl(this.locationConfig.attributionText || ''),
@@ -89,6 +94,8 @@ export class LocationFeaturesConfigurationComponent
         this.locationConfig.locationEnabled = this.locationForm.get(
             'locationFeaturesEnabled',
         ).value;
+        this.locationConfig.mapLayerType =
+            this.locationForm.get('mapLayerType').value;
         if (this.locationConfig.locationEnabled) {
             this.locationConfig.tileServerUrl =
                 this.locationForm.get('tileServerUrl').value;
diff --git a/ui/src/app/core-ui/services/map-layer-provider.service.ts 
b/ui/src/app/core-ui/services/map-layer-provider.service.ts
new file mode 100644
index 0000000000..1896a5975a
--- /dev/null
+++ b/ui/src/app/core-ui/services/map-layer-provider.service.ts
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { Injectable } from '@angular/core';
+import { LocationConfig } from '@streampipes/platform-services';
+import * as L from 'leaflet';
+import '@maplibre/maplibre-gl-leaflet';
+
+@Injectable({ providedIn: 'root' })
+export class MapLayerProviderService {
+    getMapLayers(locationConfig: LocationConfig): L.Layer[] {
+        if (locationConfig?.locationEnabled) {
+            if (locationConfig.mapLayerType === 'TILE') {
+                return [
+                    L.tileLayer(locationConfig.tileServerUrl, {
+                        maxZoom: 18,
+                        attribution: locationConfig.attributionText,
+                    }),
+                ];
+            } else {
+                return [
+                    (L as any).maplibreGL({
+                        style: locationConfig.tileServerUrl,
+                        attribution: locationConfig.attributionText,
+                    }),
+                ];
+            }
+        } else {
+            return [];
+        }
+    }
+}
diff --git 
a/ui/src/app/core-ui/single-marker-map/single-marker-map.component.ts 
b/ui/src/app/core-ui/single-marker-map/single-marker-map.component.ts
index 417b489c9d..561a690471 100644
--- a/ui/src/app/core-ui/single-marker-map/single-marker-map.component.ts
+++ b/ui/src/app/core-ui/single-marker-map/single-marker-map.component.ts
@@ -16,7 +16,7 @@
  *
  */
 
-import { Component, forwardRef, Input, OnInit } from '@angular/core';
+import { Component, forwardRef, inject, Input, OnInit } from '@angular/core';
 import {
     icon,
     Layer,
@@ -33,6 +33,7 @@ import {
     LocationConfig,
 } from '@streampipes/platform-services';
 import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
+import { MapLayerProviderService } from 
'../services/map-layer-provider.service';
 
 @Component({
     selector: 'sp-single-marker-map',
@@ -47,6 +48,8 @@ import { ControlValueAccessor, NG_VALUE_ACCESSOR } from 
'@angular/forms';
     standalone: false,
 })
 export class SingleMarkerMapComponent implements OnInit, ControlValueAccessor {
+    private mapLayerProviderService = inject(MapLayerProviderService);
+
     @Input()
     locationConfig: LocationConfig;
 
@@ -67,18 +70,15 @@ export class SingleMarkerMapComponent implements OnInit, 
ControlValueAccessor {
     ngOnInit() {
         this.assetLocation ??= {
             coordinates: {
-                latitude: 0,
-                longitude: 0,
+                latitude: 49.00689,
+                longitude: 8.40365,
             },
-            zoom: 1,
+            zoom: 8,
         };
         this.mapOptions = {
-            layers: [
-                tileLayer(this.locationConfig.tileServerUrl, {
-                    maxZoom: 18,
-                    attribution: this.locationConfig.attributionText,
-                }),
-            ],
+            layers: this.mapLayerProviderService.getMapLayers(
+                this.locationConfig,
+            ),
             zoom: this.assetLocation.zoom || 1,
             center: {
                 lat: this.assetLocation.coordinates.latitude,


Reply via email to