feat: ✨ implemented visual messaging
This commit is contained in:
parent
20ac0faa75
commit
5769fabce4
48
app.py
48
app.py
@ -40,17 +40,21 @@ gpxHandler = GPXHandler(session)
|
||||
driverHandler = DriverHandler(session)
|
||||
vehicleHandler = VehicleHandler(session)
|
||||
|
||||
|
||||
@app.route('/')
|
||||
@cross_origin()
|
||||
def serve_vue_app():
|
||||
return send_from_directory(app.static_folder, 'index.html')
|
||||
|
||||
@app.route("/track", methods=['GET'])
|
||||
|
||||
@app.route("/track", methods=['GET', 'DELETE'])
|
||||
@cross_origin()
|
||||
def getTrack():
|
||||
|
||||
app.logger.debug(f"found arguments {request.args}")
|
||||
|
||||
match request.method:
|
||||
case "GET":
|
||||
if ("start" in request.args and "end" in request.args) or ("id" in request.args):
|
||||
if "start" in request.args and "end" in request.args:
|
||||
if "asMap" in request.args:
|
||||
@ -59,7 +63,8 @@ def getTrack():
|
||||
end = request.args["end"]
|
||||
|
||||
# Die GeoJSON-Daten aus der Datenbank abrufen
|
||||
geojson_data = gpxHandler.getTracksInTimeWithGeoData(start, end)
|
||||
geojson_data = gpxHandler.getTracksInTimeWithGeoData(
|
||||
start, end)
|
||||
app.logger.debug(f"returned track {geojson_data}")
|
||||
|
||||
# Die GeoJSON-Daten als JSON zurückgeben
|
||||
@ -71,7 +76,8 @@ def getTrack():
|
||||
try:
|
||||
return gpxHandler.getTracksInTime(start, request.args["end"]), 200
|
||||
except Exception as e:
|
||||
app.logger.debug(f"failed to search tracks error {e} values: start={start}, end={end}")
|
||||
app.logger.debug(f"failed to search tracks error {
|
||||
e} values: start={start}, end={end}")
|
||||
return f"error {e}", 500
|
||||
|
||||
elif "id" in request.args:
|
||||
@ -99,6 +105,9 @@ def getTrack():
|
||||
except Exception as e:
|
||||
app.logger.debug(f"fetching all tracks failed with error {e}")
|
||||
return f"error {e}", 500
|
||||
case "DELETE":
|
||||
pass
|
||||
|
||||
|
||||
@app.route("/track/meta", methods=['GET'])
|
||||
@cross_origin()
|
||||
@ -121,11 +130,13 @@ def getTrackMeta():
|
||||
app.logger.debug(f"fetching track failed with error {e}")
|
||||
return f"error {e}", 500
|
||||
|
||||
@app.route("/driver", methods=['GET', 'POST'])
|
||||
|
||||
@app.route("/driver", methods=['GET', 'POST', 'PUT', 'DELETE'])
|
||||
@cross_origin()
|
||||
def handleDriverRoute():
|
||||
|
||||
if request.method == "GET":
|
||||
match request.method:
|
||||
case "GET":
|
||||
if 'driver' in request.args:
|
||||
|
||||
try:
|
||||
@ -144,9 +155,7 @@ def handleDriverRoute():
|
||||
except Exception as e:
|
||||
app.logger.debug(f"getting drivers failed with error {e}")
|
||||
return "error" + " " + str(e), 500
|
||||
|
||||
elif request.method == "POST":
|
||||
|
||||
case "POST":
|
||||
# grabbing json from request
|
||||
data = request.get_json()
|
||||
app.logger.debug(f"json request payload: {data}")
|
||||
@ -166,13 +175,18 @@ def handleDriverRoute():
|
||||
except Exception as e:
|
||||
app.logger.debug(f"creating drivers failed with error {e}")
|
||||
return "error" + " " + str(e), 500
|
||||
case "PUT":
|
||||
pass
|
||||
case "DELETE":
|
||||
pass
|
||||
|
||||
|
||||
@app.route("/vehicle", methods=['GET', 'POST'])
|
||||
@app.route("/vehicle", methods=['GET', 'POST', 'PUT', 'DELETE'])
|
||||
@cross_origin()
|
||||
def handleVehicleRoute():
|
||||
|
||||
if request.method == "GET":
|
||||
match request.method:
|
||||
case "GET":
|
||||
if 'vehicle' in request.args:
|
||||
app.logger.debug(f"no vehicle id was found in request")
|
||||
vehicle = int(request.args["vehicle"])
|
||||
@ -190,10 +204,10 @@ def handleVehicleRoute():
|
||||
foundVehicles = vehicleHandler.getVehicles()
|
||||
return foundVehicles, 200
|
||||
except Exception as e:
|
||||
app.logger.debug(f"getting all vehicles failed with error {e}")
|
||||
app.logger.debug(
|
||||
f"getting all vehicles failed with error {e}")
|
||||
return "error" + " " + str(e), 500
|
||||
|
||||
elif request.method == "POST":
|
||||
case "POST":
|
||||
data = request.get_json()
|
||||
app.logger.debug(f"json request payload: {data}")
|
||||
|
||||
@ -216,6 +230,10 @@ def handleVehicleRoute():
|
||||
except Exception as e:
|
||||
app.logger.debug(f"creating vehicle with name {name} failed with error {e}")
|
||||
return "error" + " " + str(e), 500
|
||||
case "PUT":
|
||||
pass
|
||||
case "DELETE":
|
||||
pass
|
||||
|
||||
|
||||
@app.route('/upload', methods=['POST'])
|
||||
@ -231,9 +249,9 @@ def uploadFile():
|
||||
return "no file selected", 400
|
||||
|
||||
try:
|
||||
|
||||
app.logger.debug(f"Received file: {file.filename}, size: {len(file.read())} bytes")
|
||||
file.seek(0) # Setzt den Datei-Zeiger zurück, nachdem die Größe abgerufen wurde.
|
||||
|
||||
file.seek(0)
|
||||
|
||||
file_path = f'./uploads/{file.filename}'
|
||||
with open(file_path, 'wb') as f:
|
||||
|
@ -1,6 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { defineComponent, SetupContext, ref, Ref } from 'vue';
|
||||
import GetLocalizedText from "../classes/language";
|
||||
import Message from "./message.vue";
|
||||
|
||||
type driver = {
|
||||
id: number
|
||||
@ -15,6 +16,7 @@ type vehicle = {
|
||||
|
||||
export default defineComponent({
|
||||
emits: ['close', 'response'],
|
||||
components: { Message },
|
||||
name: 'settings',
|
||||
props: ["drivers"],
|
||||
setup(props, { emit }: SetupContext) {
|
||||
@ -28,6 +30,13 @@ export default defineComponent({
|
||||
const selectedDriverName: Ref<String> = ref("N/A");
|
||||
const selectedVehicleName: Ref<String> = ref("N/A");
|
||||
|
||||
// button text
|
||||
const buttonText: Ref<string> = ref('Upload');
|
||||
|
||||
// values for UI Information distribution
|
||||
const messageType: Ref<string> = ref("None ");
|
||||
const message:Ref<string> = ref("");
|
||||
|
||||
props.drivers.forEach((d: driver) => {
|
||||
drivers.value.push({ id: d.id, name: d.name })
|
||||
});
|
||||
@ -73,6 +82,8 @@ export default defineComponent({
|
||||
}
|
||||
} else {
|
||||
console.log(await response.text())
|
||||
messageType.value = "error";
|
||||
message.value = `upload failed: ${await response.statusText}`;
|
||||
}
|
||||
}
|
||||
|
||||
@ -98,13 +109,17 @@ export default defineComponent({
|
||||
}
|
||||
} else {
|
||||
console.log(await response.text())
|
||||
messageType.value = "error";
|
||||
message.value = `upload failed: ${await response.text()}`;
|
||||
buttonText.value = "Upload";
|
||||
}
|
||||
}
|
||||
|
||||
var save = async () => {
|
||||
|
||||
if (!file.value) {
|
||||
alert("Bitte wählen Sie eine Datei aus, bevor Sie sie hochladen.");
|
||||
messageType.value = "warning";
|
||||
message.value = "please fill all values";
|
||||
return;
|
||||
}
|
||||
|
||||
@ -113,6 +128,8 @@ export default defineComponent({
|
||||
formData.append("driverID", selectedDriverID.value.toString());
|
||||
formData.append("vehicleID", selectedVehicleID.value.toString());
|
||||
|
||||
buttonText.value = 'Loading <span class="loading loading-spinner loading-xs"></span>';
|
||||
|
||||
try {
|
||||
|
||||
console.log('Request Body:', formData);
|
||||
@ -125,15 +142,19 @@ export default defineComponent({
|
||||
if (response.ok) {
|
||||
const result = await response.json();
|
||||
emit("response", result);
|
||||
alert("Datei erfolgreich hochgeladen!");
|
||||
messageType.value = "success";
|
||||
message.value = `upload successfull`;
|
||||
buttonText.value = "Upload";
|
||||
} else {
|
||||
console.error('Fehler beim Hochladen:', response.statusText);
|
||||
alert("Fehler beim Hochladen der Datei.");
|
||||
console.error('upload failed: ', await response.statusText);
|
||||
messageType.value = "error";
|
||||
message.value = `upload failed: ${await response.statusText}`;
|
||||
buttonText.value = "Upload";
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error("upload failed:", error);
|
||||
alert("failed to upload file.");
|
||||
messageType.value = "error";
|
||||
message.value = `upload failed: ${error}`;
|
||||
buttonText.value = "Upload";
|
||||
}
|
||||
|
||||
}
|
||||
@ -155,7 +176,10 @@ export default defineComponent({
|
||||
save,
|
||||
drivers,
|
||||
vehicles,
|
||||
localizedUploadHeader
|
||||
localizedUploadHeader,
|
||||
buttonText,
|
||||
messageType,
|
||||
message
|
||||
};
|
||||
},
|
||||
});
|
||||
@ -167,10 +191,12 @@ export default defineComponent({
|
||||
<div class="card-body">
|
||||
|
||||
<h2 class="card-title">File Upload</h2>
|
||||
|
||||
<Message v-if="type=='none'" :type="messageType" :message="message" @close="message=''; messageType='None'"></Message>
|
||||
<button class="btn btn-error close round" @click="close()">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#e8eaed">
|
||||
<path d="m256-200-56-56 224-224-224-224 56-56 224 224 224-224 56 56-224 224 224 224-56 56-224-224-224 224Z" />
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px"
|
||||
fill="#e8eaed">
|
||||
<path
|
||||
d="m256-200-56-56 224-224-224-224 56-56 224 224 224-224 56 56-224 224 224 224-56 56-224-224-224 224Z" />
|
||||
</svg>
|
||||
</button>
|
||||
<label class="form-control w-full max-w-xs">
|
||||
@ -183,16 +209,20 @@ export default defineComponent({
|
||||
<div class="dropdown dropdown-bottom">
|
||||
select Driver: <div tabindex="0" role="button" class="btn m-1"> {{ selectedDriverName }}</div>
|
||||
<ul tabindex="0" class="dropdown-content menu bg-base-100 rounded-box z-[1] w-52 p-2 shadow">
|
||||
<li v-for="driver in drivers"><a v-on:click="selectedDriverID = driver.id; selectedDriverName=driver.name">{{ driver.name }}</a></li>
|
||||
<li v-for="driver in drivers"><a
|
||||
v-on:click="selectedDriverID = driver.id; selectedDriverName = driver.name">{{ driver.name
|
||||
}}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="dropdown dropdown-bottom">
|
||||
select Vehicle: <div tabindex="0" role="button" class="btn m-1"> {{ selectedVehicleName }}</div>
|
||||
<ul tabindex="0" class="dropdown-content menu bg-base-100 rounded-box z-[1] w-52 p-2 shadow">
|
||||
<li v-for="vehicle in vehicles"><a v-on:click="selectedVehicleID = vehicle.id; selectedVehicleName=vehicle.name">{{ vehicle.name }}</a></li>
|
||||
<li v-for="vehicle in vehicles"><a
|
||||
v-on:click="selectedVehicleID = vehicle.id; selectedVehicleName = vehicle.name">{{
|
||||
vehicle.name }}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<button class="btn btn-success" v-on:click="save">Upload</button>
|
||||
<button class="btn btn-success" v-on:click="save" v-html="buttonText"></button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -38,6 +38,10 @@ export default defineComponent({
|
||||
const track: Ref<Track> = ref({ id: 0, name: "N/A", driver: "N/A", vehicle: { name: "N/A", licenseplate: "N/A" }, distance: 0.0 })
|
||||
const multiple: Ref<boolean> = ref(props.multiple);
|
||||
|
||||
// values for UI Information distribution
|
||||
const messageType: Ref<string> = ref("None");
|
||||
const message: Ref<string> = ref("");
|
||||
|
||||
const initializeMap = () => {
|
||||
if (mapDiv.value) {
|
||||
mapInstance.value = L.map(mapDiv.value, {
|
||||
@ -91,6 +95,9 @@ export default defineComponent({
|
||||
distance: jsonBody["distance"]
|
||||
}
|
||||
console.log(track.value)
|
||||
} else {
|
||||
messageType.value = "error";
|
||||
message.value = `"failed to load track meta with error: ${await response.statusText}`;
|
||||
}
|
||||
}
|
||||
|
||||
@ -116,6 +123,8 @@ export default defineComponent({
|
||||
mapInstance.value.fitBounds(bounds);
|
||||
} else {
|
||||
console.error("Map or GeoJSON data not available.");
|
||||
messageType.value = "error";
|
||||
message.value = `"Map or GeoJSON data not available.`;
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -123,13 +132,17 @@ export default defineComponent({
|
||||
return {
|
||||
mapDiv,
|
||||
multiple,
|
||||
track
|
||||
track,
|
||||
message,
|
||||
messageType
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
<template>
|
||||
<Message v-if="type == 'none'" :type="messageType" :message="message" @close="message = ''; messageType = 'None'"></Message>
|
||||
<div ref="mapDiv" style="width: 70vw; height: 75vh; overflow: hidden;"></div>
|
||||
<br>
|
||||
<div class="overflow-x-auto" style="width: 70vw;" v-if="!multiple">
|
||||
@ -146,7 +159,23 @@ export default defineComponent({
|
||||
</thead>
|
||||
<tbody>
|
||||
<!-- row 1 -->
|
||||
<tr class="bg-base-200">
|
||||
<tr v-if="track.id == 0" class="bg-base-200">
|
||||
<th>{{ track.name }}</th>
|
||||
<td>
|
||||
<div class="skeleton h-4 w-full"></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="skeleton h-4 w-full"></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="skeleton h-4 w-full"></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="skeleton h-4 w-full"></div>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr v-if="track.id != 0" class="bg-base-200">
|
||||
<th>{{ track.name }}</th>
|
||||
<td>{{ track.driver }}</td>
|
||||
<td>{{ track.vehicle.name }}</td>
|
||||
|
46
web/src/components/message.vue
Normal file
46
web/src/components/message.vue
Normal file
@ -0,0 +1,46 @@
|
||||
<script lang="ts">
|
||||
import { defineComponent, SetupContext, Ref, ref } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'Navbar',
|
||||
emits: ['close'],
|
||||
props:["type", "message"],
|
||||
setup(props, { emit }: SetupContext) {
|
||||
|
||||
const type:Ref<string> = ref(props.type);
|
||||
const message:Ref<string> = ref(props.message);
|
||||
|
||||
const close = () => {
|
||||
emit("close");
|
||||
};
|
||||
|
||||
return {
|
||||
close,
|
||||
type,
|
||||
message,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
<template>
|
||||
<div v-if="type==='info'" role="alert" class="alert alert-info alert-soft">
|
||||
<span>{{ message }}</span>
|
||||
<button class="btn btn-soft btn-info" v-on:click="close">Close</button>
|
||||
</div>
|
||||
<div v-if="type==='success'" role="alert" class="alert alert-success alert-soft">
|
||||
<span>{{ message }}</span>
|
||||
<button class="btn btn-soft btn-success" v-on:click="close">Close</button>
|
||||
</div>
|
||||
<div v-if="type==='warning'" role="alert" class="alert alert-warning alert-soft">
|
||||
<span>{{ message }}</span>
|
||||
<button class="btn btn-soft btn-warning" v-on:click="close">Close</button>
|
||||
</div>
|
||||
<div v-if="type==='error'" role="alert" class="alert error alert-soft">
|
||||
<span>{{ message }}</span>
|
||||
<button class="btn btn-soft btn-error" v-on:click="close">Close</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
@ -40,6 +40,10 @@ export default defineComponent({
|
||||
var drivers: driver[] = [];
|
||||
const points: Route[] = props.routes;
|
||||
|
||||
// values for UI Information distribution
|
||||
const messageType: Ref<string> = ref("None");
|
||||
const message: Ref<string> = ref("");
|
||||
|
||||
// handles sending webrequests to the backend
|
||||
const getDrivers = async () => {
|
||||
|
||||
@ -72,6 +76,8 @@ export default defineComponent({
|
||||
}
|
||||
} else {
|
||||
console.log(await response.text())
|
||||
messageType.value = "error";
|
||||
message.value = `failed to get drivers with error: ${await response.statusText}`;
|
||||
}
|
||||
}
|
||||
|
||||
@ -112,11 +118,9 @@ export default defineComponent({
|
||||
const colors: number[] = [];
|
||||
|
||||
const totalPoints = points.length;
|
||||
const offsetXStep = 2; // Wir setzen den Abstand pro Gruppe
|
||||
const offsetXStep = 2;
|
||||
|
||||
let offsetX = 0;
|
||||
|
||||
// Berechnungen für den Mittelpunkt der Punktwolke
|
||||
let sumX = 0, sumY = 0, sumZ = 0;
|
||||
|
||||
const getColorForDriver = (driverId: number) => {
|
||||
@ -128,7 +132,12 @@ export default defineComponent({
|
||||
return color;
|
||||
};
|
||||
|
||||
// complicated math things
|
||||
/**
|
||||
* complicated math things (i am scared of this part)
|
||||
*
|
||||
* calculates a points position and ensures that all points grouped by the same driver are placed together
|
||||
* a point is a uploaded track and during this step it gets applied its color material which was generated whiles getting drivers
|
||||
*/
|
||||
Object.entries(groupedPoints).forEach(([driverIdStr, driverPoints], index) => {
|
||||
const driverId = parseInt(driverIdStr, 10);
|
||||
console.log("Driver Colors:", driverColors.value[driverIdStr]);
|
||||
@ -159,7 +168,7 @@ export default defineComponent({
|
||||
});
|
||||
});
|
||||
|
||||
// Mittelpunkt der Punktwolke berechnen
|
||||
// calculate clouds centerpoint
|
||||
const centerX = sumX / totalPoints;
|
||||
const centerY = sumY / totalPoints;
|
||||
const centerZ = sumZ / totalPoints;
|
||||
@ -194,7 +203,10 @@ export default defineComponent({
|
||||
}
|
||||
animate();
|
||||
|
||||
// handles mouse actions
|
||||
/**
|
||||
* handles mouse events and moves 3D space
|
||||
* @param event the event triggered when the mouse is moved inside the canvas
|
||||
*/
|
||||
const onMouseMove = (event: MouseEvent) => {
|
||||
if (!canvasRef.value || !tooltipRef.value) return;
|
||||
|
||||
@ -211,22 +223,24 @@ export default defineComponent({
|
||||
|
||||
tooltipRef.value.style.display = "block";
|
||||
|
||||
// 3D-Koordinaten des Punktes holen
|
||||
|
||||
/**
|
||||
* getting coordinates and calculating 2D coordinates from them
|
||||
* this is done for the tooltip to be positions at the cursor
|
||||
*/
|
||||
const positionArray = pointCloud.geometry.attributes.position.array;
|
||||
const x = positionArray[intersectIndex * 3];
|
||||
const y = positionArray[intersectIndex * 3 + 1];
|
||||
const z = positionArray[intersectIndex * 3 + 2];
|
||||
|
||||
// 3D-Koordinaten in 2D Bildschirmkoordinaten umrechnen
|
||||
const screenPosition = new THREE.Vector3(x, y, z);
|
||||
screenPosition.project(camera);
|
||||
|
||||
// Umrechnung von NDC (Normalized Device Coordinates) zu Pixeln
|
||||
const tooltipX = (screenPosition.x * 0.5 + 0.5) * window.innerWidth;
|
||||
const tooltipY = (screenPosition.y * -0.5 + 0.5) * window.innerHeight;
|
||||
|
||||
tooltipRef.value.style.left = `${tooltipX + 10}px`; // 10px Abstand zum Punkt
|
||||
tooltipRef.value.style.top = `${tooltipY + 10}px`; // 10px Abstand zum Punkt
|
||||
tooltipRef.value.style.left = `${tooltipX + 10}px`;
|
||||
tooltipRef.value.style.top = `${tooltipY + 10}px`;
|
||||
|
||||
tooltipText.value = `${point.driver.name}: ${point.name} (${point.time.toLocaleString()})`;
|
||||
} else {
|
||||
@ -250,6 +264,8 @@ export default defineComponent({
|
||||
tooltipText,
|
||||
legend,
|
||||
driverColors,
|
||||
message,
|
||||
messageType
|
||||
};
|
||||
},
|
||||
});
|
||||
@ -257,6 +273,7 @@ export default defineComponent({
|
||||
|
||||
|
||||
<template>
|
||||
<Message v-if="type == 'none'" :type="messageType" :message="message" @close="message = ''; messageType = 'None'"></Message>
|
||||
<div class="pointcloud-container relative">
|
||||
<canvas ref="canvasRef"></canvas>
|
||||
<div ref="tooltipRef" class="tooltip hidden fixed z-50 px-2 py-1 bg-base-200 text-base-content rounded">
|
||||
@ -264,7 +281,7 @@ export default defineComponent({
|
||||
</div>
|
||||
<!-- Legende -->
|
||||
<div class="legend absolute top-10 left-10 bg-base-200 p-4 rounded shadow-lg z-50">
|
||||
<h3 class="font-bold mb-2">Fahrer Legende</h3>
|
||||
<h3 class="font-bold mb-2">Drivers</h3>
|
||||
<ul>
|
||||
<li v-for="(driverName, driverId) in legend" :key="driverId" class="flex items-center mb-1">
|
||||
<div class="w-4 h-4" :style="{ backgroundColor: driverColors[driverId] }"></div>
|
||||
|
@ -13,6 +13,11 @@ export default defineComponent({
|
||||
const driverName: Ref<string> = ref("")
|
||||
const driverList: Ref<driver[]> = ref([])
|
||||
|
||||
// values for UI Information distribution
|
||||
const messageType: Ref<string> = ref("");
|
||||
const message: Ref<string> = ref("");
|
||||
|
||||
|
||||
// handles sending webrequests to the backend
|
||||
const getDrivers = async () => {
|
||||
|
||||
@ -39,6 +44,8 @@ export default defineComponent({
|
||||
}
|
||||
} else {
|
||||
console.log(await response.text())
|
||||
messageType.value = "error";
|
||||
message.value = `upload failed: ${response.text()}`;
|
||||
}
|
||||
}
|
||||
|
||||
@ -64,6 +71,8 @@ export default defineComponent({
|
||||
driverList.value.push({ id: jsonBody["body"], name: driverName.value })
|
||||
} else {
|
||||
console.log(await response.text())
|
||||
messageType.value = "error";
|
||||
message.value = `upload failed: ${response.text()}`;
|
||||
}
|
||||
}
|
||||
|
||||
@ -71,7 +80,9 @@ export default defineComponent({
|
||||
return {
|
||||
createDriver,
|
||||
driverName,
|
||||
driverList
|
||||
driverList,
|
||||
message,
|
||||
messageType
|
||||
};
|
||||
},
|
||||
});
|
||||
@ -79,6 +90,7 @@ export default defineComponent({
|
||||
|
||||
|
||||
<template>
|
||||
<Message v-if="type == 'none'" :type="messageType" :message="message" @close="message = ''; messageType = 'None'"></Message>
|
||||
<div class="overflow-x-auto">
|
||||
<table class="table">
|
||||
<!-- head -->
|
||||
@ -92,9 +104,18 @@ export default defineComponent({
|
||||
<tbody>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td><input type="text" placeholder="Driver Name" class="input input-bordered w-full max-w-xs"
|
||||
v-model="driverName" /></td>
|
||||
<td><a class="btn btn-success" v-on:click="createDriver">Create Driver</a></td>
|
||||
<td><input type="text" placeholder="Driver Name" class="input input-bordered w-full" v-model="driverName" />
|
||||
</td>
|
||||
<td><a class="btn btn-success w-full" v-on:click="createDriver">Create Driver</a></td>
|
||||
</tr>
|
||||
<tr v-if="driverList.length == 0">
|
||||
<th>
|
||||
<div class="skeleton h-4 w-full"></div>
|
||||
</th>
|
||||
<td>
|
||||
<div class="skeleton h-4 w-full"></div>
|
||||
</td>
|
||||
<td><a class="btn btn-error w-full" v-on:click="createVehicle">Delete Vehicle</a></td>
|
||||
</tr>
|
||||
<tr v-for="driver in driverList">
|
||||
<th>{{ driver.id }}</th>
|
||||
|
@ -5,6 +5,7 @@ import VueDatePicker from '@vuepic/vue-datepicker';
|
||||
import '@vuepic/vue-datepicker/dist/main.css'
|
||||
import Map from '../components/map.vue';
|
||||
import FileUpload from '../components/fileUpload.vue';
|
||||
import Message from '../components/message.vue';
|
||||
|
||||
type DriverType = {
|
||||
id: number
|
||||
@ -37,7 +38,7 @@ type GeoJSON = {
|
||||
|
||||
export default defineComponent({
|
||||
name: 'map',
|
||||
components: { PointCloud, VueDatePicker, Map, FileUpload },
|
||||
components: { PointCloud, VueDatePicker, Map, FileUpload, Message },
|
||||
setup(_, { emit }: SetupContext) {
|
||||
const showMap: Ref<boolean> = ref(false);
|
||||
const showCloud: Ref<boolean> = ref(false);
|
||||
@ -52,6 +53,10 @@ export default defineComponent({
|
||||
const multipleTracks: Ref<Boolean> = ref(false);
|
||||
const trackid: Ref<number> = ref(0)
|
||||
|
||||
// values for UI Information distribution
|
||||
const messageType: Ref<string> = ref("");
|
||||
const message: Ref<string> = ref("");
|
||||
|
||||
const loadTrack = async (id: number) => {
|
||||
showMap.value = true;
|
||||
showCloud.value = false;
|
||||
@ -75,12 +80,15 @@ export default defineComponent({
|
||||
if (response.ok) {
|
||||
// Wenn die Antwort OK ist, die Daten verarbeiten
|
||||
mapData.value = await response.json();
|
||||
console.log("GeoJSON-Daten erfolgreich geladen", mapData.value);
|
||||
} else {
|
||||
console.log(await response.text());
|
||||
messageType.value = "error";
|
||||
message.value = `loading tracks failed: ${await response.text()}`;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Fehler beim Laden der Track-Daten:", error);
|
||||
console.error("loading tracks failed with error:", error);
|
||||
messageType.value = "error";
|
||||
message.value = `loading tracks failed with error: ${error}`;
|
||||
}
|
||||
};
|
||||
|
||||
@ -106,6 +114,8 @@ export default defineComponent({
|
||||
}
|
||||
} else {
|
||||
console.log(await response.text())
|
||||
messageType.value = "error";
|
||||
message.value = `loading track list failed with error: ${error}`;
|
||||
}
|
||||
}
|
||||
|
||||
@ -121,7 +131,8 @@ export default defineComponent({
|
||||
multipleTracks.value = false;
|
||||
|
||||
if (startSearchDate.value == null || endSearchDate.value == null) {
|
||||
alert("please give all required infos")
|
||||
messageType.value = "error";
|
||||
message.value = "please give all required infos";
|
||||
return;
|
||||
}
|
||||
|
||||
@ -155,6 +166,8 @@ export default defineComponent({
|
||||
|
||||
} else {
|
||||
console.log(await response.text())
|
||||
messageType.value = "error";
|
||||
message.value = `searching tracks failed: ${await response.text()}`;
|
||||
}
|
||||
|
||||
if (renderSearchOnMap.value) {
|
||||
@ -188,6 +201,8 @@ export default defineComponent({
|
||||
showUpload,
|
||||
multipleTracks,
|
||||
trackid,
|
||||
message,
|
||||
messageType
|
||||
};
|
||||
},
|
||||
});
|
||||
@ -195,6 +210,7 @@ export default defineComponent({
|
||||
|
||||
|
||||
<template>
|
||||
<Message v-if="type == 'none'" :type="messageType" :message="message" @close="message = ''; messageType = 'None'"></Message>
|
||||
<FileUpload v-if="showUpload" @close="showUpload = false;" :drivers="[]"
|
||||
style="position:absolute; top: 30VH; width: 80%;"></FileUpload>
|
||||
<div class="grid grid-flow-col auto-cols-max gap-4">
|
||||
@ -207,6 +223,9 @@ export default defineComponent({
|
||||
<li>
|
||||
<div class="divider"></div>
|
||||
</li>
|
||||
<li v-if="tracks.length == 0">
|
||||
<div class="skeleton h-4 w-full"></div>
|
||||
</li>
|
||||
<li v-for="track in tracks"> <a v-on:click="loadTrack(track.id); multipleTracks = false;"> {{ track.name }} </a>
|
||||
</li>
|
||||
</ul>
|
||||
@ -217,11 +236,11 @@ export default defineComponent({
|
||||
<div v-if="!showMap && !showCloud && search" style="margin-left: 20%; display:flex;">
|
||||
<div>
|
||||
start time
|
||||
<input class="datepicker" type="date" id="birthday" name="birthday" v-model="startSearchDate">
|
||||
<input class="datepicker" type="date" id="startdate" name="startdate" v-model="startSearchDate">
|
||||
</div>
|
||||
<div style="margin-left: 5%;">
|
||||
end time
|
||||
<input class="datepicker" type="date" id="birthday" name="birthday" v-model="endSearchDate">
|
||||
<input class="datepicker" type="date" id="enddate" name="enddate" v-model="endSearchDate">
|
||||
</div>
|
||||
<div style="margin-left: 5%;">
|
||||
show on map:
|
||||
|
@ -15,6 +15,10 @@ export default defineComponent({
|
||||
const licensePlate: Ref<string> = ref("")
|
||||
const vehicleList: Ref<vehicle[]> = ref([])
|
||||
|
||||
// values for UI Information distribution
|
||||
const messageType: Ref<string> = ref("");
|
||||
const message: Ref<string> = ref("");
|
||||
|
||||
// handles getting all existing drivers
|
||||
const getVehicles = async () => {
|
||||
const headers: Headers = new Headers()
|
||||
@ -43,6 +47,8 @@ export default defineComponent({
|
||||
}
|
||||
} else {
|
||||
console.log(await response.text())
|
||||
messageType.value = "error";
|
||||
message.value = `loading vehicles failed with error: ${await response.text()}`;
|
||||
}
|
||||
}
|
||||
|
||||
@ -68,6 +74,8 @@ export default defineComponent({
|
||||
vehicleList.value.push({ id: jsonBody["body"], name: vehicleName.value, licenseplate: "N/A" })
|
||||
} else {
|
||||
console.log(await response.text())
|
||||
messageType.value = "error";
|
||||
message.value = `creating vehicle failed with error: ${error}`;
|
||||
}
|
||||
}
|
||||
|
||||
@ -76,7 +84,9 @@ export default defineComponent({
|
||||
createVehicle,
|
||||
vehicleName,
|
||||
licensePlate,
|
||||
vehicleList
|
||||
vehicleList,
|
||||
message,
|
||||
messageType
|
||||
};
|
||||
},
|
||||
});
|
||||
@ -84,6 +94,7 @@ export default defineComponent({
|
||||
|
||||
|
||||
<template>
|
||||
<Message v-if="type == 'none'" :type="messageType" :message="message" @close="message = ''; messageType = 'None'"></Message>
|
||||
<div class="overflow-x-auto">
|
||||
<table class="table">
|
||||
<!-- head -->
|
||||
@ -97,20 +108,34 @@ export default defineComponent({
|
||||
<tbody>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td><input type="text" placeholder="Vehicle Name" class="input input-bordered w-full max-w-xs" v-model="vehicleName"/></td>
|
||||
<td><input type="text" placeholder="License Plate" class="input input-bordered w-full max-w-xs" v-model="licensePlate"/></td>
|
||||
<td><a class="btn btn-success" v-on:click="createVehicle">Create Vehicle</a></td>
|
||||
<td><input type="text" placeholder="Vehicle Name" class="input input-bordered w-full "
|
||||
v-model="vehicleName" /></td>
|
||||
<td><input type="text" placeholder="License Plate" class="input input-bordered w-full "
|
||||
v-model="licensePlate" /></td>
|
||||
<td><a class="btn btn-success w-full" v-on:click="createVehicle">Create Vehicle</a></td>
|
||||
</tr>
|
||||
<tr v-if="vehicleList.length == 0">
|
||||
<th>
|
||||
<div class="skeleton h-4 w-full"></div>
|
||||
</th>
|
||||
<td>
|
||||
<div class="skeleton h-4 w-full"></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="skeleton h-4 w-full"></div>
|
||||
</td>
|
||||
<td><a class="btn btn-error w-full" v-on:click="createVehicle">Delete Vehicle</a></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr v-for="vehicle in vehicleList">
|
||||
<th>{{ vehicle.id }}</th>
|
||||
<td>{{ vehicle.name }}</td>
|
||||
<td>{{ vehicle.licenseplate }}</td>
|
||||
<td></td>
|
||||
<td><a class="btn btn-error w-full" v-on:click="createVehicle">Delete Vehicle</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
||||
<style scoped></style>
|
@ -1 +1 @@
|
||||
{"root":["./theme-manager.config.ts","./vite.config.ts","./src/app.vue","./src/leatflet.d.ts","./src/main.ts","./src/vite-env.d.ts","./src/classes/debugger.ts","./src/classes/language.ts","./src/components/settings.vue","./src/components/cookieprompt.vue","./src/components/fileupload.vue","./src/components/map.vue","./src/components/navbar.vue","./src/components/pointcloud.vue","./src/views/driver.vue","./src/views/home.vue","./src/views/login.vue","./src/views/register.vue","./src/views/route.vue","./src/views/settings.vue","./src/views/vehicle.vue"],"version":"5.6.2"}
|
||||
{"root":["./theme-manager.config.ts","./vite.config.ts","./src/app.vue","./src/leatflet.d.ts","./src/main.ts","./src/vite-env.d.ts","./src/classes/debugger.ts","./src/classes/language.ts","./src/components/settings.vue","./src/components/cookieprompt.vue","./src/components/fileupload.vue","./src/components/map.vue","./src/components/navbar.vue","./src/components/pointcloud.vue","./src/views/driver.vue","./src/views/home.vue","./src/views/login.vue","./src/views/register.vue","./src/views/route.vue","./src/views/settings.vue","./src/views/vehicle.vue"],"errors":true,"version":"5.6.2"}
|
Loading…
x
Reference in New Issue
Block a user