diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 0b619009b..e6c7f4284 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -14,6 +14,30 @@ concurrency:
cancel-in-progress: true
jobs:
+ ui:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - uses: actions/setup-node@v4
+ with:
+ node-version: 20
+
+ - name: Install Dependencies
+ working-directory: ui
+ run: npm install -f
+
+ - name: Code Lint
+ working-directory: ui
+ run: npm run lint
+
+ - name: Svelte Check
+ working-directory: ui
+ run: npm run check
+
+ - name: Build
+ working-directory: ui
+ run: npm run build
+
formatting:
runs-on: ubuntu-latest
container: ghcr.io/motis-project/docker-cpp-build
@@ -110,7 +134,7 @@ jobs:
# ==== RESTORE CACHE ====
- name: Restore buildcache Cache
- uses: actions/cache/restore@v3
+ uses: actions/cache/restore@v4
id: restore-buildcache
with:
path: ${{ github.workspace }}/.buildcache
@@ -121,7 +145,7 @@ jobs:
buildcache-${{ matrix.config.preset }}-
- name: Dependencies Cache
- uses: actions/cache@v3
+ uses: actions/cache@v4
with:
path: ${{ github.workspace }}/deps
key: deps-${{ hashFiles('.pkg') }}
@@ -145,7 +169,7 @@ jobs:
# ==== SAVE CACHE ====
- name: Save buildcache cache
if: always()
- uses: actions/cache/save@v3
+ uses: actions/cache/save@v4
with:
path: ${{ github.workspace }}/.buildcache
key: ${{ steps.restore-buildcache.outputs.cache-primary-key }}
diff --git a/assistance.csv b/assistance_times.csv
similarity index 100%
rename from assistance.csv
rename to assistance_times.csv
diff --git a/ui/.eslintignore b/ui/.eslintignore
index 38972655f..d967be1bb 100644
--- a/ui/.eslintignore
+++ b/ui/.eslintignore
@@ -11,3 +11,9 @@ node_modules
pnpm-lock.yaml
package-lock.json
yarn.lock
+
+# Generated code
+src/lib/openapi
+
+# shadcn-svelte
+src/lib/components
\ No newline at end of file
diff --git a/ui/.prettierignore b/ui/.prettierignore
index cc41cea9b..af61c7f51 100644
--- a/ui/.prettierignore
+++ b/ui/.prettierignore
@@ -2,3 +2,5 @@
pnpm-lock.yaml
package-lock.json
yarn.lock
+src/lib/openapi/**
+src/lib/components/**
\ No newline at end of file
diff --git a/ui/package-lock.json b/ui/package-lock.json
index 60e3f80cf..7de8a66b8 100644
--- a/ui/package-lock.json
+++ b/ui/package-lock.json
@@ -12,6 +12,7 @@
"bits-ui": "^0.21.12",
"clsx": "^2.1.1",
"colord": "^2.9.3",
+ "geojson": "^0.5.0",
"lucide-svelte": "^0.445.0",
"maplibre-gl": "^4.3.2",
"polyline": "^0.2.0",
@@ -555,14 +556,14 @@
"integrity": "sha512-kym7SodPp8/wloecOpcmSnWJsK7M0E5Wg8UcFA+uO4B9s5d0ywXOEro/8HM9x0rW+TljRzul/14UYz3TleT3ig=="
},
"node_modules/@hey-api/client-fetch": {
- "version": "0.3.1",
- "resolved": "https://registry.npmjs.org/@hey-api/client-fetch/-/client-fetch-0.3.1.tgz",
- "integrity": "sha512-JwhK2f8h4JtSC9aBjx6QvKx9wo24IEv47D/vh3RrKcb3hjoHOvMmSlRzOICApjXQflfKGjbXvdPrrFyxQgGqsQ=="
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/@hey-api/client-fetch/-/client-fetch-0.3.3.tgz",
+ "integrity": "sha512-KwaKmfltKNfBefeyo19JA7zYwC7BTvWlew1/tfsFi0gIWl2dLVVvhGNgvfUH1kx/bpdC65PXzE9qgkQ/njVPoA=="
},
"node_modules/@hey-api/openapi-ts": {
- "version": "0.53.2",
- "resolved": "https://registry.npmjs.org/@hey-api/openapi-ts/-/openapi-ts-0.53.2.tgz",
- "integrity": "sha512-Z4wM4NeFghRHibukYZHnk3AmDuisIlHYKTNhSIFt7e7njQmJt2xYSJZUmFp10y5jt/V1eIw4L9yc0kfsZPSCXQ==",
+ "version": "0.53.4",
+ "resolved": "https://registry.npmjs.org/@hey-api/openapi-ts/-/openapi-ts-0.53.4.tgz",
+ "integrity": "sha512-5GJ7lQ8FjRFVTqmsGhikj5IpNujySXwF2pN8XJDBP6UXkKycr7GbZrnI0dAww+15Md6MixsClUZuvodp3qJ20g==",
"dev": true,
"dependencies": {
"@apidevtools/json-schema-ref-parser": "11.7.0",
@@ -865,12 +866,12 @@
}
},
"node_modules/@playwright/test": {
- "version": "1.47.1",
- "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.47.1.tgz",
- "integrity": "sha512-dbWpcNQZ5nj16m+A5UNScYx7HX5trIy7g4phrcitn+Nk83S32EBX/CLU4hiF4RGKX/yRc93AAqtfaXB7JWBd4Q==",
+ "version": "1.47.2",
+ "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.47.2.tgz",
+ "integrity": "sha512-jTXRsoSPONAs8Za9QEQdyjFn+0ZQFjCiIztAIF6bi1HqhBzG9Ma7g1WotyiGqFSBRZjIEqMdT8RUlbk1QVhzCQ==",
"dev": true,
"dependencies": {
- "playwright": "1.47.1"
+ "playwright": "1.47.2"
},
"bin": {
"playwright": "cli.js"
@@ -886,9 +887,9 @@
"dev": true
},
"node_modules/@rollup/rollup-android-arm-eabi": {
- "version": "4.22.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.22.0.tgz",
- "integrity": "sha512-/IZQvg6ZR0tAkEi4tdXOraQoWeJy9gbQ/cx4I7k9dJaCk9qrXEcdouxRVz5kZXt5C2bQ9pILoAA+KB4C/d3pfw==",
+ "version": "4.22.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.22.4.tgz",
+ "integrity": "sha512-Fxamp4aEZnfPOcGA8KSNEohV8hX7zVHOemC8jVBoBUHu5zpJK/Eu3uJwt6BMgy9fkvzxDaurgj96F/NiLukF2w==",
"cpu": [
"arm"
],
@@ -899,9 +900,9 @@
]
},
"node_modules/@rollup/rollup-android-arm64": {
- "version": "4.22.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.22.0.tgz",
- "integrity": "sha512-ETHi4bxrYnvOtXeM7d4V4kZWixib2jddFacJjsOjwbgYSRsyXYtZHC4ht134OsslPIcnkqT+TKV4eU8rNBKyyQ==",
+ "version": "4.22.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.22.4.tgz",
+ "integrity": "sha512-VXoK5UMrgECLYaMuGuVTOx5kcuap1Jm8g/M83RnCHBKOqvPPmROFJGQaZhGccnsFtfXQ3XYa4/jMCJvZnbJBdA==",
"cpu": [
"arm64"
],
@@ -912,9 +913,9 @@
]
},
"node_modules/@rollup/rollup-darwin-arm64": {
- "version": "4.22.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.22.0.tgz",
- "integrity": "sha512-ZWgARzhSKE+gVUX7QWaECoRQsPwaD8ZR0Oxb3aUpzdErTvlEadfQpORPXkKSdKbFci9v8MJfkTtoEHnnW9Ulng==",
+ "version": "4.22.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.22.4.tgz",
+ "integrity": "sha512-xMM9ORBqu81jyMKCDP+SZDhnX2QEVQzTcC6G18KlTQEzWK8r/oNZtKuZaCcHhnsa6fEeOBionoyl5JsAbE/36Q==",
"cpu": [
"arm64"
],
@@ -925,9 +926,9 @@
]
},
"node_modules/@rollup/rollup-darwin-x64": {
- "version": "4.22.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.22.0.tgz",
- "integrity": "sha512-h0ZAtOfHyio8Az6cwIGS+nHUfRMWBDO5jXB8PQCARVF6Na/G6XS2SFxDl8Oem+S5ZsHQgtsI7RT4JQnI1qrlaw==",
+ "version": "4.22.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.22.4.tgz",
+ "integrity": "sha512-aJJyYKQwbHuhTUrjWjxEvGnNNBCnmpHDvrb8JFDbeSH3m2XdHcxDd3jthAzvmoI8w/kSjd2y0udT+4okADsZIw==",
"cpu": [
"x64"
],
@@ -938,9 +939,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
- "version": "4.22.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.22.0.tgz",
- "integrity": "sha512-9pxQJSPwFsVi0ttOmqLY4JJ9pg9t1gKhK0JDbV1yUEETSx55fdyCjt39eBQ54OQCzAF0nVGO6LfEH1KnCPvelA==",
+ "version": "4.22.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.22.4.tgz",
+ "integrity": "sha512-j63YtCIRAzbO+gC2L9dWXRh5BFetsv0j0va0Wi9epXDgU/XUi5dJKo4USTttVyK7fGw2nPWK0PbAvyliz50SCQ==",
"cpu": [
"arm"
],
@@ -951,9 +952,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
- "version": "4.22.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.22.0.tgz",
- "integrity": "sha512-YJ5Ku5BmNJZb58A4qSEo3JlIG4d3G2lWyBi13ABlXzO41SsdnUKi3HQHe83VpwBVG4jHFTW65jOQb8qyoR+qzg==",
+ "version": "4.22.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.22.4.tgz",
+ "integrity": "sha512-dJnWUgwWBX1YBRsuKKMOlXCzh2Wu1mlHzv20TpqEsfdZLb3WoJW2kIEsGwLkroYf24IrPAvOT/ZQ2OYMV6vlrg==",
"cpu": [
"arm"
],
@@ -964,9 +965,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm64-gnu": {
- "version": "4.22.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.22.0.tgz",
- "integrity": "sha512-U4G4u7f+QCqHlVg1Nlx+qapZy+QoG+NV6ux+upo/T7arNGwKvKP2kmGM4W5QTbdewWFgudQxi3kDNST9GT1/mg==",
+ "version": "4.22.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.22.4.tgz",
+ "integrity": "sha512-AdPRoNi3NKVLolCN/Sp4F4N1d98c4SBnHMKoLuiG6RXgoZ4sllseuGioszumnPGmPM2O7qaAX/IJdeDU8f26Aw==",
"cpu": [
"arm64"
],
@@ -977,9 +978,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm64-musl": {
- "version": "4.22.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.22.0.tgz",
- "integrity": "sha512-aQpNlKmx3amwkA3a5J6nlXSahE1ijl0L9KuIjVOUhfOh7uw2S4piR3mtpxpRtbnK809SBtyPsM9q15CPTsY7HQ==",
+ "version": "4.22.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.22.4.tgz",
+ "integrity": "sha512-Gl0AxBtDg8uoAn5CCqQDMqAx22Wx22pjDOjBdmG0VIWX3qUBHzYmOKh8KXHL4UpogfJ14G4wk16EQogF+v8hmA==",
"cpu": [
"arm64"
],
@@ -990,9 +991,9 @@
]
},
"node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
- "version": "4.22.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.22.0.tgz",
- "integrity": "sha512-9fx6Zj/7vve/Fp4iexUFRKb5+RjLCff6YTRQl4CoDhdMfDoobWmhAxQWV3NfShMzQk1Q/iCnageFyGfqnsmeqQ==",
+ "version": "4.22.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.22.4.tgz",
+ "integrity": "sha512-3aVCK9xfWW1oGQpTsYJJPF6bfpWfhbRnhdlyhak2ZiyFLDaayz0EP5j9V1RVLAAxlmWKTDfS9wyRyY3hvhPoOg==",
"cpu": [
"ppc64"
],
@@ -1003,9 +1004,9 @@
]
},
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
- "version": "4.22.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.22.0.tgz",
- "integrity": "sha512-VWQiCcN7zBgZYLjndIEh5tamtnKg5TGxyZPWcN9zBtXBwfcGSZ5cHSdQZfQH/GB4uRxk0D3VYbOEe/chJhPGLQ==",
+ "version": "4.22.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.22.4.tgz",
+ "integrity": "sha512-ePYIir6VYnhgv2C5Xe9u+ico4t8sZWXschR6fMgoPUK31yQu7hTEJb7bCqivHECwIClJfKgE7zYsh1qTP3WHUA==",
"cpu": [
"riscv64"
],
@@ -1016,9 +1017,9 @@
]
},
"node_modules/@rollup/rollup-linux-s390x-gnu": {
- "version": "4.22.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.22.0.tgz",
- "integrity": "sha512-EHmPnPWvyYqncObwqrosb/CpH3GOjE76vWVs0g4hWsDRUVhg61hBmlVg5TPXqF+g+PvIbqkC7i3h8wbn4Gp2Fg==",
+ "version": "4.22.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.22.4.tgz",
+ "integrity": "sha512-GqFJ9wLlbB9daxhVlrTe61vJtEY99/xB3C8e4ULVsVfflcpmR6c8UZXjtkMA6FhNONhj2eA5Tk9uAVw5orEs4Q==",
"cpu": [
"s390x"
],
@@ -1029,9 +1030,9 @@
]
},
"node_modules/@rollup/rollup-linux-x64-gnu": {
- "version": "4.22.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.22.0.tgz",
- "integrity": "sha512-tsSWy3YQzmpjDKnQ1Vcpy3p9Z+kMFbSIesCdMNgLizDWFhrLZIoN21JSq01g+MZMDFF+Y1+4zxgrlqPjid5ohg==",
+ "version": "4.22.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.22.4.tgz",
+ "integrity": "sha512-87v0ol2sH9GE3cLQLNEy0K/R0pz1nvg76o8M5nhMR0+Q+BBGLnb35P0fVz4CQxHYXaAOhE8HhlkaZfsdUOlHwg==",
"cpu": [
"x64"
],
@@ -1042,9 +1043,9 @@
]
},
"node_modules/@rollup/rollup-linux-x64-musl": {
- "version": "4.22.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.22.0.tgz",
- "integrity": "sha512-anr1Y11uPOQrpuU8XOikY5lH4Qu94oS6j0xrulHk3NkLDq19MlX8Ng/pVipjxBJ9a2l3+F39REZYyWQFkZ4/fw==",
+ "version": "4.22.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.22.4.tgz",
+ "integrity": "sha512-UV6FZMUgePDZrFjrNGIWzDo/vABebuXBhJEqrHxrGiU6HikPy0Z3LfdtciIttEUQfuDdCn8fqh7wiFJjCNwO+g==",
"cpu": [
"x64"
],
@@ -1055,9 +1056,9 @@
]
},
"node_modules/@rollup/rollup-win32-arm64-msvc": {
- "version": "4.22.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.22.0.tgz",
- "integrity": "sha512-7LB+Bh+Ut7cfmO0m244/asvtIGQr5pG5Rvjz/l1Rnz1kDzM02pSX9jPaS0p+90H5I1x4d1FkCew+B7MOnoatNw==",
+ "version": "4.22.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.22.4.tgz",
+ "integrity": "sha512-BjI+NVVEGAXjGWYHz/vv0pBqfGoUH0IGZ0cICTn7kB9PyjrATSkX+8WkguNjWoj2qSr1im/+tTGRaY+4/PdcQw==",
"cpu": [
"arm64"
],
@@ -1068,9 +1069,9 @@
]
},
"node_modules/@rollup/rollup-win32-ia32-msvc": {
- "version": "4.22.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.22.0.tgz",
- "integrity": "sha512-+3qZ4rer7t/QsC5JwMpcvCVPRcJt1cJrYS/TMJZzXIJbxWFQEVhrIc26IhB+5Z9fT9umfVc+Es2mOZgl+7jdJQ==",
+ "version": "4.22.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.22.4.tgz",
+ "integrity": "sha512-SiWG/1TuUdPvYmzmYnmd3IEifzR61Tragkbx9D3+R8mzQqDBz8v+BvZNDlkiTtI9T15KYZhP0ehn3Dld4n9J5g==",
"cpu": [
"ia32"
],
@@ -1081,9 +1082,9 @@
]
},
"node_modules/@rollup/rollup-win32-x64-msvc": {
- "version": "4.22.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.22.0.tgz",
- "integrity": "sha512-YdicNOSJONVx/vuPkgPTyRoAPx3GbknBZRCOUkK84FJ/YTfs/F0vl/YsMscrB6Y177d+yDRcj+JWMPMCgshwrA==",
+ "version": "4.22.4",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.22.4.tgz",
+ "integrity": "sha512-j8pPKp53/lq9lMXN57S8cFz0MynJk8OWNuUnXct/9KCpKU7DgU3bYMJhwWmcqC0UU29p8Lr0/7KEVcaM6bf47Q==",
"cpu": [
"x64"
],
@@ -1688,9 +1689,9 @@
"dev": true
},
"node_modules/aria-query": {
- "version": "5.3.1",
- "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.1.tgz",
- "integrity": "sha512-Z/ZeOgVl7bcSYZ/u/rh0fOpvEpq//LZmdbkXyc7syVzjPAhfOa9ebsdTSjEBDU4vs5nC98Kfduj1uFo0qyET3g==",
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz",
+ "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==",
"engines": {
"node": ">= 0.4"
}
@@ -1791,9 +1792,9 @@
}
},
"node_modules/bits-ui": {
- "version": "0.21.14",
- "resolved": "https://registry.npmjs.org/bits-ui/-/bits-ui-0.21.14.tgz",
- "integrity": "sha512-goCDjXy4O7qQZiaOpNtojYtDm0vJA7RBtPQyCqQFmj6RzIvsa0d6JOPNY7IpRZT9Oc3uR0nNb5WqfOwehgtuVw==",
+ "version": "0.21.15",
+ "resolved": "https://registry.npmjs.org/bits-ui/-/bits-ui-0.21.15.tgz",
+ "integrity": "sha512-+m5WSpJnFdCcNdXSTIVC1WYBozipO03qRh03GFWgrdxoHiolCfwW71EYG4LPCWYPG6KcTZV0Cj6iHSiZ7cdKdg==",
"dependencies": {
"@internationalized/date": "^3.5.1",
"@melt-ui/svelte": "0.76.2",
@@ -1842,9 +1843,9 @@
}
},
"node_modules/browserslist": {
- "version": "4.23.3",
- "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz",
- "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==",
+ "version": "4.24.0",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.0.tgz",
+ "integrity": "sha512-Rmb62sR1Zpjql25eSanFGEhAxcFwfA1K0GuQcLoaJBAcENegrQut3hYdhXFF1obQfiDyqIW/cLM5HSJ/9k884A==",
"dev": true,
"funding": [
{
@@ -1861,8 +1862,8 @@
}
],
"dependencies": {
- "caniuse-lite": "^1.0.30001646",
- "electron-to-chromium": "^1.5.4",
+ "caniuse-lite": "^1.0.30001663",
+ "electron-to-chromium": "^1.5.28",
"node-releases": "^2.0.18",
"update-browserslist-db": "^1.1.0"
},
@@ -1954,9 +1955,9 @@
}
},
"node_modules/caniuse-lite": {
- "version": "1.0.30001662",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001662.tgz",
- "integrity": "sha512-sgMUVwLmGseH8ZIrm1d51UbrhqMCH3jvS7gF/M6byuHOnKyLOBL7W8yz5V02OHwgLGA36o/AFhWzzh4uc5aqTA==",
+ "version": "1.0.30001664",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001664.tgz",
+ "integrity": "sha512-AmE7k4dXiNKQipgn7a2xg558IRqPN3jMQY/rOsbxDhrd0tyChwbITBfiwtnqz8bi2M5mIWbxAYBvk7W7QBUS2g==",
"dev": true,
"funding": [
{
@@ -2226,9 +2227,9 @@
}
},
"node_modules/devalue": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.0.0.tgz",
- "integrity": "sha512-gO+/OMXF7488D+u3ue+G7Y4AA3ZmUnB3eHJXmBTgNHvr4ZNzl36A0ZtG+XCRNYCkYx/bFmw4qtkoFLa+wSrwAA==",
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.1.1.tgz",
+ "integrity": "sha512-maua5KUiapvEwiEAe+XnlZ3Rh0GD+qI1J/nb9vrJc3muPXvcF/8gXYTWF76+5DAqHyDUtOIImEuo0YKE9mshVw==",
"dev": true
},
"node_modules/didyoumean": {
@@ -2297,9 +2298,9 @@
"integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="
},
"node_modules/electron-to-chromium": {
- "version": "1.5.25",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.25.tgz",
- "integrity": "sha512-kMb204zvK3PsSlgvvwzI3wBIcAw15tRkYk+NQdsjdDtcQWTp2RABbMQ9rUBy8KNEOM+/E6ep+XC3AykiWZld4g==",
+ "version": "1.5.29",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.29.tgz",
+ "integrity": "sha512-PF8n2AlIhCKXQ+gTpiJi0VhcHDb69kYX4MtCiivctc2QD3XuNZ/XIOlbGzt7WAjjEev0TtaH6Cu3arZExm5DOw==",
"dev": true
},
"node_modules/emoji-regex": {
@@ -2865,6 +2866,14 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/geojson": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/geojson/-/geojson-0.5.0.tgz",
+ "integrity": "sha512-/Bx5lEn+qRF4TfQ5aLu6NH+UKtvIv7Lhc487y/c8BdludrCTpiWf9wyI0RTyqg49MFefIAvFDuEi5Dfd/zgNxQ==",
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
"node_modules/geojson-vt": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/geojson-vt/-/geojson-vt-4.0.2.tgz",
@@ -3515,7 +3524,6 @@
"version": "0.445.0",
"resolved": "https://registry.npmjs.org/lucide-svelte/-/lucide-svelte-0.445.0.tgz",
"integrity": "sha512-+4q7aL0fJArdAYw8CzO5DhfH4K5Hx/Z3JX5ggUDVMKjq6UHWWSvQ6wKOe7yNxc5muw22U7x3tzoLbHr/5pYPsg==",
- "license": "ISC",
"peerDependencies": {
"svelte": "^3 || ^4 || ^5.0.0-next.42"
}
@@ -3529,9 +3537,9 @@
}
},
"node_modules/maplibre-gl": {
- "version": "4.7.0",
- "resolved": "https://registry.npmjs.org/maplibre-gl/-/maplibre-gl-4.7.0.tgz",
- "integrity": "sha512-hkt7je7NxiMQE8EpCxLWP8t6tkK6SkrMe0hIBjYd4Ar/Q7BOCILxthGmGnU993Mwmkvs2mGiXnVUSOK12DeCzg==",
+ "version": "4.7.1",
+ "resolved": "https://registry.npmjs.org/maplibre-gl/-/maplibre-gl-4.7.1.tgz",
+ "integrity": "sha512-lgL7XpIwsgICiL82ITplfS7IGwrB1OJIw/pCvprDp2dhmSSEBgmPzYRvwYYYvJGJD7fxUv1Tvpih4nZ6VrLuaA==",
"dependencies": {
"@mapbox/geojson-rewind": "^0.5.2",
"@mapbox/jsonlint-lines-primitives": "^2.0.2",
@@ -3819,9 +3827,9 @@
}
},
"node_modules/nypm": {
- "version": "0.3.11",
- "resolved": "https://registry.npmjs.org/nypm/-/nypm-0.3.11.tgz",
- "integrity": "sha512-E5GqaAYSnbb6n1qZyik2wjPDZON43FqOJO59+3OkWrnmQtjggrMOVnsyzfjxp/tS6nlYJBA4zRA5jSM2YaadMg==",
+ "version": "0.3.12",
+ "resolved": "https://registry.npmjs.org/nypm/-/nypm-0.3.12.tgz",
+ "integrity": "sha512-D3pzNDWIvgA+7IORhD/IuWzEk4uXv6GsgOxiid4UU3h9oq5IqV1KtPDi63n4sZJ/xcWlr88c0QM2RgN5VbOhFA==",
"dev": true,
"dependencies": {
"citty": "^0.1.6",
@@ -4080,12 +4088,12 @@
}
},
"node_modules/playwright": {
- "version": "1.47.1",
- "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.47.1.tgz",
- "integrity": "sha512-SUEKi6947IqYbKxRiqnbUobVZY4bF1uu+ZnZNJX9DfU1tlf2UhWfvVjLf01pQx9URsOr18bFVUKXmanYWhbfkw==",
+ "version": "1.47.2",
+ "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.47.2.tgz",
+ "integrity": "sha512-nx1cLMmQWqmA3UsnjaaokyoUpdVaaDhJhMoxX2qj3McpjnsqFHs516QAKYhqHAgOP+oCFTEOCOAaD1RgD/RQfA==",
"dev": true,
"dependencies": {
- "playwright-core": "1.47.1"
+ "playwright-core": "1.47.2"
},
"bin": {
"playwright": "cli.js"
@@ -4098,9 +4106,9 @@
}
},
"node_modules/playwright-core": {
- "version": "1.47.1",
- "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.47.1.tgz",
- "integrity": "sha512-i1iyJdLftqtt51mEk6AhYFaAJCDx0xQ/O5NU8EKaWFgMjItPVma542Nh/Aq8aLCjIJSzjaiEQGW/nyqLkGF1OQ==",
+ "version": "1.47.2",
+ "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.47.2.tgz",
+ "integrity": "sha512-3JvMfF+9LJfe16l7AbSmU555PaTl2tPyQsVInqm3id16pdDfvZ8TTZ/pyzmkbDrZTQefyzU7AIHlZqQnxpqHVQ==",
"dev": true,
"bin": {
"playwright-core": "cli.js"
@@ -4519,9 +4527,9 @@
}
},
"node_modules/rollup": {
- "version": "4.22.0",
- "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.22.0.tgz",
- "integrity": "sha512-W21MUIFPZ4+O2Je/EU+GP3iz7PH4pVPUXSbEZdatQnxo29+3rsUjgrJmzuAZU24z7yRAnFN6ukxeAhZh/c7hzg==",
+ "version": "4.22.4",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.22.4.tgz",
+ "integrity": "sha512-vD8HJ5raRcWOyymsR6Z3o6+RzfEPCnVLMFJ6vRslO1jt4LO6dUo5Qnpg7y4RkZFM2DMe3WUirkI5c16onjrc6A==",
"dev": true,
"dependencies": {
"@types/estree": "1.0.5"
@@ -4534,22 +4542,22 @@
"npm": ">=8.0.0"
},
"optionalDependencies": {
- "@rollup/rollup-android-arm-eabi": "4.22.0",
- "@rollup/rollup-android-arm64": "4.22.0",
- "@rollup/rollup-darwin-arm64": "4.22.0",
- "@rollup/rollup-darwin-x64": "4.22.0",
- "@rollup/rollup-linux-arm-gnueabihf": "4.22.0",
- "@rollup/rollup-linux-arm-musleabihf": "4.22.0",
- "@rollup/rollup-linux-arm64-gnu": "4.22.0",
- "@rollup/rollup-linux-arm64-musl": "4.22.0",
- "@rollup/rollup-linux-powerpc64le-gnu": "4.22.0",
- "@rollup/rollup-linux-riscv64-gnu": "4.22.0",
- "@rollup/rollup-linux-s390x-gnu": "4.22.0",
- "@rollup/rollup-linux-x64-gnu": "4.22.0",
- "@rollup/rollup-linux-x64-musl": "4.22.0",
- "@rollup/rollup-win32-arm64-msvc": "4.22.0",
- "@rollup/rollup-win32-ia32-msvc": "4.22.0",
- "@rollup/rollup-win32-x64-msvc": "4.22.0",
+ "@rollup/rollup-android-arm-eabi": "4.22.4",
+ "@rollup/rollup-android-arm64": "4.22.4",
+ "@rollup/rollup-darwin-arm64": "4.22.4",
+ "@rollup/rollup-darwin-x64": "4.22.4",
+ "@rollup/rollup-linux-arm-gnueabihf": "4.22.4",
+ "@rollup/rollup-linux-arm-musleabihf": "4.22.4",
+ "@rollup/rollup-linux-arm64-gnu": "4.22.4",
+ "@rollup/rollup-linux-arm64-musl": "4.22.4",
+ "@rollup/rollup-linux-powerpc64le-gnu": "4.22.4",
+ "@rollup/rollup-linux-riscv64-gnu": "4.22.4",
+ "@rollup/rollup-linux-s390x-gnu": "4.22.4",
+ "@rollup/rollup-linux-x64-gnu": "4.22.4",
+ "@rollup/rollup-linux-x64-musl": "4.22.4",
+ "@rollup/rollup-win32-arm64-msvc": "4.22.4",
+ "@rollup/rollup-win32-ia32-msvc": "4.22.4",
+ "@rollup/rollup-win32-x64-msvc": "4.22.4",
"fsevents": "~2.3.2"
}
},
@@ -5043,9 +5051,9 @@
}
},
"node_modules/svelte": {
- "version": "5.0.0-next.254",
- "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.0.0-next.254.tgz",
- "integrity": "sha512-U5xNn38rOqNWa1QYliSQDS2gGDyz+YjIvmMHBU8tlaD4+ni1H3PtOkAyIjfK4a2a4RB7YT7VBldLY7dCzAtGEw==",
+ "version": "5.0.0-next.259",
+ "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.0.0-next.259.tgz",
+ "integrity": "sha512-trRFSjKD+11KbXerGmBT0Uc+ZSNUhxn0aQ02q9tjtig/FV24dpZlXmCrcZTZliOLS0P8JWjw6xaWgNheZZoYOg==",
"dependencies": {
"@ampproject/remapping": "^2.3.0",
"@jridgewell/sourcemap-codec": "^1.5.0",
@@ -5212,9 +5220,9 @@
}
},
"node_modules/tailwindcss": {
- "version": "3.4.12",
- "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.12.tgz",
- "integrity": "sha512-Htf/gHj2+soPb9UayUNci/Ja3d8pTmu9ONTfh4QY8r3MATTZOzmv6UYWF7ZwikEIC8okpfqmGqrmDehua8mF8w==",
+ "version": "3.4.13",
+ "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.13.tgz",
+ "integrity": "sha512-KqjHOJKogOUt5Bs752ykCeiwvi0fKVkr5oqsFNt/8px/tA8scFPIlkygsf6jXrfCqGHz7VflA6+yytWuM+XhFw==",
"dependencies": {
"@alloc/quick-lru": "^5.2.0",
"arg": "^5.0.2",
@@ -5586,9 +5594,9 @@
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
},
"node_modules/vite": {
- "version": "5.4.6",
- "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.6.tgz",
- "integrity": "sha512-IeL5f8OO5nylsgzd9tq4qD2QqI0k2CQLGrWD0rCN0EQJZpBK5vJAx0I+GDkMOXxQX/OfFHMuLIx6ddAxGX/k+Q==",
+ "version": "5.4.8",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.8.tgz",
+ "integrity": "sha512-FqrItQ4DT1NC4zCUqMB4c4AZORMKIa0m8/URVCZ77OZ/QSNeJ54bU1vrFADbDsuwfIPcgknRkmqakQcgnL4GiQ==",
"dev": true,
"dependencies": {
"esbuild": "^0.21.3",
diff --git a/ui/package.json b/ui/package.json
index e9ed8f3cf..574b2460a 100644
--- a/ui/package.json
+++ b/ui/package.json
@@ -51,6 +51,7 @@
"polyline": "^0.2.0",
"svelte-radix": "^1.1.0",
"tailwind-merge": "^2.3.0",
- "tailwind-variants": "^0.2.1"
+ "tailwind-variants": "^0.2.1",
+ "geojson": "^0.5.0"
}
-}
\ No newline at end of file
+}
diff --git a/ui/src/app.css b/ui/src/app.css
index 83f2661c2..a566b3b53 100644
--- a/ui/src/app.css
+++ b/ui/src/app.css
@@ -37,7 +37,7 @@
}
.dark {
- --background: 222.2 84% 4.9%;
+ --background: 222.2 84% 4%;
--foreground: 210 40% 98%;
--muted: 217.2 32.6% 17.5%;
diff --git a/ui/src/app.html b/ui/src/app.html
index 1f98ca369..bab364d11 100644
--- a/ui/src/app.html
+++ b/ui/src/app.html
@@ -1,5 +1,5 @@
-
+
diff --git a/ui/src/lib/AddressTypeahead.svelte b/ui/src/lib/AddressTypeahead.svelte
index 85149eb91..84aef986e 100644
--- a/ui/src/lib/AddressTypeahead.svelte
+++ b/ui/src/lib/AddressTypeahead.svelte
@@ -1,22 +1,28 @@
-
-
+
+
{#each items as item (item.value)}
- {#if item.value.type == 'STOP'}
+ {#if item.value.match?.type == 'STOP'}
- {:else if item.value.type == 'ADDRESS'}
+ {:else if item.value.match?.type == 'ADDRESS'}
- {:else if item.value.type == 'PLACE'}
+ {:else if item.value.match?.type == 'PLACE'}
{/if}
- {item.value.name}
+ {item.value.match?.name}
- {item.area}
+ {getDisplayArea(item.value.match)}
{/each}
diff --git a/ui/src/lib/DateInput.svelte b/ui/src/lib/DateInput.svelte
index d68fa54c3..7ec8293e7 100644
--- a/ui/src/lib/DateInput.svelte
+++ b/ui/src/lib/DateInput.svelte
@@ -6,7 +6,7 @@
class: className
}: {
value: Date;
- class: string | undefined;
+ class?: string;
} = $props();
let el: undefined | HTMLInputElement;
@@ -30,7 +30,8 @@
)}
bind:this={el}
onchange={(e) => {
- const dateTimeLocalValue = e.target.value;
+ // @ts-expect-error target exists, value exists
+ const dateTimeLocalValue = e.target!.value!;
const fakeUtcTime = new Date(`${dateTimeLocalValue}Z`);
value = new Date(fakeUtcTime.getTime() + fakeUtcTime.getTimezoneOffset() * 60000);
}}
diff --git a/ui/src/lib/ItineraryToGeoJSON.ts b/ui/src/lib/ItineraryToGeoJSON.ts
deleted file mode 100644
index 6a712e8c7..000000000
--- a/ui/src/lib/ItineraryToGeoJSON.ts
+++ /dev/null
@@ -1,46 +0,0 @@
-import { getColor } from './modeStyle';
-import { type Itinerary } from './openapi/types.gen';
-import polyline from 'polyline';
-import { colord } from 'colord';
-
-export function itineraryToGeoJSON(i: Itinerary | null) {
- return {
- type: 'FeatureCollection',
- features:
- i === null
- ? []
- : i.legs.flatMap((l) => {
- if (l.legGeometryWithLevels) {
- return l.legGeometryWithLevels.map((p) => {
- return {
- type: 'Feature',
- properties: {
- color: '#42a5f5',
- outlineColor: '#1966a4',
- level: p.from_level,
- way: p.osm_way
- },
- geometry: {
- type: 'LineString',
- coordinates: polyline.decode(p.polyline.points, 7).map(([x, y]) => [y, x])
- }
- };
- });
- } else {
- const color = `#${getColor(l)}`;
- const outlineColor = colord(color).darken(0.2).toHex();
- return {
- type: 'Feature',
- properties: {
- outlineColor,
- color
- },
- geometry: {
- type: 'LineString',
- coordinates: polyline.decode(l.legGeometry.points, 7).map(([x, y]) => [y, x])
- }
- };
- }
- })
- };
-}
diff --git a/ui/src/lib/Location.ts b/ui/src/lib/Location.ts
new file mode 100644
index 000000000..028a671c6
--- /dev/null
+++ b/ui/src/lib/Location.ts
@@ -0,0 +1,10 @@
+import type { Match } from './openapi';
+
+export type Location = {
+ label?: string;
+ value: {
+ match?: Match;
+ precision?: number;
+ level?: number;
+ };
+};
diff --git a/ui/src/lib/PopUp.svelte b/ui/src/lib/PopUp.svelte
deleted file mode 100644
index 4224d93a0..000000000
--- a/ui/src/lib/PopUp.svelte
+++ /dev/null
@@ -1,30 +0,0 @@
-
-
-
- {@render children()}
-
diff --git a/ui/src/lib/Precision.ts b/ui/src/lib/Precision.ts
new file mode 100644
index 000000000..bcbb782a1
--- /dev/null
+++ b/ui/src/lib/Precision.ts
@@ -0,0 +1,25 @@
+export const GEOCODER_PRECISION: number = 50;
+export const ZOOM_LEVEL_PRECISION: Array = [
+ 9000, // level 0 entire world
+ 8000, // level 1 entire world
+ 7000, // level 2 entire world
+ 6000, // level 3 entire world
+ 5000, // level 4 entire world
+ 4000, // level 5 entire world
+ 3000, // level 6 entire world
+ 2000, // level 7 entire world
+ 1600, // level 8 entire world
+ 800, // level 9 entire world
+ 400, // level 10 entire world
+ 200, // level 11 entire world
+ 100, // level 12 entire world
+ 50, // level 13 Darmstadt
+ 50, // level 14
+ 50, // level 15
+ 50, // level 16
+ 20, // level 17 Herrngarten
+ 10, // level 18
+ 5, // level 19
+ 5, // level 20
+ 5 // level 21
+];
diff --git a/ui/src/lib/ThemeToggle.svelte b/ui/src/lib/ThemeToggle.svelte
new file mode 100644
index 000000000..4f4f2edfd
--- /dev/null
+++ b/ui/src/lib/ThemeToggle.svelte
@@ -0,0 +1,23 @@
+
+
+
diff --git a/ui/src/routes/Time.svelte b/ui/src/lib/Time.svelte
similarity index 56%
rename from ui/src/routes/Time.svelte
rename to ui/src/lib/Time.svelte
index b201afec4..a6eca7541 100644
--- a/ui/src/routes/Time.svelte
+++ b/ui/src/lib/Time.svelte
@@ -1,11 +1,21 @@
-
+
{#if delay === undefined || (delay !== undefined && delay !== 0)}
{pad(d.getHours())}:{pad(d.getMinutes())}
{/if}
diff --git a/ui/src/lib/api.ts b/ui/src/lib/api.ts
deleted file mode 100644
index 7ba22f872..000000000
--- a/ui/src/lib/api.ts
+++ /dev/null
@@ -1,99 +0,0 @@
-import maplibregl from 'maplibre-gl';
-
-const baseUrl = 'http://localhost:7999';
-
-export class Location {
- lat!: number;
- lng!: number;
- level!: number;
- zoom!: number;
-}
-
-export class Id {
- name!: string;
- id!: string;
- src!: number;
-}
-
-export class Footpath {
- id!: Id;
- loc!: Location;
- default?: number;
- foot?: number;
- wheelchair?: number;
- wheelchair_uses_elevator?: boolean;
-}
-
-export class Footpaths {
- loc!: Location;
- id!: Id;
- footpaths!: Array
;
-}
-
-export class RoutingQuery {
- start!: Location;
- destination!: Location;
- profile!: string;
- direction!: string;
-}
-
-export type Elevator = {
- id: string;
- desc: string;
- state: 'ACTIVE' | 'INACTIVE';
- outOfService: Array<[Date, Date]>;
-};
-
-const post = async (path: string, req: any) => {
- console.log(`FETCH ${path}: ${JSON.stringify(req)}`);
- const response = await fetch(`${baseUrl}${path}`, {
- method: 'POST',
- mode: 'cors',
- headers: {
- 'Access-Control-Allow-Origin': '*',
- 'Content-Type': 'application/json'
- },
- body: JSON.stringify(req)
- });
- return await response.json();
-};
-
-export const getPlatforms = async (bounds: maplibregl.LngLatBounds, level: number) => {
- return await post('/api/platforms', {
- level: level,
- waypoints: bounds.toArray().flat()
- });
-};
-
-export const getRoute = async (query: RoutingQuery) => {
- return await post('/api/route', query);
-};
-
-export const getGraph = async (bounds: maplibregl.LngLatBounds, level: number) => {
- return await post('/api/graph', {
- level: level,
- waypoints: bounds.toArray().flat()
- });
-};
-
-export const getLevels = async (bounds: maplibregl.LngLatBounds) => {
- return await post('/api/levels', {
- waypoints: bounds.toArray().flat()
- });
-};
-
-export const getMatches = async (bounds: maplibregl.LngLatBounds) => {
- return await post('/api/matches', bounds.toArray().flat());
-};
-
-export const getElevators = async (bounds: maplibregl.LngLatBounds) => {
- return await post('/api/elevators', bounds.toArray().flat());
-};
-
-export const getFootpaths = async (station: { id: string; src: number }): Promise => {
- return await post('/api/footpaths', station);
-};
-
-export const updateElevator = async (elevator: Elevator) => {
- return await post('/api/update_elevator', elevator);
-};
diff --git a/ui/src/lib/components/ui/button/index.ts b/ui/src/lib/components/ui/button/index.ts
index 86b4f18de..534fa42e8 100644
--- a/ui/src/lib/components/ui/button/index.ts
+++ b/ui/src/lib/components/ui/button/index.ts
@@ -6,7 +6,7 @@ const buttonVariants = tv({
base: 'inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50',
variants: {
variant: {
- default: 'bg-primary text-primary-foreground shadow hover:bg-primary/90',
+ default: 'bg-foreground text-primary-foreground shadow hover:bg-primary/90',
destructive: 'bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90',
outline:
'border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground',
diff --git a/ui/src/lib/index.ts b/ui/src/lib/index.ts
deleted file mode 100644
index 856f2b6c3..000000000
--- a/ui/src/lib/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-// place files you want to import through the `$lib` alias in this folder.
diff --git a/ui/src/lib/Control.svelte b/ui/src/lib/map/Control.svelte
similarity index 56%
rename from ui/src/lib/Control.svelte
rename to ui/src/lib/map/Control.svelte
index ba4372693..57a2d4552 100644
--- a/ui/src/lib/Control.svelte
+++ b/ui/src/lib/map/Control.svelte
@@ -1,21 +1,22 @@
-
- {@render children()}
+
+ {#if children}
+ {@render children()}
+ {/if}
-
-
diff --git a/ui/src/lib/GeoJSON.svelte b/ui/src/lib/map/GeoJSON.svelte
similarity index 78%
rename from ui/src/lib/GeoJSON.svelte
rename to ui/src/lib/map/GeoJSON.svelte
index 83e4d92e8..ba6178a48 100644
--- a/ui/src/lib/GeoJSON.svelte
+++ b/ui/src/lib/map/GeoJSON.svelte
@@ -1,10 +1,12 @@
diff --git a/ui/src/lib/Map.svelte b/ui/src/lib/map/Map.svelte
similarity index 65%
rename from ui/src/lib/Map.svelte
rename to ui/src/lib/map/Map.svelte
index ced7c1f14..fe43e1c00 100644
--- a/ui/src/lib/Map.svelte
+++ b/ui/src/lib/map/Map.svelte
@@ -7,24 +7,26 @@
let {
map = $bindable(),
zoom = $bindable(),
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
bounds = $bindable(),
style,
transformRequest,
center,
children,
- ...props
+ class: className
}: {
- map: maplibregl.Map | null;
+ map?: maplibregl.Map;
style: maplibregl.StyleSpecification;
transformRequest: maplibregl.RequestTransformFunction;
center: maplibregl.LngLatLike;
- bounds: maplibregl.LngLatBoundsLike | undefined;
+ bounds?: maplibregl.LngLatBoundsLike | undefined;
zoom: number;
- children: Snippet;
+ children?: Snippet;
+ class: string;
} = $props();
let currStyle: maplibregl.StyleSpecification | null = null;
- let ctx = $state<{ map: maplibregl.Map | null }>({ map: null });
+ let ctx = $state<{ map: maplibregl.Map | undefined }>({ map: undefined });
setContext('map', ctx);
$effect(() => {
@@ -33,6 +35,7 @@
}
});
+ let currentCenter = center;
const createMap = (container: HTMLElement) => {
map = new maplibregl.Map({ container, zoom, center, style, transformRequest });
@@ -44,6 +47,14 @@
})
);
+ map.addImage(
+ 'shield-dark',
+ ...createShield({
+ fill: 'hsl(0, 0%, 16%)',
+ stroke: 'hsl(0, 0%, 30%)'
+ })
+ );
+
map.on('load', () => {
currStyle = style;
ctx.map = map;
@@ -58,12 +69,21 @@
return {
destroy() {
ctx.map?.remove();
- ctx.map = null;
+ ctx.map = undefined;
}
};
};
+
+ $effect(() => {
+ if (center != currentCenter) {
+ map?.setCenter(center);
+ currentCenter = center;
+ }
+ });
-
- {@render children()}
+
+ {#if children}
+ {@render children()}
+ {/if}
diff --git a/ui/src/lib/shield.ts b/ui/src/lib/map/shield.ts
similarity index 89%
rename from ui/src/lib/shield.ts
rename to ui/src/lib/map/shield.ts
index 0d477e9a4..df5b4ea94 100644
--- a/ui/src/lib/shield.ts
+++ b/ui/src/lib/map/shield.ts
@@ -1,11 +1,12 @@
import { browser } from '$app/environment';
+import type { StyleImageMetadata } from 'maplibre-gl';
class ShieldOptions {
fill!: string;
stroke!: string;
}
-export function createShield(opt: ShieldOptions): [ImageData, Object] {
+export function createShield(opt: ShieldOptions): [ImageData, Partial
] {
if (!browser) {
throw 'not supported';
}
@@ -29,7 +30,7 @@ export function createShield(opt: ShieldOptions): [ImageData, Object] {
const lp_front = l_front + 1;
const lp_back = l_back - 1;
- let p = new Path2D();
+ const p = new Path2D();
p.moveTo(lr_front, l_front);
// top line
diff --git a/ui/src/lib/style.ts b/ui/src/lib/map/style.ts
similarity index 74%
rename from ui/src/lib/style.ts
rename to ui/src/lib/map/style.ts
index 78315518f..afd396a3e 100644
--- a/ui/src/lib/style.ts
+++ b/ui/src/lib/map/style.ts
@@ -1,16 +1,122 @@
import type { StyleSpecification } from 'maplibre-gl';
-const water = '#99ddff';
-const rail = '#a8a8a8';
-const pedestrian = '#e8e7eb';
+const colors = {
+ light: {
+ background: '#f8f4f0',
-const sport = '#d0f4be';
-const sport_outline = '#b3e998';
+ water: '#99ddff',
+ rail: '#a8a8a8',
+ pedestrian: '#e8e7eb',
-const building = '#ded7d3';
-const building_outline = '#cfc8c4';
+ sport: '#d0f4be',
+ sportOutline: '#b3e998',
-export const getStyle = (level: number): StyleSpecification => {
+ building: '#ded7d3',
+ buildingOutline: '#cfc8c4',
+
+ landuseComplex: '#f0e6d1',
+ landuseCommercial: 'hsla(0, 60%, 87%, 0.23)',
+ landuseIndustrial: '#e0e2eb',
+ landuseResidential: '#ece7e4',
+ landuseRetail: 'hsla(0, 60%, 87%, 0.23)',
+ landuseConstruction: '#aaa69d',
+
+ landusePark: '#b8ebad',
+ landuseNatureLight: '#ddecd7',
+ landuseNatureHeavy: '#a3e39c',
+ landuseCemetery: '#e0e4dd',
+ landuseBeach: '#fffcd3',
+
+ indoorCorridor: '#fdfcfa',
+ indoor: '#d4edff',
+ indoorOutline: '#808080',
+ indoorText: '#333333',
+
+ publicTransport: 'rgba(218,140,140,0.3)',
+
+ footway: '#fff',
+ steps: '#ff4524',
+
+ elevatorOutline: '#808080',
+ elevator: '#bcf1ba',
+
+ roadBackResidential: '#ffffff',
+ roadBackNonResidential: '#ffffff',
+
+ motorway: '#ffb366',
+ motorwayLink: '#f7e06e',
+ primarySecondary: '#fffbf8',
+ linkTertiary: '#ffffff',
+ residential: '#ffffff',
+ road: '#ffffff',
+
+ text: '#333333',
+ textHalo: 'white',
+ citiesText: '#111111',
+ citiesTextHalo: 'white',
+
+ shield: 'shield'
+ },
+ dark: {
+ background: '#292929',
+
+ water: '#1F1F1F',
+ rail: '#232323',
+ pedestrian: '#292929',
+
+ sport: '#272525',
+ sportOutline: '#272525',
+
+ building: '#1F1F1F',
+ buildingOutline: '#1A1A1A',
+
+ landuseComplex: '#292929',
+ landuseCommercial: '#292929',
+ landuseIndustrial: '#353538',
+ landuseResidential: '#292929',
+ landuseRetail: '#292929',
+ landuseConstruction: 'red',
+
+ landusePark: '#272525',
+ landuseNatureLight: '#272525',
+ landuseNatureHeavy: '#272525',
+ landuseCemetery: '#272525',
+ landuseBeach: '#4c4b3e',
+
+ indoorCorridor: '#494949',
+ indoor: '#1a1a1a',
+ indoorOutline: '#0d0d0d',
+ indoorText: '#eeeeee',
+
+ publicTransport: 'rgba(65, 48, 48, 0.3)',
+
+ footway: '#3D3D3D',
+ steps: '#70504b',
+
+ elevatorOutline: '#808080',
+ elevator: '#3b423b',
+
+ roadBackResidential: '#414141',
+ roadBackNonResidential: '#414141',
+
+ motorway: '#414141',
+ motorwayLink: '#414141',
+ primarySecondary: '#414141',
+ linkTertiary: '#414141',
+ residential: '#414141',
+ road: '#414141',
+
+ text: '#787878',
+ textHalo: '#151515',
+ citiesText: '#A8A8A8',
+ citiesTextHalo: '#1A1A1A',
+
+ shield: 'shield-dark'
+ }
+};
+
+export const getStyle = (theme: 'light' | 'dark', level: number): StyleSpecification => {
+ const c = colors[theme];
return {
version: 8,
sources: {
@@ -26,14 +132,14 @@ export const getStyle = (level: number): StyleSpecification => {
{
id: 'background',
type: 'background',
- paint: { 'background-color': '#f8f4f0' }
+ paint: { 'background-color': c.background }
},
{
id: 'coastline',
type: 'fill',
source: 'osm',
'source-layer': 'coastline',
- paint: { 'fill-color': water }
+ paint: { 'fill-color': c.water }
},
{
id: 'landuse_park',
@@ -42,8 +148,7 @@ export const getStyle = (level: number): StyleSpecification => {
'source-layer': 'landuse',
filter: ['==', ['get', 'landuse'], 'park'],
paint: {
- 'fill-color': '#b8ebad'
- // "fill-outline-color": "rgba(95, 208, 100, 1)"
+ 'fill-color': c.landusePark
}
},
{
@@ -57,26 +162,26 @@ export const getStyle = (level: number): StyleSpecification => {
'match',
['get', 'landuse'],
'complex',
- '#f0e6d1',
+ c.landuseComplex,
'commercial',
- 'hsla(0, 60%, 87%, 0.23)',
+ c.landuseCommercial,
'industrial',
- '#e0e2eb',
+ c.landuseIndustrial,
'residential',
- '#ece7e4',
+ c.landuseResidential,
'retail',
- 'hsla(0, 60%, 87%, 0.23)',
+ c.landuseRetail,
'construction',
- '#aaa69d',
+ c.landuseConstruction,
'nature_light',
- '#ddecd7',
+ c.landuseNatureLight,
'nature_heavy',
- '#a3e39c',
+ c.landuseNatureHeavy,
'cemetery',
- '#e0e4dd',
+ c.landuseCemetery,
'beach',
- '#fffcd3',
+ c.landuseBeach,
'magenta'
]
@@ -87,7 +192,7 @@ export const getStyle = (level: number): StyleSpecification => {
type: 'fill',
source: 'osm',
'source-layer': 'water',
- paint: { 'fill-color': water }
+ paint: { 'fill-color': c.water }
},
{
id: 'sport',
@@ -95,8 +200,8 @@ export const getStyle = (level: number): StyleSpecification => {
source: 'osm',
'source-layer': 'sport',
paint: {
- 'fill-color': sport,
- 'fill-outline-color': sport_outline
+ 'fill-color': c.sport,
+ 'fill-outline-color': c.sportOutline
}
},
{
@@ -104,14 +209,14 @@ export const getStyle = (level: number): StyleSpecification => {
type: 'fill',
source: 'osm',
'source-layer': 'pedestrian',
- paint: { 'fill-color': pedestrian }
+ paint: { 'fill-color': c.pedestrian }
},
{
id: 'waterway',
type: 'line',
source: 'osm',
'source-layer': 'waterway',
- paint: { 'line-color': water }
+ paint: { 'line-color': c.water }
},
{
id: 'building',
@@ -119,8 +224,8 @@ export const getStyle = (level: number): StyleSpecification => {
source: 'osm',
'source-layer': 'building',
paint: {
- 'fill-color': building,
- 'fill-outline-color': building_outline,
+ 'fill-color': c.building,
+ 'fill-outline-color': c.buildingOutline,
'fill-opacity': ['interpolate', ['linear'], ['zoom'], 14, 0, 16, 0.8]
}
},
@@ -131,7 +236,7 @@ export const getStyle = (level: number): StyleSpecification => {
'source-layer': 'indoor',
filter: ['all', ['==', 'indoor', 'corridor'], ['==', 'level', level]],
paint: {
- 'fill-color': '#fdfcfa',
+ 'fill-color': c.indoorCorridor,
'fill-opacity': 0.8
}
},
@@ -142,7 +247,7 @@ export const getStyle = (level: number): StyleSpecification => {
'source-layer': 'indoor',
filter: ['all', ['!in', 'indoor', 'corridor', 'wall', 'elevator'], ['==', 'level', level]],
paint: {
- 'fill-color': '#d4edff',
+ 'fill-color': c.indoor,
'fill-opacity': 0.8
}
},
@@ -154,7 +259,7 @@ export const getStyle = (level: number): StyleSpecification => {
filter: ['all', ['!in', 'indoor', 'corridor', 'wall', 'elevator'], ['==', 'level', level]],
minzoom: 18,
paint: {
- 'line-color': '#808080',
+ 'line-color': c.indoorOutline,
'line-width': 2
}
},
@@ -172,7 +277,7 @@ export const getStyle = (level: number): StyleSpecification => {
'text-size': 12
},
paint: {
- 'text-color': '#333333'
+ 'text-color': c.indoorText
}
},
{
@@ -186,7 +291,7 @@ export const getStyle = (level: number): StyleSpecification => {
['any', ['!has', 'level'], ['==', 'level', level]]
],
paint: {
- 'fill-color': 'rgba(218,140,140,0.3)'
+ 'fill-color': c.publicTransport
}
},
{
@@ -205,7 +310,7 @@ export const getStyle = (level: number): StyleSpecification => {
minzoom: 14,
paint: {
'line-dasharray': [0.75, 1.5],
- 'line-color': '#fff',
+ 'line-color': c.footway,
'line-opacity': 0.5,
'line-width': [
'let',
@@ -248,7 +353,7 @@ export const getStyle = (level: number): StyleSpecification => {
],
paint: {
'line-dasharray': [0.5, 0.5],
- 'line-color': '#ff4524',
+ 'line-color': c.steps,
'line-opacity': 1,
'line-width': [
'let',
@@ -285,7 +390,7 @@ export const getStyle = (level: number): StyleSpecification => {
['>=', 'to_level', level]
],
paint: {
- 'circle-color': '#808080',
+ 'circle-color': c.elevatorOutline,
'circle-radius': 16
}
},
@@ -302,7 +407,7 @@ export const getStyle = (level: number): StyleSpecification => {
['>=', 'to_level', level]
],
paint: {
- 'circle-color': '#bcf1ba',
+ 'circle-color': c.elevator,
'circle-radius': 14
}
},
@@ -333,7 +438,7 @@ export const getStyle = (level: number): StyleSpecification => {
'line-cap': 'round'
},
paint: {
- 'line-color': '#ffffff',
+ 'line-color': c.roadBackResidential,
'line-width': ['interpolate', ['linear'], ['zoom'], 5, 0, 9, 0.5, 12, 1, 16, 4, 20, 20],
'line-opacity': ['interpolate', ['linear'], ['zoom'], 12, 0.4, 15, 1]
}
@@ -359,7 +464,7 @@ export const getStyle = (level: number): StyleSpecification => {
'line-cap': 'round'
},
paint: {
- 'line-color': '#ffffff',
+ 'line-color': c.roadBackNonResidential,
'line-width': [
'let',
'base',
@@ -418,16 +523,16 @@ export const getStyle = (level: number): StyleSpecification => {
'match',
['get', 'highway'],
'motorway',
- '#ffb366',
+ c.motorway,
['trunk', 'motorway_link'],
- '#f7e06e',
+ c.motorwayLink,
['primary', 'secondary', 'aeroway', 'trunk_link'],
- '#fffbf8',
+ c.primarySecondary,
['primary_link', 'secondary_link', 'tertiary', 'tertiary_link'],
- '#ffffff',
+ c.linkTertiary,
'residential',
- '#ffffff',
- '#ffffff'
+ c.residential,
+ c.road
],
'line-width': [
'let',
@@ -472,7 +577,7 @@ export const getStyle = (level: number): StyleSpecification => {
'source-layer': 'rail',
filter: ['==', 'rail', 'old'],
paint: {
- 'line-color': rail
+ 'line-color': c.rail
}
},
{
@@ -482,7 +587,7 @@ export const getStyle = (level: number): StyleSpecification => {
'source-layer': 'rail',
filter: ['==', 'rail', 'detail'],
paint: {
- 'line-color': rail
+ 'line-color': c.rail
}
},
{
@@ -496,7 +601,7 @@ export const getStyle = (level: number): StyleSpecification => {
['any', ['!has', 'level'], ['==', 'level', level]]
],
paint: {
- 'line-color': rail,
+ 'line-color': c.rail,
'line-width': 1.15
}
},
@@ -511,7 +616,7 @@ export const getStyle = (level: number): StyleSpecification => {
['any', ['!has', 'level'], ['==', 'level', level]]
],
paint: {
- 'line-color': rail,
+ 'line-color': c.rail,
'line-width': 1.3
}
},
@@ -540,14 +645,14 @@ export const getStyle = (level: number): StyleSpecification => {
'text-justify': 'center',
'text-rotation-alignment': 'viewport',
'text-pitch-alignment': 'viewport',
- 'icon-image': 'shield',
+ 'icon-image': c.shield,
'icon-text-fit': 'both',
'icon-text-fit-padding': [0.5, 4, 0.5, 4],
'icon-rotation-alignment': 'viewport',
'icon-pitch-alignment': 'viewport'
},
paint: {
- 'text-color': '#333333'
+ 'text-color': c.text
}
},
{
@@ -564,8 +669,8 @@ export const getStyle = (level: number): StyleSpecification => {
},
paint: {
'text-halo-width': 11,
- 'text-halo-color': 'white',
- 'text-color': '#333333'
+ 'text-halo-color': c.textHalo,
+ 'text-color': c.text
}
},
{
@@ -582,8 +687,8 @@ export const getStyle = (level: number): StyleSpecification => {
},
paint: {
'text-halo-width': 1,
- 'text-halo-color': 'white',
- 'text-color': '#333333'
+ 'text-halo-color': c.textHalo,
+ 'text-color': c.text
}
},
{
@@ -600,8 +705,8 @@ export const getStyle = (level: number): StyleSpecification => {
},
paint: {
'text-halo-width': 2,
- 'text-halo-color': 'white',
- 'text-color': '#111111'
+ 'text-halo-color': c.citiesTextHalo,
+ 'text-color': c.citiesText
}
}
]
diff --git a/ui/src/lib/modeStyle.ts b/ui/src/lib/modeStyle.ts
index 81edf1d7f..2dd46d8c5 100644
--- a/ui/src/lib/modeStyle.ts
+++ b/ui/src/lib/modeStyle.ts
@@ -4,13 +4,13 @@ export const getModeStyle = (mode: Mode): [string, string] => {
switch (mode) {
case 'WALK':
case 'FLEXIBLE':
- return ['walk', '333'];
+ return ['walk', 'hsl(var(--foreground) / 1)'];
case 'BIKE':
case 'BIKE_TO_PARK':
case 'BIKE_RENTAL':
case 'SCOOTER_RENTAL':
- return ['bike', '333'];
+ return ['bike', '#333'];
case 'CAR':
case 'CAR_TO_PARK':
@@ -18,56 +18,56 @@ export const getModeStyle = (mode: Mode): [string, string] => {
case 'CAR_SHARING':
case 'CAR_PICKUP':
case 'CAR_RENTAL':
- return ['car', '333333'];
+ return ['car', '#333'];
case 'TRANSIT':
case 'BUS':
- return ['bus', 'ff9800'];
+ return ['bus', '#ff9800'];
case 'COACH':
- return ['bus', '9ccc65'];
+ return ['bus', '#9ccc65'];
case 'TRAM':
- return ['tram', 'ff9800'];
+ return ['tram', '#ff9800'];
case 'METRO':
- return ['sbahn', '4caf50'];
+ return ['sbahn', '#4caf50'];
case 'SUBWAY':
- return ['ubahn', '3f51b5'];
+ return ['ubahn', '#3f51b5'];
case 'FERRY':
- return ['ferry', '00acc1'];
+ return ['ferry', '#00acc1'];
case 'AIRPLANE':
- return ['plane', '90a4ae'];
+ return ['plane', '#90a4ae'];
case 'HIGHSPEED_RAIL':
- return ['train', '9c27b0'];
+ return ['train', '#9c27b0'];
case 'LONG_DISTANCE':
- return ['train', 'e91e63'];
+ return ['train', '#e91e63'];
case 'NIGHT_RAIL':
- return ['train', '1a237e'];
+ return ['train', '#1a237e'];
case 'REGIONAL_FAST_RAIL':
case 'REGIONAL_RAIL':
case 'RAIL':
- return ['train', 'f44336'];
+ return ['train', '#f44336'];
}
- return ['train', '000000'];
+ return ['train', '#000000'];
};
export const getColor = (l: Leg): string => {
const defaultColor = getModeStyle(l.mode)[1];
- return !l.routeColor || l.routeColor === '000000' ? defaultColor || '000000' : l.routeColor;
+ return !l.routeColor || l.routeColor === '000000' ? defaultColor : '#' + l.routeColor;
};
export const routeBorderColor = (l: Leg) => {
- return `border-color: #${getColor(l)}`;
+ return `border-color: ${getColor(l)}`;
};
export const routeColor = (l: Leg) => {
- return `background-color: #${getColor(l)}; color: #FFF;`;
+ return `background-color: ${getColor(l)}; color: #FFF;`;
};
diff --git a/ui/src/lib/openapi/core/ApiError.ts b/ui/src/lib/openapi/core/ApiError.ts
index 36675d288..9cf094969 100644
--- a/ui/src/lib/openapi/core/ApiError.ts
+++ b/ui/src/lib/openapi/core/ApiError.ts
@@ -18,4 +18,4 @@ export class ApiError extends Error {
this.body = response.body;
this.request = request;
}
-}
\ No newline at end of file
+}
diff --git a/ui/src/lib/openapi/core/ApiRequestOptions.ts b/ui/src/lib/openapi/core/ApiRequestOptions.ts
index 1758d98c4..2c83c55dd 100644
--- a/ui/src/lib/openapi/core/ApiRequestOptions.ts
+++ b/ui/src/lib/openapi/core/ApiRequestOptions.ts
@@ -11,4 +11,4 @@ export type ApiRequestOptions = {
readonly responseHeader?: string;
readonly responseTransformer?: (data: unknown) => Promise;
readonly errors?: Record;
-};
\ No newline at end of file
+};
diff --git a/ui/src/lib/openapi/core/ApiResult.ts b/ui/src/lib/openapi/core/ApiResult.ts
index 4c58e3913..84b9f9da7 100644
--- a/ui/src/lib/openapi/core/ApiResult.ts
+++ b/ui/src/lib/openapi/core/ApiResult.ts
@@ -4,4 +4,4 @@ export type ApiResult = {
readonly status: number;
readonly statusText: string;
readonly url: string;
-};
\ No newline at end of file
+};
diff --git a/ui/src/lib/openapi/core/CancelablePromise.ts b/ui/src/lib/openapi/core/CancelablePromise.ts
index ccc082e8f..f0face199 100644
--- a/ui/src/lib/openapi/core/CancelablePromise.ts
+++ b/ui/src/lib/openapi/core/CancelablePromise.ts
@@ -65,15 +65,15 @@ export class CancelablePromise implements Promise {
};
Object.defineProperty(onCancel, 'isResolved', {
- get: (): boolean => this._isResolved,
+ get: (): boolean => this._isResolved
});
Object.defineProperty(onCancel, 'isRejected', {
- get: (): boolean => this._isRejected,
+ get: (): boolean => this._isRejected
});
Object.defineProperty(onCancel, 'isCancelled', {
- get: (): boolean => this._isCancelled,
+ get: (): boolean => this._isCancelled
});
return executor(onResolve, onReject, onCancel as OnCancel);
@@ -81,7 +81,7 @@ export class CancelablePromise implements Promise {
}
get [Symbol.toStringTag]() {
- return "Cancellable Promise";
+ return 'Cancellable Promise';
}
public then(
@@ -123,4 +123,4 @@ export class CancelablePromise implements Promise {
public get isCancelled(): boolean {
return this._isCancelled;
}
-}
\ No newline at end of file
+}
diff --git a/ui/src/lib/openapi/core/OpenAPI.ts b/ui/src/lib/openapi/core/OpenAPI.ts
index c9a1b0acb..8f77483d0 100644
--- a/ui/src/lib/openapi/core/OpenAPI.ts
+++ b/ui/src/lib/openapi/core/OpenAPI.ts
@@ -5,22 +5,22 @@ type Middleware = (value: T) => T | Promise;
type Resolver = (options: ApiRequestOptions) => Promise;
export class Interceptors {
- _fns: Middleware[];
+ _fns: Middleware[];
- constructor() {
- this._fns = [];
- }
+ constructor() {
+ this._fns = [];
+ }
- eject(fn: Middleware): void {
- const index = this._fns.indexOf(fn);
- if (index !== -1) {
- this._fns = [...this._fns.slice(0, index), ...this._fns.slice(index + 1)];
- }
- }
+ eject(fn: Middleware): void {
+ const index = this._fns.indexOf(fn);
+ if (index !== -1) {
+ this._fns = [...this._fns.slice(0, index), ...this._fns.slice(index + 1)];
+ }
+ }
- use(fn: Middleware): void {
- this._fns = [...this._fns, fn];
- }
+ use(fn: Middleware): void {
+ this._fns = [...this._fns, fn];
+ }
}
export type OpenAPIConfig = {
@@ -51,6 +51,6 @@ export const OpenAPI: OpenAPIConfig = {
WITH_CREDENTIALS: false,
interceptors: {
request: new Interceptors(),
- response: new Interceptors(),
- },
-};
\ No newline at end of file
+ response: new Interceptors()
+ }
+};
diff --git a/ui/src/lib/openapi/core/request.ts b/ui/src/lib/openapi/core/request.ts
index 5458a2899..3d09b2f48 100644
--- a/ui/src/lib/openapi/core/request.ts
+++ b/ui/src/lib/openapi/core/request.ts
@@ -45,7 +45,7 @@ export const getQueryString = (params: Record): string => {
if (value instanceof Date) {
append(key, value.toISOString());
} else if (Array.isArray(value)) {
- value.forEach(v => encodePair(key, v));
+ value.forEach((v) => encodePair(key, v));
} else if (typeof value === 'object') {
Object.entries(value).forEach(([k, v]) => encodePair(`${key}[${k}]`, v));
} else {
@@ -90,7 +90,7 @@ export const getFormData = (options: ApiRequestOptions): FormData | undefined =>
.filter(([, value]) => value !== undefined && value !== null)
.forEach(([key, value]) => {
if (Array.isArray(value)) {
- value.forEach(v => process(key, v));
+ value.forEach((v) => process(key, v));
} else {
process(key, value);
}
@@ -103,14 +103,20 @@ export const getFormData = (options: ApiRequestOptions): FormData | undefined =>
type Resolver = (options: ApiRequestOptions) => Promise;
-export const resolve = async (options: ApiRequestOptions, resolver?: T | Resolver): Promise => {
+export const resolve = async (
+ options: ApiRequestOptions,
+ resolver?: T | Resolver
+): Promise => {
if (typeof resolver === 'function') {
return (resolver as Resolver)(options);
}
return resolver;
};
-export const getHeaders = async (config: OpenAPIConfig, options: ApiRequestOptions): Promise => {
+export const getHeaders = async (
+ config: OpenAPIConfig,
+ options: ApiRequestOptions
+): Promise => {
const [token, username, password, additionalHeaders] = await Promise.all([
// @ts-ignore
resolve(options, config.TOKEN),
@@ -119,19 +125,22 @@ export const getHeaders = async (config: OpenAPIConfig, options: ApiRequestOp
// @ts-ignore
resolve(options, config.PASSWORD),
// @ts-ignore
- resolve(options, config.HEADERS),
+ resolve(options, config.HEADERS)
]);
const headers = Object.entries({
Accept: 'application/json',
...additionalHeaders,
- ...options.headers,
+ ...options.headers
})
.filter(([, value]) => value !== undefined && value !== null)
- .reduce((headers, [key, value]) => ({
- ...headers,
- [key]: String(value),
- }), {} as Record);
+ .reduce(
+ (headers, [key, value]) => ({
+ ...headers,
+ [key]: String(value)
+ }),
+ {} as Record
+ );
if (isStringWithValue(token)) {
headers['Authorization'] = `Bearer ${token}`;
@@ -185,7 +194,7 @@ export const sendRequest = async (
headers,
body: body ?? formData,
method: options.method,
- signal: controller.signal,
+ signal: controller.signal
};
if (config.WITH_CREDENTIALS) {
@@ -201,7 +210,10 @@ export const sendRequest = async (
return await fetch(url, request);
};
-export const getResponseHeader = (response: Response, responseHeader?: string): string | undefined => {
+export const getResponseHeader = (
+ response: Response,
+ responseHeader?: string
+): string | undefined => {
if (responseHeader) {
const content = response.headers.get(responseHeader);
if (isString(content)) {
@@ -216,10 +228,17 @@ export const getResponseBody = async (response: Response): Promise => {
try {
const contentType = response.headers.get('Content-Type');
if (contentType) {
- const binaryTypes = ['application/octet-stream', 'application/pdf', 'application/zip', 'audio/', 'image/', 'video/'];
+ const binaryTypes = [
+ 'application/octet-stream',
+ 'application/pdf',
+ 'application/zip',
+ 'audio/',
+ 'image/',
+ 'video/'
+ ];
if (contentType.includes('application/json') || contentType.includes('+json')) {
return await response.json();
- } else if (binaryTypes.some(type => contentType.includes(type))) {
+ } else if (binaryTypes.some((type) => contentType.includes(type))) {
return await response.blob();
} else if (contentType.includes('multipart/form-data')) {
return await response.formData();
@@ -276,8 +295,8 @@ export const catchErrorCodes = (options: ApiRequestOptions, result: ApiResult):
508: 'Loop Detected',
510: 'Not Extended',
511: 'Network Authentication Required',
- ...options.errors,
- }
+ ...options.errors
+ };
const error = errors[result.status];
if (error) {
@@ -295,7 +314,9 @@ export const catchErrorCodes = (options: ApiRequestOptions, result: ApiResult):
}
})();
- throw new ApiError(options, result,
+ throw new ApiError(
+ options,
+ result,
`Generic Error: status: ${errorStatus}; status text: ${errorStatusText}; body: ${errorBody}`
);
}
@@ -308,7 +329,10 @@ export const catchErrorCodes = (options: ApiRequestOptions, result: ApiResult):
* @returns CancelablePromise
* @throws ApiError
*/
-export const request = (config: OpenAPIConfig, options: ApiRequestOptions): CancelablePromise => {
+export const request = (
+ config: OpenAPIConfig,
+ options: ApiRequestOptions
+): CancelablePromise => {
return new CancelablePromise(async (resolve, reject, onCancel) => {
try {
const url = getUrl(config, options);
@@ -328,7 +352,7 @@ export const request = (config: OpenAPIConfig, options: ApiRequestOptions)
let transformedBody = responseBody;
if (options.responseTransformer && response.ok) {
- transformedBody = await options.responseTransformer(responseBody)
+ transformedBody = await options.responseTransformer(responseBody);
}
const result: ApiResult = {
@@ -336,7 +360,7 @@ export const request = (config: OpenAPIConfig, options: ApiRequestOptions)
ok: response.ok,
status: response.status,
statusText: response.statusText,
- body: responseHeader ?? transformedBody,
+ body: responseHeader ?? transformedBody
};
catchErrorCodes(options, result);
@@ -347,4 +371,4 @@ export const request = (config: OpenAPIConfig, options: ApiRequestOptions)
reject(error);
}
});
-};
\ No newline at end of file
+};
diff --git a/ui/src/lib/openapi/services.gen.ts b/ui/src/lib/openapi/services.gen.ts
index ca7879e03..112ed6a79 100644
--- a/ui/src/lib/openapi/services.gen.ts
+++ b/ui/src/lib/openapi/services.gen.ts
@@ -1,10 +1,18 @@
// This file is auto-generated by @hey-api/openapi-ts
import { createClient, createConfig, type Options } from '@hey-api/client-fetch';
-import type { GeocodeData, GeocodeError, GeocodeResponse, PlanData, PlanError, PlanResponse } from './types.gen';
+import type { ReverseGeocodeData, ReverseGeocodeError, ReverseGeocodeResponse, GeocodeData, GeocodeError, GeocodeResponse, PlanData, PlanError, PlanResponse } from './types.gen';
export const client = createClient(createConfig());
+/**
+ * Translate coordinates to the closest address(es)/places/stops.
+ */
+export const reverseGeocode = (options: Options) => { return (options?.client ?? client).get({
+ ...options,
+ url: '/api/v1/reverse-geocode'
+}); };
+
/**
* Autocompletion & geocoding that resolves user input addresses including coordinates
*/
diff --git a/ui/src/lib/openapi/types.gen.ts b/ui/src/lib/openapi/types.gen.ts
index e5bbadd8a..b467c372f 100644
--- a/ui/src/lib/openapi/types.gen.ts
+++ b/ui/src/lib/openapi/types.gen.ts
@@ -375,6 +375,19 @@ export type Itinerary = {
legs: Array;
};
+export type ReverseGeocodeData = {
+ query: {
+ /**
+ * latitude, longitude in degrees
+ */
+ place: string;
+ };
+};
+
+export type ReverseGeocodeResponse = (Array);
+
+export type ReverseGeocodeError = unknown;
+
export type GeocodeData = {
query: {
/**
diff --git a/ui/src/lib/toTable.ts b/ui/src/lib/toTable.ts
deleted file mode 100644
index 586a80bda..000000000
--- a/ui/src/lib/toTable.ts
+++ /dev/null
@@ -1,38 +0,0 @@
-export const toTable = (properties: Object) => {
- const table = document.createElement('table');
- table.classList.add('routing-graph', 'properties');
- for (const key in properties) {
- const value = properties[key];
- const row = document.createElement('tr');
- const keyCell = document.createElement('td');
- keyCell.innerText = key;
- keyCell.className = 'key';
- const valueCell = document.createElement('td');
- if (key == 'osm_way_id' && value != 0) {
- const osmLink = document.createElement('a');
- osmLink.href = 'https://www.openstreetmap.org/way/' + Math.abs(value);
- osmLink.target = '_blank';
- osmLink.innerText = value;
- valueCell.appendChild(osmLink);
- } else if (key == 'osm_relation_id' && value != 0) {
- const osmLink = document.createElement('a');
- osmLink.href = 'https://www.openstreetmap.org/relation/' + Math.abs(value);
- osmLink.target = '_blank';
- osmLink.innerText = value;
- valueCell.appendChild(osmLink);
- } else if (key == 'osm_node_id' && value != 0) {
- const osmLink = document.createElement('a');
- osmLink.href = 'https://www.openstreetmap.org/node/' + Math.abs(value);
- osmLink.target = '_blank';
- osmLink.innerText = value;
- valueCell.appendChild(osmLink);
- } else {
- valueCell.innerText = value;
- }
- valueCell.className = 'value';
- row.appendChild(keyCell);
- row.appendChild(valueCell);
- table.appendChild(row);
- }
- return table;
-};
diff --git a/ui/src/routes/+layout.svelte b/ui/src/routes/+layout.svelte
index 2e511e004..f87b35e58 100644
--- a/ui/src/routes/+layout.svelte
+++ b/ui/src/routes/+layout.svelte
@@ -1,4 +1,4 @@
-
diff --git a/ui/src/routes/+page.svelte b/ui/src/routes/+page.svelte
index a3b3c9287..eb3ec87fd 100644
--- a/ui/src/routes/+page.svelte
+++ b/ui/src/routes/+page.svelte
@@ -1,962 +1,139 @@