diff --git a/app.py b/app.py
index db56645..22619e8 100644
--- a/app.py
+++ b/app.py
@@ -33,23 +33,6 @@ print("initialize database")
engine = db_connect()
SessionFactory = sessionmaker(bind=engine)
session = SessionFactory()
-create_table(engine)
-
-print("pushing initial data if not already happened")
-try:
- defDriver = session.query(Driver).filter(id=1)
- defVehicle = session.query(Vehicle).filter(id=1)
- if not defDriver and not defVehicle:
- defaultVehicle = Vehicle(id=1, name="default", licenseplate="default")
- defaultDriver = Driver(id=1, name="default")
-
- session.add(defaultVehicle)
- session.add(defaultDriver)
- session.commit()
- session.flush()
-except:
- print("default data not pushed as already present")
-session.flush()
print("initialize handlers")
gpxHandler = GPXHandler(session)
@@ -278,7 +261,7 @@ def handleVehicleRoute():
vehicleHandler.deleteVehicle(data["id"])
return "vehicle deleted", 200
except Exception as e:
- return f"couldnt delete vehicle due to error: {e}", 500
+ return f"couldn't delete vehicle due to error: {e}", 500
@app.route('/upload', methods=['POST'])
diff --git a/compose.yaml b/compose.yaml
index ca88985..9ba25d2 100644
--- a/compose.yaml
+++ b/compose.yaml
@@ -17,6 +17,8 @@ services:
POSTGRES_USER: example
POSTGRES_PASSWORD: example
POSTGRES_DB: geotrack
+ volumes:
+ - ./init.sql:/docker-entrypoint-initdb.d/init.sql
# web:
# build: .
# ports:
diff --git a/init.sql b/init.sql
new file mode 100644
index 0000000..e9ec7e1
--- /dev/null
+++ b/init.sql
@@ -0,0 +1,67 @@
+-- Adminer 4.8.1 PostgreSQL 16.4 (Debian 16.4-1.pgdg120+1) dump
+
+DROP TABLE IF EXISTS "driver";
+DROP SEQUENCE IF EXISTS driver_id_seq;
+CREATE SEQUENCE driver_id_seq INCREMENT 1 MINVALUE 1 MAXVALUE 2147483647 CACHE 1;
+
+CREATE TABLE "public"."driver" (
+ "id" integer DEFAULT nextval('driver_id_seq') NOT NULL,
+ "name" character varying NOT NULL,
+ CONSTRAINT "driver_pkey" PRIMARY KEY ("id")
+) WITH (oids = false);
+
+INSERT INTO "driver" ("id", "name") VALUES
+(1, 'default');
+
+DROP TABLE IF EXISTS "track";
+DROP SEQUENCE IF EXISTS track_id_seq;
+CREATE SEQUENCE track_id_seq INCREMENT 1 MINVALUE 1 MAXVALUE 2147483647 CACHE 1;
+
+CREATE TABLE "public"."track" (
+ "id" integer DEFAULT nextval('track_id_seq') NOT NULL,
+ "trackName" character varying(200),
+ "vehicle_id" integer NOT NULL,
+ "driver_id" integer NOT NULL,
+ "date" date,
+ "distance" double precision NOT NULL,
+ "speed" double precision NOT NULL,
+ CONSTRAINT "track_pkey" PRIMARY KEY ("id")
+) WITH (oids = false);
+
+
+DROP TABLE IF EXISTS "vehicle";
+DROP SEQUENCE IF EXISTS vehicle_id_seq;
+CREATE SEQUENCE vehicle_id_seq INCREMENT 1 MINVALUE 1 MAXVALUE 2147483647 CACHE 1;
+
+CREATE TABLE "public"."vehicle" (
+ "id" integer DEFAULT nextval('vehicle_id_seq') NOT NULL,
+ "name" character varying NOT NULL,
+ "licenseplate" character varying,
+ CONSTRAINT "vehicle_pkey" PRIMARY KEY ("id")
+) WITH (oids = false);
+
+INSERT INTO "vehicle" ("id", "name", "licenseplate") VALUES
+(1, 'default', 'default');
+
+DROP TABLE IF EXISTS "waypoint";
+DROP SEQUENCE IF EXISTS waypoint_id_seq;
+CREATE SEQUENCE waypoint_id_seq INCREMENT 1 MINVALUE 1 MAXVALUE 2147483647 CACHE 1;
+
+CREATE TABLE "public"."waypoint" (
+ "id" integer DEFAULT nextval('waypoint_id_seq') NOT NULL,
+ "lat" double precision NOT NULL,
+ "lon" double precision NOT NULL,
+ "ele" double precision NOT NULL,
+ "speed" double precision,
+ "time" timestamp,
+ "track_id" integer NOT NULL,
+ CONSTRAINT "waypoint_pkey" PRIMARY KEY ("id")
+) WITH (oids = false);
+
+
+ALTER TABLE ONLY "public"."track" ADD CONSTRAINT "track_driver_id_fkey" FOREIGN KEY (driver_id) REFERENCES driver(id) NOT DEFERRABLE;
+ALTER TABLE ONLY "public"."track" ADD CONSTRAINT "track_vehicle_id_fkey" FOREIGN KEY (vehicle_id) REFERENCES vehicle(id) NOT DEFERRABLE;
+
+ALTER TABLE ONLY "public"."waypoint" ADD CONSTRAINT "waypoint_track_id_fkey" FOREIGN KEY (track_id) REFERENCES track(id) NOT DEFERRABLE;
+
+-- 2025-01-16 09:13:38.732525+00
\ No newline at end of file
diff --git a/web/src/App.vue b/web/src/App.vue
index eb50392..29a2c26 100644
--- a/web/src/App.vue
+++ b/web/src/App.vue
@@ -39,7 +39,7 @@ export default defineComponent({
-
+
diff --git a/web/src/components/cookiePrompt.vue b/web/src/components/cookiePrompt.vue
index 5199ca0..00cd7d9 100644
--- a/web/src/components/cookiePrompt.vue
+++ b/web/src/components/cookiePrompt.vue
@@ -8,10 +8,12 @@ export default defineComponent({
setup(_, { emit }: SetupContext) {
function acceptCookies(){
+ emit("close")
localStorage.setItem("allow-data-storage", "true")
}
function rejectCookies(){
+ emit("close")
localStorage.setItem("allow-data-storage", "false")
}
diff --git a/web/src/components/fileUpload.vue b/web/src/components/fileUpload.vue
index cd51537..5048547 100644
--- a/web/src/components/fileUpload.vue
+++ b/web/src/components/fileUpload.vue
@@ -81,6 +81,8 @@ export default defineComponent({
drivers.value.push({ id: jsonBody[i]["id"], name: jsonBody[i]["name"] })
}
} else {
+
+ alert(`upload failed: ${await response.text()}`)
console.log(await response.text())
messageType.value = "error";
message.value = `upload failed: ${await response.statusText}`;
@@ -98,8 +100,8 @@ export default defineComponent({
headers: headers
})
+ // make sure the request was successful
var response = await fetch(request)
- // make sure the request was successfull
if (response.ok) {
var jsonBody = await response.json()
@@ -108,6 +110,8 @@ export default defineComponent({
vehicles.value.push({ id: jsonBody[i]["id"], name: jsonBody[i]["name"] })
}
} else {
+
+ alert(`upload failed: ${await response.text()}`)
console.log(await response.text())
messageType.value = "error";
message.value = `upload failed: ${await response.text()}`;
@@ -118,6 +122,8 @@ export default defineComponent({
var save = async () => {
if (!file.value) {
+
+ alert("please select a file");
messageType.value = "warning";
message.value = "please select a file";
return;
@@ -142,19 +148,25 @@ export default defineComponent({
if (response.ok) {
const result = await response.json();
emit("response", result);
+
messageType.value = "success";
- message.value = `upload successfull`;
- buttonText.value = 'upload successfull';
+ message.value = `Upload Successful`;
+ buttonText.value = 'Upload Successful';
+
setTimeout(() => {
buttonText.value = "Upload";
}, 2000);
} else {
+
+ alert(`upload failed: ${await response.statusText}`)
console.error('upload failed: ', await response.statusText);
messageType.value = "error";
message.value = `upload failed: ${await response.statusText}`;
buttonText.value = "Upload";
}
} catch (error) {
+
+ alert(`upload failed: ${error}`)
messageType.value = "error";
message.value = `upload failed: ${error}`;
buttonText.value = "Upload";
diff --git a/web/src/components/map.vue b/web/src/components/map.vue
index 2504dc2..fd7b871 100644
--- a/web/src/components/map.vue
+++ b/web/src/components/map.vue
@@ -96,8 +96,10 @@ export default defineComponent({
}
console.log(track.value)
} else {
+
+ alert(`failed to load track meta with error: ${await response.statusText}`)
messageType.value = "error";
- message.value = `"failed to load track meta with error: ${await response.statusText}`;
+ message.value = `failed to load track meta with error: ${await response.statusText}`;
}
}
@@ -122,6 +124,8 @@ export default defineComponent({
const bounds = geoJsonLayer.getBounds();
mapInstance.value.fitBounds(bounds);
} else {
+
+ alert("Map or GeoJSON data not available.")
console.error("Map or GeoJSON data not available.");
messageType.value = "error";
message.value = `"Map or GeoJSON data not available.`;
@@ -160,7 +164,9 @@ export default defineComponent({
- {{ track.name }} |
+
+
+ |
|
diff --git a/web/src/components/message.vue b/web/src/components/message.vue
index 7d0230d..a6af3b9 100644
--- a/web/src/components/message.vue
+++ b/web/src/components/message.vue
@@ -25,19 +25,19 @@ export default defineComponent({
-
+
{{ message }}
-
+
{{ message }}
-
+
{{ message }}
-
+
{{ message }}
diff --git a/web/src/components/pointcloud.vue b/web/src/components/pointcloud.vue
index 3dacb12..6e4bfb7 100644
--- a/web/src/components/pointcloud.vue
+++ b/web/src/components/pointcloud.vue
@@ -45,6 +45,8 @@ export default defineComponent({
console.log(props)
if (!props.routes || props.routes.length <= 0) {
+
+ alert("no points to show")
messageType.value = "error";
message.value = `no points to show`;
}
@@ -80,6 +82,8 @@ export default defineComponent({
legend.value[driver["id"]] = driver["name"];
}
} else {
+
+ alert(`failed to get drivers with error: ${await response.statusText}`)
console.log(await response.text())
messageType.value = "error";
message.value = `failed to get drivers with error: ${await response.statusText}`;
@@ -253,7 +257,30 @@ export default defineComponent({
}
}
+ /**
+ * Handles mouse clicks to navigate to the specific track page
+ * @param event MouseEvent triggered on click
+ */
+ const onMouseClick = (event: MouseEvent) => {
+ if (!canvasRef.value) return;
+
+ raycaster.setFromCamera(mouse, camera);
+ const intersects = raycaster.intersectObject(pointCloud);
+
+ if (intersects.length > 0) {
+ const intersectIndex = Math.floor(intersects[0].index || 0);
+ const point = points[intersectIndex];
+
+ console.log(point.id)
+
+ // Redirect to /track/:id using Vue Router
+ router.push(`/track/${point.id}`);
+ }
+ };
+
+ // Add event listeners for mouse actions
canvasRef.value.addEventListener("mousemove", onMouseMove);
+ canvasRef.value.addEventListener("click", onMouseClick);
// Fenstergröße anpassen
window.addEventListener("resize", () => {
@@ -278,7 +305,8 @@ export default defineComponent({
-
+
diff --git a/web/src/views/driver.vue b/web/src/views/driver.vue
index 4ea2cbc..b3ed316 100644
--- a/web/src/views/driver.vue
+++ b/web/src/views/driver.vue
@@ -14,7 +14,7 @@ export default defineComponent({
const driverList: Ref
= ref([])
// values for UI Information distribution
- const messageType: Ref = ref("");
+ const messageType: Ref = ref("error");
const message: Ref = ref("");
// handles delete a driver
@@ -33,13 +33,17 @@ export default defineComponent({
var response = await fetch(request)
if (!response.ok) {
- console.log(await response.text())
+
+ alert(`deleting driver failed with error: ${await response.text()}`)
messageType.value = "error";
message.value = `deleting driver failed with error: ${await response.text()}`;
} else {
- console.log(await response.text())
+
+ alert("deleted driver successful")
messageType.value = "success";
message.value = `deleted driver`;
+ driverList.value = []
+ getDrivers();
}
}
@@ -68,7 +72,8 @@ export default defineComponent({
driverList.value.push({ id: jsonBody[i]["id"], name: jsonBody[i]["name"] })
}
} else {
- console.log(await response.text())
+
+ alert(`upload failed: ${response.text()}`)
messageType.value = "error";
message.value = `upload failed: ${response.text()}`;
}
@@ -95,9 +100,10 @@ export default defineComponent({
var jsonBody = await response.json()
driverList.value.push({ id: jsonBody["body"], name: driverName.value })
} else {
- console.log(await response.text())
+
+ alert(`creating driver: ${response.text()}`)
messageType.value = "error";
- message.value = `upload failed: ${response.text()}`;
+ message.value = `creating driver: ${response.text()}`;
}
}
@@ -116,8 +122,7 @@ export default defineComponent({
-
-
+
diff --git a/web/src/views/route.vue b/web/src/views/route.vue
index ef7335d..c5cb2ac 100644
--- a/web/src/views/route.vue
+++ b/web/src/views/route.vue
@@ -81,11 +81,15 @@ export default defineComponent({
// Wenn die Antwort OK ist, die Daten verarbeiten
mapData.value = await response.json();
} else {
+
+ alert(`loading tracks failed: ${await response.text()}`)
console.log(await response.text());
messageType.value = "error";
message.value = `loading tracks failed: ${await response.text()}`;
}
} catch (error) {
+
+ alert(`loading tracks failed with error: ${error}`)
console.error("loading tracks failed with error:", error);
messageType.value = "error";
message.value = `loading tracks failed with error: ${error}`;
@@ -114,6 +118,8 @@ export default defineComponent({
message.value = `deleting track failed with error: ${await response.text()}`;
getTracks()
} else {
+
+ alert("deleted track")
console.log(await response.text())
messageType.value = "success";
message.value = `deleted track`;
@@ -141,6 +147,8 @@ export default defineComponent({
tracks.value.push({ id: jsonBody[i]["id"], name: jsonBody[i]["name"], driver: { name: "", id: 0 }, time: new Date(Date.now()) })
}
} else {
+
+ alert(`loading track list failed with error: ${error}`)
console.log(await response.text())
messageType.value = "error";
message.value = `loading track list failed with error: ${error}`;
@@ -193,7 +201,8 @@ export default defineComponent({
showCloud.value = true;
} else {
- console.log(await response.text())
+
+ alert(`searching tracks failed: ${await response.text()}`)
messageType.value = "error";
message.value = `searching tracks failed: ${await response.text()}`;
}
@@ -242,7 +251,7 @@ export default defineComponent({
-