diff --git a/Server/src/models/api.ts b/Server/src/models/api.ts index 28f009bb..9c9e1d14 100644 --- a/Server/src/models/api.ts +++ b/Server/src/models/api.ts @@ -37,10 +37,20 @@ export type FullTrack = BareTrack & { /** @see {isTrackList} ts-auto-guard:type-guard */ export type TrackList = BareTrack[] +/** @see {isCreatePOITypeIcon} ts-auto-guard:type-guard */ +export enum POITypeIcon { + Generic = 0, + LevelCrossing = 1, + LesserLevelCrossing = 2, + Picnic = 3, + TrackEnd = 4, + TurningPoint = 5, +} + /** @see {isCreatePOIType} ts-auto-guard:type-guard */ export type CreatePOIType = { name: string - icon: string + icon: POITypeIcon description?: string } diff --git a/Server/src/routes/init.route.ts b/Server/src/routes/init.route.ts index 6cae697f..6bdbdd16 100644 --- a/Server/src/routes/init.route.ts +++ b/Server/src/routes/init.route.ts @@ -1,10 +1,10 @@ import { Request, Response, Router } from "express" import { jsonParser } from "." import { InitRequestApp, InitResponseApp, TrackListEntryApp } from "../models/api.app" -import { PointOfInterest, Position } from "../models/api" +import { PointOfInterest, POITypeIcon, Position } from "../models/api" import { logger } from "../utils/logger" import TrackService from "../services/track.service" -import { POI, Track } from "@prisma/client" +import { POI, POIType, Track } from "@prisma/client" import POIService from "../services/poi.service" import VehicleService from "../services/vehicle.service" import { Feature, FeatureCollection, GeoJsonProperties, LineString, Point } from "geojson" @@ -196,11 +196,22 @@ export class InitRoute { private async getAppPoisFromDbPoi(pois: POI[]): Promise { const apiPois: PointOfInterest[] = [] for (const poi of pois) { - const type: number = poi.typeId + const type: POIType | null = await POIService.getPOITypeById(poi.typeId) if (!type) { logger.error(`Could not determine type of poi with id ${poi.uid}`) continue } + const poiIcon: number = Number.parseInt(type.icon) + if (!Number.isInteger(poiIcon)) { + logger.error(`Icon of type with id ${type.uid} is not an integer.`) + continue + } + // Check if the icon number is a member of the enum. + if (!(poiIcon in POITypeIcon)) { + logger.warn(`Icon of type with id ${type.uid} is ${poiIcon}, not one of the known icons.`) + } + // ensure that the app always gets an enum member. + const appType: POITypeIcon = poiIcon in POITypeIcon ? poiIcon : POITypeIcon.Generic const geoJsonPos: Feature | null = GeoJSONUtils.parseGeoJSONFeaturePoint(poi.position) if (!geoJsonPos) { @@ -220,7 +231,7 @@ export class InitRoute { apiPois.push({ id: poi.uid, name: poi.name, - typeId: 0 <= type && type <= 4 ? type : 0, + typeId: appType, pos: pos, percentagePosition: percentagePosition, isTurningPoint: poi.isTurningPoint, diff --git a/Server/src/routes/poitype.route.ts b/Server/src/routes/poitype.route.ts index 980bf20c..5321c4cd 100644 --- a/Server/src/routes/poitype.route.ts +++ b/Server/src/routes/poitype.route.ts @@ -45,7 +45,7 @@ export class PoiTypeRoute { const type: APIPoiType = { id: uid, name, - icon, + icon: Number.parseInt(icon), description: description ?? undefined } return type @@ -74,7 +74,7 @@ export class PoiTypeRoute { id: poiType.uid, name: poiType.name, description: poiType.description ?? undefined, - icon: poiType.icon + icon: Number.parseInt(poiType.icon) } res.json(apiPoiType) @@ -82,9 +82,10 @@ export class PoiTypeRoute { } private async createType(req: Request, res: Response): Promise { + // TODO: ensure that the icon is a member of the enum (or check if the type guard checks that) const { name, icon, description }: CreatePOIType = req.body - const poiType: POIType | null = await database.pois.saveType(name, icon, description) + const poiType: POIType | null = await database.pois.saveType(name, icon.toString(), description) if (!poiType) { logger.error("Could not create poi type") res.sendStatus(500) @@ -94,7 +95,7 @@ export class PoiTypeRoute { const responseType: APIPoiType = { id: poiType.uid, name: poiType.name, - icon: poiType.icon, + icon: Number.parseInt(poiType.icon), description: poiType.description ?? undefined } res.status(201).json(responseType) @@ -104,6 +105,7 @@ export class PoiTypeRoute { private async updateType(req: Request, res: Response): Promise { const typeId: number = parseInt(req.params.typeId) const userData: APIPoiType = req.body + // TODO: ensure that the icon is a member of the enum (or check if the type guard checks that) if (userData.id !== typeId) { res.sendStatus(400) return @@ -116,7 +118,7 @@ export class PoiTypeRoute { return } - type = await database.pois.updateType(typeId, userData.name, userData.icon, userData.description) + type = await database.pois.updateType(typeId, userData.name, userData.icon.toString(), userData.description) if (!type) { logger.error(`Could not update poi type with id ${userData.id}`) res.sendStatus(500) diff --git a/Server/src/services/db/poi.controller.ts b/Server/src/services/db/poi.controller.ts index 7d5b5d8e..98a3632e 100644 --- a/Server/src/services/db/poi.controller.ts +++ b/Server/src/services/db/poi.controller.ts @@ -71,6 +71,7 @@ export default class POIController { }, data: { name: name, + icon: icon, description: description } }) diff --git a/Website/package-lock.json b/Website/package-lock.json index 8ea06706..bf2f0fd6 100644 --- a/Website/package-lock.json +++ b/Website/package-lock.json @@ -24,6 +24,7 @@ "react-dom": "18.2.0", "react-select": "^5.7.4", "server-only": "^0.0.1", + "sharp": "^0.32.5", "swr": "^2.2.0", "tailwindcss": "3.3.2" }, @@ -1310,6 +1311,11 @@ "dequal": "^2.0.3" } }, + "node_modules/b4a": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.4.tgz", + "integrity": "sha512-fpWrvyVHEKyeEvbKZTVOeZF3VSKKWtJxFIxX/jaVPf+cLbGUSitjb49pHLqPV2BUNNZ0LcoeEGfE/YCpyDYHIw==" + }, "node_modules/babel-plugin-macros": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", @@ -1329,6 +1335,25 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -1337,6 +1362,16 @@ "node": ">=8" } }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -1388,6 +1423,29 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, "node_modules/busboy": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", @@ -1500,16 +1558,32 @@ "node": ">= 6" } }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, "node_modules/client-only": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==" }, + "node_modules/color": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", + "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", + "dependencies": { + "color-convert": "^2.0.1", + "color-string": "^1.9.0" + }, + "engines": { + "node": ">=12.5.0" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "dependencies": { "color-name": "~1.1.4" }, @@ -1520,8 +1594,16 @@ "node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } }, "node_modules/commander": { "version": "4.1.1", @@ -1640,6 +1722,28 @@ } } }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "engines": { + "node": ">=4.0.0" + } + }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -1671,6 +1775,14 @@ "node": ">=6" } }, + "node_modules/detect-libc": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.2.tgz", + "integrity": "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==", + "engines": { + "node": ">=8" + } + }, "node_modules/didyoumean": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", @@ -1725,6 +1837,14 @@ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "dev": true }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, "node_modules/enhanced-resolve": { "version": "5.15.0", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", @@ -2310,12 +2430,25 @@ "node": ">=0.10.0" } }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "engines": { + "node": ">=6" + } + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, + "node_modules/fast-fifo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", + "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==" + }, "node_modules/fast-glob": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", @@ -2446,6 +2579,11 @@ "url": "https://www.patreon.com/infusion" } }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -2548,6 +2686,11 @@ "git-format-staged": "git-format-staged" } }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, "node_modules/glob": { "version": "7.1.7", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", @@ -2745,6 +2888,25 @@ "react-is": "^16.7.0" } }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/ignore": { "version": "5.2.4", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", @@ -2792,6 +2954,11 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, "node_modules/internal-slot": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", @@ -3321,7 +3488,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -3354,6 +3520,17 @@ "node": ">=8.6" } }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/mini-svg-data-uri": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz", @@ -3378,11 +3555,15 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -3416,6 +3597,11 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -3491,6 +3677,22 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/node-abi": { + "version": "3.47.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.47.0.tgz", + "integrity": "sha512-2s6B2CWZM//kPgwnuI0KrYwNjfdByE25zvAaEpq9IH4zcNsarH8Ihu/UuX6XMPEogDAxkuUFeZn60pXNHAqn3A==", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-addon-api": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.1.0.tgz", + "integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==" + }, "node_modules/node-releases": { "version": "2.0.13", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", @@ -3915,6 +4117,57 @@ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, + "node_modules/prebuild-install": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz", + "integrity": "sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw==", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/prebuild-install/node_modules/tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/prebuild-install/node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -3949,6 +4202,15 @@ "react-is": "^16.13.1" } }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, "node_modules/punycode": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", @@ -3977,6 +4239,33 @@ } ] }, + "node_modules/queue-tick": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.1.tgz", + "integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==" + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/rc/node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/react": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", @@ -4048,6 +4337,19 @@ "pify": "^2.3.0" } }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -4198,6 +4500,25 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/safe-regex-test": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", @@ -4224,7 +4545,6 @@ "version": "7.5.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, "dependencies": { "lru-cache": "^6.0.0" }, @@ -4240,6 +4560,28 @@ "resolved": "https://registry.npmjs.org/server-only/-/server-only-0.0.1.tgz", "integrity": "sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA==" }, + "node_modules/sharp": { + "version": "0.32.5", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.32.5.tgz", + "integrity": "sha512-0dap3iysgDkNaPOaOL4X/0akdu0ma62GcdC2NBQ+93eqpePdDdr2/LM0sFdDSMmN7yS+odyZtPsb7tx/cYBKnQ==", + "hasInstallScript": true, + "dependencies": { + "color": "^4.2.3", + "detect-libc": "^2.0.2", + "node-addon-api": "^6.1.0", + "prebuild-install": "^7.1.1", + "semver": "^7.5.4", + "simple-get": "^4.0.1", + "tar-fs": "^3.0.4", + "tunnel-agent": "^0.6.0" + }, + "engines": { + "node": ">=14.15.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -4275,6 +4617,62 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", + "dependencies": { + "is-arrayish": "^0.3.1" + } + }, + "node_modules/simple-swizzle/node_modules/is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" + }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -4308,6 +4706,23 @@ "node": ">=10.0.0" } }, + "node_modules/streamx": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.15.1.tgz", + "integrity": "sha512-fQMzy2O/Q47rgwErk/eGeLu/roaFWV0jVsogDmrszM9uIw8L5OA+t+V93MgYlufNptfjmYR1tOMWhei/Eh7TQA==", + "dependencies": { + "fast-fifo": "^1.1.0", + "queue-tick": "^1.0.1" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, "node_modules/string.prototype.matchall": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz", @@ -4553,6 +4968,26 @@ "node": ">=6" } }, + "node_modules/tar-fs": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.4.tgz", + "integrity": "sha512-5AFQU8b9qLfZCX9zp2duONhPmZv0hGYiBPJsyUdqMjzq/mqVpy/rEUSeHk1+YitmxugaptgBh5oDGU3VsAJq4w==", + "dependencies": { + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^3.1.5" + } + }, + "node_modules/tar-stream": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.6.tgz", + "integrity": "sha512-B/UyjYwPpMBv+PaFSWAmtYjwdrlEaZQEhMIBFNC5oEG8lpiW8XjcSdmEaClj28ArfKScKHs2nshz3k2le6crsg==", + "dependencies": { + "b4a": "^1.6.4", + "fast-fifo": "^1.2.0", + "streamx": "^2.15.0" + } + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -4631,6 +5066,17 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -4923,8 +5369,7 @@ "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/yaml": { "version": "2.3.1", diff --git a/Website/package.json b/Website/package.json index a231edf6..4e8c44cd 100644 --- a/Website/package.json +++ b/Website/package.json @@ -25,6 +25,7 @@ "react-dom": "18.2.0", "react-select": "^5.7.4", "server-only": "^0.0.1", + "sharp": "^0.32.5", "swr": "^2.2.0", "tailwindcss": "3.3.2" }, diff --git a/Website/public/generic_rail_bound_vehicle.svg b/Website/public/generic_rail_bound_vehicle.svg deleted file mode 100644 index 17eff589..00000000 --- a/Website/public/generic_rail_bound_vehicle.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/Website/public/poiTypeIcons/generic.svg b/Website/public/poiTypeIcons/generic.svg new file mode 100644 index 00000000..df59a54e --- /dev/null +++ b/Website/public/poiTypeIcons/generic.svg @@ -0,0 +1,15 @@ + + + + \ No newline at end of file diff --git a/Website/public/poiTypeIcons/generic_rail_bound_vehicle.svg b/Website/public/poiTypeIcons/generic_rail_bound_vehicle.svg deleted file mode 100644 index 77dbbae4..00000000 --- a/Website/public/poiTypeIcons/generic_rail_bound_vehicle.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/Website/public/poiTypeIcons/lesser_level_crossing.svg b/Website/public/poiTypeIcons/lesser_level_crossing.svg index 72fa7632..7668b1b5 100644 --- a/Website/public/poiTypeIcons/lesser_level_crossing.svg +++ b/Website/public/poiTypeIcons/lesser_level_crossing.svg @@ -1,3 +1,15 @@ - - + + diff --git a/Website/public/poiTypeIcons/level_crossing.svg b/Website/public/poiTypeIcons/level_crossing.svg index a8fef462..6df9ce81 100644 --- a/Website/public/poiTypeIcons/level_crossing.svg +++ b/Website/public/poiTypeIcons/level_crossing.svg @@ -1,4 +1,18 @@ - - - + + + diff --git a/Website/public/poiTypeIcons/parking.svg b/Website/public/poiTypeIcons/parking.svg deleted file mode 100644 index 92372c0f..00000000 --- a/Website/public/poiTypeIcons/parking.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/Website/public/poiTypeIcons/passing_position.svg b/Website/public/poiTypeIcons/passing_position.svg new file mode 100644 index 00000000..fd8f8bde --- /dev/null +++ b/Website/public/poiTypeIcons/passing_position.svg @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + diff --git a/Website/public/poiTypeIcons/picnic.svg b/Website/public/poiTypeIcons/picnic.svg new file mode 100644 index 00000000..fa805ccf --- /dev/null +++ b/Website/public/poiTypeIcons/picnic.svg @@ -0,0 +1,20 @@ + + + + + + diff --git a/Website/public/poiTypeIcons/track_end.svg b/Website/public/poiTypeIcons/track_end.svg new file mode 100644 index 00000000..a1cbd278 --- /dev/null +++ b/Website/public/poiTypeIcons/track_end.svg @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + diff --git a/Website/public/poiTypeIcons/turning_point.svg b/Website/public/poiTypeIcons/turning_point.svg new file mode 100644 index 00000000..b7c6a228 --- /dev/null +++ b/Website/public/poiTypeIcons/turning_point.svg @@ -0,0 +1,22 @@ + + + + + diff --git a/Website/public/vehicle/Vehicle_background_neutral.svg b/Website/public/vehicle/Vehicle_background_neutral.svg index 69b69302..8df92c0c 100644 --- a/Website/public/vehicle/Vehicle_background_neutral.svg +++ b/Website/public/vehicle/Vehicle_background_neutral.svg @@ -1,3 +1,3 @@ - + diff --git a/Website/public/vehicle/Vehicle_background_heading.svg b/Website/public/vehicle/Vehicle_heading.svg similarity index 77% rename from Website/public/vehicle/Vehicle_background_heading.svg rename to Website/public/vehicle/Vehicle_heading.svg index a0e7b9bd..390883fc 100644 --- a/Website/public/vehicle/Vehicle_background_heading.svg +++ b/Website/public/vehicle/Vehicle_heading.svg @@ -1,4 +1,3 @@ - diff --git a/Website/src/app/components/dynlist.tsx b/Website/src/app/components/dynlist.tsx index c903f5f6..2e084af3 100644 --- a/Website/src/app/components/dynlist.tsx +++ b/Website/src/app/components/dynlist.tsx @@ -53,25 +53,25 @@ export default function DynamicList({ server_vehicles, track_id, logged_in, trac - - - - - - + + + + + + {sorted_vehicles?.map(v => ( - - - diff --git a/Website/src/app/components/iconSelection.tsx b/Website/src/app/components/iconSelection.tsx index 55c32cfc..d21514ee 100644 --- a/Website/src/app/components/iconSelection.tsx +++ b/Website/src/app/components/iconSelection.tsx @@ -1,13 +1,10 @@ import Select, { Options, SingleValue } from "react-select"; import { Option } from "@/utils/types"; import { useMemo } from "react"; +import { POIIconCommonName, POIIconImg } from "@/utils/common"; +import { POITypeIcon, POITypeIconValues } from "@/utils/api"; -export const icons = [ - { path: "/poiTypeIcons/generic_rail_bound_vehicle.svg", name: "Schienenfahrzeug" }, - { path: "/poiTypeIcons/level_crossing.svg", name: "Bahnübergang" }, - { path: "/poiTypeIcons/lesser_level_crossing.svg", name: "Unbeschilderter Bahnübergang" }, - { path: "/poiTypeIcons/parking.svg", name: "Haltepunkt" } -]; +const POI_ICONS: POITypeIcon[] = Object.values(POITypeIconValues); /** * A consolidated icon selection component @@ -20,27 +17,29 @@ export default function IconSelection({ id, name }: { - currentIcon: string; - setIcon: (newIcon: string) => void; + currentIcon: POITypeIcon | ""; + setIcon: (newIcon: POITypeIcon | "") => void; setModified?: (modified: boolean) => void; className?: string; id: string; name: string; }) { - const iconOptions: Options> = useMemo( + const iconOptions: Options> = useMemo( () => - icons.map(i => ({ - value: i.path, + POI_ICONS.map(i => ({ + value: i, label: ( -
- {i.name} -
{i.name}
+
+
+ {POIIconCommonName[i]} +
+
{POIIconCommonName[i]}
) })), [] ); - const defaultIcon: Option = useMemo( + const defaultIcon: Option<""> = useMemo( () => ({ value: "", label: ( @@ -52,14 +51,14 @@ export default function IconSelection({ [] ); - const icon = useMemo( + const icon: Option = useMemo( () => iconOptions.find(v => v.value === currentIcon) ?? defaultIcon, [currentIcon, iconOptions, defaultIcon] ); console.log("Icon for", currentIcon, icon); - function changeFunction(newValue: SingleValue>) { - if (newValue) { + function changeFunction(newValue: SingleValue>) { + if (newValue && newValue.value !== "") { setIcon(newValue.value); setModified ? setModified(true) : undefined; } diff --git a/Website/src/app/components/login_wrap.tsx b/Website/src/app/components/login_wrap.tsx index c307fbcb..0ee1fa64 100644 --- a/Website/src/app/components/login_wrap.tsx +++ b/Website/src/app/components/login_wrap.tsx @@ -1,8 +1,8 @@ -"use client" -import {IMapRefreshConfig} from "@/utils/types"; -import {useState} from "react"; -import {LoginDialog} from "@/app/components/login"; -import {SelectionDialog} from "@/app/components/track_selection"; +"use client"; +import { IMapRefreshConfig } from "@/utils/types"; +import { useState } from "react"; +import { LoginDialog } from "@/app/components/login"; +import { SelectionDialog } from "@/app/components/track_selection"; /** * Component wrapping some other component with a login- and track selection dialog and keeping track of login state. @@ -11,21 +11,37 @@ import {SelectionDialog} from "@/app/components/track_selection"; * @param map_conf parameters for the construction of the child * @param child Function contructing the wrapped React Component. */ -const LoginWrapper = ({logged_in, track_selected, map_conf, child}: {logged_in: boolean, track_selected: boolean, map_conf: IMapRefreshConfig, child: (conf: IMapRefreshConfig) => JSX.Element}) => { - const [loginState, setLogin] = useState(logged_in); +const LoginWrapper = ({ + logged_in, + track_selected, + map_conf, + child +}: { + logged_in: boolean; + track_selected: boolean; + map_conf: IMapRefreshConfig; + child: (conf: IMapRefreshConfig) => JSX.Element; +}) => { + const [loginState, setLogin] = useState(logged_in); - // console.log('track selected', track_selected, map_conf.track_id) + // console.log('track selected', track_selected, map_conf.track_id) - return <> - {!loginState && - -

You need to log in!

-
} - {loginState && !track_selected && -

Please select a track!

-
} - {child({...map_conf, logged_in: loginState, setLogin: setLogin})} - -} + return ( + <> + {!loginState ? ( + +

Sie müssen sich einloggen!

+
+ ) : ( + !track_selected && ( + +

Bitte wählen Sie eine Strecke aus

+
+ ) + )} + {child({ ...map_conf, logged_in: loginState, setLogin: setLogin })} + + ); +}; -export default LoginWrapper; \ No newline at end of file +export default LoginWrapper; diff --git a/Website/src/app/components/map.tsx b/Website/src/app/components/map.tsx index 89a94c14..d044ac66 100644 --- a/Website/src/app/components/map.tsx +++ b/Website/src/app/components/map.tsx @@ -8,7 +8,8 @@ import { coordinateFormatter } from "@/utils/helpers"; import assert from "assert"; import { createPortal } from "react-dom"; import RotatingVehicleIcon from "@/utils/rotatingIcon"; -import { PointOfInterest, POIType } from "@/utils/api"; +import { PointOfInterest, POIType, POITypeIconValues } from "@/utils/api"; +import { POIIconImg } from "@/utils/common"; function poiPopupFactory(poi: PointOfInterest, poi_type?: POIType): HTMLDivElement { const container = document.createElement("div"); @@ -48,10 +49,19 @@ function Map({ // find the vehicle that is in focus, but only if either the vehicles, or the focus changes. const vehicleInFocus = useMemo(() => vehicles.find(v => v.id == focus), [vehicles, focus]); - // create icons for each poi type - const enriched_poi_types: (POIType & {leaf_icon: L.Icon})[] = useMemo( - () => poi_types.map(pt => ({ ...pt, leaf_icon: L.icon({ iconUrl: pt.icon, iconSize: [45, 45] }) })), + const enriched_poi_types: (POIType & { leaf_icon: L.Icon })[] = useMemo( + () => + poi_types.map(pt => { + const icon_src = POIIconImg[pt.icon] ?? POIIconImg[POITypeIconValues.Generic]; + console.log("poi_icon for", pt.name, pt.icon, "at", icon_src); + const leaf_icon = L.icon({ iconUrl: icon_src, iconSize: [45, 45] }); + + return { + ...pt, + leaf_icon + }; + }), [poi_types] ); diff --git a/Website/src/app/list/page.tsx b/Website/src/app/list/page.tsx index 2fe61278..fb2d82c7 100644 --- a/Website/src/app/list/page.tsx +++ b/Website/src/app/list/page.tsx @@ -28,7 +28,7 @@ export default async function Home() { console.log("server vehicles", server_vehicles); return (
-
+
); // TODO: handle fetching errors - assert(!err); + assert(true || !err); const initialPos = L.latLng({ lat: 54.2333, lng: 10.6024 }); @@ -44,7 +44,6 @@ export default function POIManagement({ poiTypes, tracks }: { poiTypes: POIType[ const [poiType, setPoiType] = useState(""); const [poiDescription, setPoiDescription] = useState(""); const [poiPosition, setPoiPosition] = useState(initialPos); - const [poiIsTurningPoint, setPoiIsTurningPoint] = useState(false); /** modified: A "dirty flag" to prevent loosing information. */ const [modified, setModified] = useState(false); @@ -69,7 +68,7 @@ export default function POIManagement({ poiTypes, tracks }: { poiTypes: POIType[ const updatePayload: UpdatePointOfInterest = { id: selPoi.value === "" ? undefined : selPoi.value, - isTurningPoint: poiIsTurningPoint, + isTurningPoint: false, pos: apiPos, trackId: +poiTrack, name: poiName, @@ -161,7 +160,6 @@ export default function POIManagement({ poiTypes, tracks }: { poiTypes: POIType[ setPoiTrack("" + (selectedPOI?.trackId ?? "")); setPoiType("" + (selectedPOI?.typeId ?? "")); setPoiDescription(selectedPOI?.description ?? ""); - setPoiIsTurningPoint(selectedPOI?.isTurningPoint ?? false); setPoiPosition(selectedPOI?.pos ? L.latLng(selectedPOI?.pos) : initialPos); // Also reset the "dirty flag" setModified(false); @@ -186,14 +184,32 @@ export default function POIManagement({ poiTypes, tracks }: { poiTypes: POIType[ name={"selPoi"} className="col-span-5 border border-gray-500 dark:bg-slate-700 rounded" options={poiOptions} + unstyled={true} classNames={ /* The zoom controls of the leaflet map use a z-index of 1000. So to display the select dropdown in front of the map, we need the z-index to be > 1000. - Unfortionately, react-select sets the z-index to 1, without an obvious way + Unfortunately, react-select sets the z-index to 1, without an obvious way to change this, so we use an important class. + The same applies to background color, which is why we need to set that one + important for proper dark-mode support... */ - { menu: () => "!z-1100" } + { + menu: () => "!z-1100 dark:bg-slate-700 bg-white my-2 rounded-md drop-shadow-lg", + valueContainer: () => "mx-3", + dropdownIndicator: () => "m-2 text-gray-500 transition-colors hover:dark:text-gray-50 hover:text-gray-950", + indicatorSeparator: () => "bg-gray-200 dark:bg-gray-500 my-2", + menuList: () => "py-1", + option: (state) => { + if (state.isSelected) { + return "px-3 py-2 dark:bg-blue-200 dark:text-black bg-blue-800 text-white"; + } else if (state.isFocused) { + return "px-3 py-2 bg-blue-100 dark:bg-blue-900"; + } else { + return "px-3 py-2"; + } + } + } } />
Namegeog. Breitegeog. LängeRichtungBatterieladungAuf Karte anzeigenNameBatterieladungAuf Karte anzeigen
{v.name} + + + {{}.toString()}