diff --git a/frontend/react/.vscode/launch.json b/frontend/react/.vscode/launch.json
index 1f07e0f0..a461c2f9 100644
--- a/frontend/react/.vscode/launch.json
+++ b/frontend/react/.vscode/launch.json
@@ -10,7 +10,11 @@
"name": "Launch Chrome against localhost",
"url": "http://localhost:3000/vite/",
"webRoot": "${workspaceFolder}",
- "preLaunchTask": "npm: dev"
- }
+ "preLaunchTask": "npm: dev",
+ "resolveSourceMapLocations": [
+ "${workspaceFolder}/**",
+ "!**/node_modules/**"
+ ]
+ },
]
}
\ No newline at end of file
diff --git a/frontend/react/src/map/map.ts b/frontend/react/src/map/map.ts
index 3b7f01ec..993683be 100644
--- a/frontend/react/src/map/map.ts
+++ b/frontend/react/src/map/map.ts
@@ -3,7 +3,7 @@ import { getApp } from "../olympusapp";
import { BoxSelect } from "./boxselect";
import { Airbase } from "../mission/airbase";
import { Unit } from "../unit/unit";
-import { areaContains, deg2rad, getFunctionArguments, getGroundElevation } from "../other/utils";
+import { areaContains, deg2rad, getGroundElevation } from "../other/utils";
import { TemporaryUnitMarker } from "./markers/temporaryunitmarker";
import { ClickableMiniMap } from "./clickableminimap";
import {
@@ -24,7 +24,7 @@ import {
import { CoalitionPolygon } from "./coalitionarea/coalitionpolygon";
import { MapHiddenTypes, MapOptions } from "../types/types";
import { SpawnRequestTable } from "../interfaces";
-import { ContextAction, ContextActionCallback } from "../unit/contextaction";
+import { ContextAction } from "../unit/contextaction";
/* Stylesheets */
import "./markers/stylesheets/airbase.css";
@@ -109,6 +109,7 @@ export class Map extends L.Map {
/* Unit spawning */
#spawnRequestTable: SpawnRequestTable | null = null;
#temporaryMarkers: TemporaryUnitMarker[] = [];
+ #currentSpawnMarker: TemporaryUnitMarker | null = null;
/**
*
@@ -349,6 +350,8 @@ export class Map extends L.Map {
/* Operations to perform when leaving a state */
if (this.#state === COALITIONAREA_DRAW_POLYGON || this.#state === COALITIONAREA_DRAW_CIRCLE) this.getSelectedCoalitionArea()?.setEditing(false);
+ this.#currentSpawnMarker?.removeFrom(this);
+ this.#currentSpawnMarker = null;
this.#state = state;
@@ -361,6 +364,8 @@ export class Map extends L.Map {
this.#spawnRequestTable = options?.spawnRequestTable ?? null;
console.log(`Spawn request table:`);
console.log(this.#spawnRequestTable);
+ this.#currentSpawnMarker = new TemporaryUnitMarker(new L.LatLng(0, 0), this.#spawnRequestTable?.unit.unitType ?? "", this.#spawnRequestTable?.coalition ?? "neutral")
+ this.#currentSpawnMarker.addTo(this);
} else if (this.#state === CONTEXT_ACTION) {
this.deselectAllCoalitionAreas();
this.#contextAction = options?.contextAction ?? null;
@@ -840,7 +845,7 @@ export class Map extends L.Map {
/* Execute the short click action */
if (this.#state === IDLE) {
} else if (this.#state === SPAWN_UNIT) {
- if (this.#spawnRequestTable !== null) {
+ if (e.originalEvent.button != 2 && this.#spawnRequestTable !== null) {
this.#spawnRequestTable.unit.location = pressLocation;
getApp()
.getUnitsManager()
@@ -920,6 +925,10 @@ export class Map extends L.Map {
this.#lastMousePosition.x = e.originalEvent.x;
this.#lastMousePosition.y = e.originalEvent.y;
this.#lastMouseCoordinates = e.latlng;
+
+ if (this.#currentSpawnMarker) {
+ this.#currentSpawnMarker.setLatLng(e.latlng);
+ }
}
#onMapMove(e: any) {
diff --git a/frontend/react/src/other/utils.ts b/frontend/react/src/other/utils.ts
index 9359b6e2..b60ce768 100644
--- a/frontend/react/src/other/utils.ts
+++ b/frontend/react/src/other/utils.ts
@@ -503,7 +503,7 @@ export function filterBlueprintsByLabel(blueprints: { [key: string]: UnitBluepri
var filteredBlueprints: { [key: string]: UnitBlueprint } = {};
if (blueprints) {
Object.entries(blueprints).forEach(([key, value]) => {
- if (value.enabled && (filterString === "" || value.label.includes(filterString))) filteredBlueprints[key] = value;
+ if (value.enabled && (filterString === "" || value.label.toLowerCase().includes(filterString.toLowerCase()))) filteredBlueprints[key] = value;
});
}
return filteredBlueprints;
diff --git a/frontend/react/src/server/servermanager.ts b/frontend/react/src/server/servermanager.ts
index 108a52ea..c4198ceb 100644
--- a/frontend/react/src/server/servermanager.ts
+++ b/frontend/react/src/server/servermanager.ts
@@ -59,7 +59,7 @@ export class ServerManager {
/* If we are forcing the request we don't care if one already exists, just send it. CAREFUL: this makes sense only for low frequency requests, like refreshes, when we
are reasonably confident any previous request will be done before we make a new one on the same URI. */
if (uri in this.#requests && this.#requests[uri].readyState !== 4 && !force) {
- console.warn(`GET request on ${uri} URI still pending, skipping...`);
+ //console.warn(`GET request on ${uri} URI still pending, skipping...`);
return;
}
diff --git a/frontend/react/src/ui/libs/useDrag.ts b/frontend/react/src/ui/libs/useDrag.ts
new file mode 100644
index 00000000..ccb343f3
--- /dev/null
+++ b/frontend/react/src/ui/libs/useDrag.ts
@@ -0,0 +1,68 @@
+import { useCallback, useEffect, useState } from "react";
+
+export const useDrag = (props: { ref, initialPosition, count}) => {
+ const [finalPosition, setFinalPosition] = useState({ x: props.initialPosition.x, y: props.initialPosition.y });
+ const [isDragging, setIsDragging] = useState(false);
+ const [count, setCount] = useState(0)
+
+ if (count !== props.count) {
+ setCount(props.count)
+ setFinalPosition({ x: props.initialPosition.x, y: props.initialPosition.y })
+ }
+
+ const handleMouseUp = (evt) => {
+ evt.preventDefault();
+
+ setIsDragging(false);
+ };
+
+ const handleMouseDown = (evt) => {
+ evt.preventDefault();
+
+ const { current: draggableElement } = props.ref;
+
+ if (!draggableElement) {
+ return;
+ }
+
+ setIsDragging(true);
+ };
+
+ const handleMouseMove = useCallback(
+ (evt) => {
+ const { current: draggableElement } = props.ref;
+
+ if (!isDragging || !draggableElement) return;
+
+ evt.preventDefault();
+
+ const parentRect = draggableElement.parentElement.getBoundingClientRect();
+ const rect = draggableElement.getBoundingClientRect();
+
+ const [width, height] = [rect.width, rect.height];
+ const [mouseX, mouseY] = [evt.clientX, evt.clientY];
+ const [parentTop, parentLeft, parentWidth, parentHeight] = [parentRect.top, parentRect.left, parentRect.width, parentRect.height];
+
+ setFinalPosition({
+ x: Math.max(width / 2, Math.min(mouseX - parentLeft, parentWidth - width / 2)),
+ y: Math.max(height / 2, Math.min(mouseY - parentTop, parentHeight - height / 2)),
+ });
+ },
+ [isDragging, props.ref]
+ );
+
+ useEffect(() => {
+ document.addEventListener("mousemove", handleMouseMove);
+ document.addEventListener("mouseup", handleMouseUp);
+
+ return () => {
+ document.removeEventListener("mousemove", handleMouseMove);
+ document.removeEventListener("mouseup", handleMouseUp);
+ };
+ }, [handleMouseMove]);
+
+ return {
+ position: finalPosition,
+ handleMouseDown
+ };
+};
diff --git a/frontend/react/src/ui/panels/airbasemenu.tsx b/frontend/react/src/ui/panels/airbasemenu.tsx
index 05224ebf..91fa1b1f 100644
--- a/frontend/react/src/ui/panels/airbasemenu.tsx
+++ b/frontend/react/src/ui/panels/airbasemenu.tsx
@@ -1,15 +1,10 @@
import React, { useState } from "react";
import { Menu } from "./components/menu";
-import { OlCheckbox } from "../components/olcheckbox";
-import { OlRangeSlider } from "../components/olrangeslider";
-import { OlNumberInput } from "../components/olnumberinput";
-import { Coalition, MapOptions } from "../../types/types";
-import { getApp } from "../../olympusapp";
+import { Coalition } from "../../types/types";
import { Airbase } from "../../mission/airbase";
import { FaArrowLeft, FaCompass } from "react-icons/fa6";
import { getUnitsByLabel } from "../../other/utils";
import { UnitBlueprint } from "../../interfaces";
-import { IDLE } from "../../constants/constants";
import { OlSearchBar } from "../components/olsearchbar";
import { OlAccordion } from "../components/olaccordion";
import { OlUnitEntryList } from "../components/olunitlistentry";
@@ -20,7 +15,7 @@ export function AirbaseMenu(props: { open: boolean; onClose: () => void; airbase
const [blueprint, setBlueprint] = useState(null as null | UnitBlueprint);
const [filterString, setFilterString] = useState("");
- const [filteredAircraft, filteredHelicopters, filteredAirDefense, filteredGroundUnits, filteredNavyUnits] = getUnitsByLabel(filterString);
+ const [filteredAircraft, filteredHelicopters, _1, _2, _3] = getUnitsByLabel(filterString);
return (