diff --git a/frontend/react/.vscode/launch.json b/frontend/react/.vscode/launch.json index a461c2f9..c242f4d0 100644 --- a/frontend/react/.vscode/launch.json +++ b/frontend/react/.vscode/launch.json @@ -8,7 +8,7 @@ "type": "chrome", "request": "launch", "name": "Launch Chrome against localhost", - "url": "http://localhost:3000/vite/", + "url": "http://localhost:3000", "webRoot": "${workspaceFolder}", "preLaunchTask": "npm: dev", "resolveSourceMapLocations": [ diff --git a/frontend/react/src/audio/audiomanager.ts b/frontend/react/src/audio/audiomanager.ts index 0fbcad0e..8a222407 100644 --- a/frontend/react/src/audio/audiomanager.ts +++ b/frontend/react/src/audio/audiomanager.ts @@ -44,7 +44,6 @@ export class AudioManager { /* The audio backend must be manually started so that the browser can detect the user is enabling audio. Otherwise, no playback will be performed. */ #running: boolean = false; - #address: string = "localhost"; #port: number; #endpoint: string; #socket: WebSocket | null = null; @@ -90,10 +89,10 @@ export class AudioManager { this.#playbackPipeline = new PlaybackPipeline(); /* Connect the audio websocket */ - let res = this.#address.match(/(?:http|https):\/\/(.+):/); - if (res === null) res = this.#address.match(/(?:http|https):\/\/(.+)/); + let res = location.toString().match(/(?:http|https):\/\/(.+):/); + if (res === null) res = location.toString().match(/(?:http|https):\/\/(.+)/); - let wsAddress = res ? res[1] : this.#address; + let wsAddress = res ? res[1] : location.toString(); if (this.#endpoint) this.#socket = new WebSocket(`wss://${wsAddress}/${this.#endpoint}`); else if (this.#port) this.#socket = new WebSocket(`ws://${wsAddress}:${this.#port}`); else console.error("The audio backend was enabled but no port/endpoint was provided in the configuration"); @@ -229,10 +228,6 @@ export class AudioManager { AudioManagerStateChangedEvent.dispatch(this.#running); } - setAddress(address) { - this.#address = address; - } - setPort(port) { this.#port = port; } diff --git a/frontend/react/src/audio/speechcontroller.ts b/frontend/react/src/audio/speechcontroller.ts index 8f181226..c97e6392 100644 --- a/frontend/react/src/audio/speechcontroller.ts +++ b/frontend/react/src/audio/speechcontroller.ts @@ -15,7 +15,7 @@ export class SpeechController { body: JSON.stringify({ data: base64 }), // Send the data in blob format }; - fetch(getApp().getExpressAddress() + `/api/speech/recognize`, requestOptions) + fetch(`./api/speech/recognize`, requestOptions) .then((response) => { if (response.status === 200) { console.log(`Speech recognized correctly`); diff --git a/frontend/react/src/audio/texttospeechsource.ts b/frontend/react/src/audio/texttospeechsource.ts index de0ceb83..a53651f7 100644 --- a/frontend/react/src/audio/texttospeechsource.ts +++ b/frontend/react/src/audio/texttospeechsource.ts @@ -30,7 +30,7 @@ export class TextToSpeechSource extends AudioSource { this.#loading = true; - fetch(getApp().getExpressAddress() + `/api/speech/generate`, requestOptions) + fetch(`./api/speech/generate`, requestOptions) .then((response) => { if (response.status === 200) { console.log(`Text to speech generate correctly`); diff --git a/frontend/react/src/map/map.ts b/frontend/react/src/map/map.ts index 044aa4a6..d3b35120 100644 --- a/frontend/react/src/map/map.ts +++ b/frontend/react/src/map/map.ts @@ -542,6 +542,10 @@ export class Map extends L.Map { return Object.keys(this.#mapLayers); } + getMirrors() { + return this.#mapMirrors; + } + setSpawnRequestTable(spawnRequestTable: SpawnRequestTable) { this.#spawnRequestTable = spawnRequestTable; } @@ -574,6 +578,17 @@ export class Map extends L.Map { } setContextAction(contextAction: ContextAction | null) { + //if (contextAction) { + // this.getContainer().classList.add(`${contextAction.getId()}-cursor`); + // Object.values(getApp().getUnitsManager().getUnits()).forEach((node) => { + // if (node instanceof Unit) node.getElement()?.classList.add(`${contextAction.getId()}-cursor`); + // }); + //} else if (this.#contextAction) { + // this.getContainer().classList.remove(`${this.#contextAction.getId()}-cursor`); + // Object.values(getApp().getUnitsManager().getUnits()).forEach((node) => { + // if (node instanceof Unit) node.getElement()?.classList.remove(`${this.#contextAction?.getId()}-cursor`); + // }); + //} this.#contextAction = contextAction; ContextActionChangedEvent.dispatch(this.#contextAction); } diff --git a/frontend/react/src/map/markers/stylesheets/units.css b/frontend/react/src/map/markers/stylesheets/units.css index 4b61615f..99217c65 100644 --- a/frontend/react/src/map/markers/stylesheets/units.css +++ b/frontend/react/src/map/markers/stylesheets/units.css @@ -1,6 +1,6 @@ /*** Unit marker elements ***/ [data-object|="unit"] { - cursor: pointer; + /*cursor: pointer;*/ display: flex; height: 100%; justify-content: center; diff --git a/frontend/react/src/map/stylesheets/map.css b/frontend/react/src/map/stylesheets/map.css index 79e9fb5b..d13348e2 100644 --- a/frontend/react/src/map/stylesheets/map.css +++ b/frontend/react/src/map/stylesheets/map.css @@ -182,3 +182,7 @@ path.leaflet-interactive:focus { outline: none; } + +.attack-cursor { + cursor: url("./images/buttons/context/attack.svg"), auto !important; +} diff --git a/frontend/react/src/mission/missionmanager.ts b/frontend/react/src/mission/missionmanager.ts index 79f107e6..2a160349 100644 --- a/frontend/react/src/mission/missionmanager.ts +++ b/frontend/react/src/mission/missionmanager.ts @@ -270,7 +270,7 @@ export class MissionManager { } var xhr = new XMLHttpRequest(); - xhr.open("GET", getApp().getExpressAddress() + `/api/airbases/${this.#theatre.toLowerCase()}/${callsign}`, true); + xhr.open("GET", `./api/airbases/${this.#theatre.toLowerCase()}/${callsign}`, true); xhr.responseType = "json"; xhr.onload = () => { var status = xhr.status; diff --git a/frontend/react/src/olympusapp.ts b/frontend/react/src/olympusapp.ts index 06c0c37a..5c134262 100644 --- a/frontend/react/src/olympusapp.ts +++ b/frontend/react/src/olympusapp.ts @@ -105,18 +105,6 @@ export class OlympusApp { return this.#AWACSController; } - getExpressAddress() { - let address = `${window.location.href.split("?")[0].replace("vite/", "").replace("vite", "")}`; - if (address[address.length - 1] !== "/") address += "/" - return address; - } - - getBackendAddress() { - let address = `${window.location.href.split("?")[0].replace("vite/", "").replace("vite", "")}`; - if (address[address.length - 1] !== "/") address += "/" - return address + "olympus" - } - start() { /* Initialize base functionalitites */ this.#shortcutManager = new ShortcutManager(); /* Keep first */ @@ -133,10 +121,6 @@ export class OlympusApp { /* Controllers */ this.#AWACSController = new AWACSController(); - /* Set the address of the server */ - this.getServerManager().setAddress(this.getBackendAddress()); - this.getAudioManager().setAddress(this.getExpressAddress()); - /* Check if we are running the latest version */ const request = new Request("https://raw.githubusercontent.com/Pax1601/DCSOlympus/main/version.json"); fetch(request) @@ -157,7 +141,7 @@ export class OlympusApp { }); /* Load the config file from the server */ - const configRequest = new Request(this.getExpressAddress() + "resources/config", { + const configRequest = new Request("./resources/config", { headers: { 'Cache-Control': 'no-cache', } @@ -187,7 +171,7 @@ export class OlympusApp { } ConfigLoadedEvent.dispatch(this.#config as OlympusConfig); }) - .catch((error) => console.error); + .catch((error) => console.error(error)); this.#shortcutManager?.addShortcut("idle", { label: "Deselect all", @@ -217,7 +201,7 @@ export class OlympusApp { body: JSON.stringify(profile), // Send the data in JSON format }; - fetch(this.getExpressAddress() + `/resources/profile/${username}`, requestOptions) + fetch(`./resources/profile/${username}`, requestOptions) .then((response) => { if (response.status === 200) { console.log(`Profile for ${username} saved correctly`); @@ -239,7 +223,7 @@ export class OlympusApp { body: "", // Send the data in JSON format }; - fetch(this.getExpressAddress() + `/resources/profile/reset/${username}`, requestOptions) + fetch(`./resources/profile/reset/${username}`, requestOptions) .then((response) => { if (response.status === 200) { console.log(`Profile for ${username} reset correctly`); @@ -260,7 +244,7 @@ export class OlympusApp { body: "", // Send the data in JSON format }; - fetch(this.getExpressAddress() + `/resources/profile/delete/all`, requestOptions) + fetch(`./resources/profile/delete/all`, requestOptions) .then((response) => { if (response.status === 200) { console.log(`All profiles reset correctly`); diff --git a/frontend/react/src/other/utils.ts b/frontend/react/src/other/utils.ts index e398937b..c77a30f2 100644 --- a/frontend/react/src/other/utils.ts +++ b/frontend/react/src/other/utils.ts @@ -306,7 +306,7 @@ export function convertDateAndTimeToDate(dateAndTime: DateAndTime) { export function getGroundElevation(latlng: LatLng, callback: CallableFunction) { /* Get the ground elevation from the server endpoint */ const xhr = new XMLHttpRequest(); - xhr.open("GET", getApp().getExpressAddress() + `/api/elevation/${latlng.lat}/${latlng.lng}`, true); + xhr.open("GET", `./api/elevation/${latlng.lat}/${latlng.lng}`, true); xhr.timeout = 500; // ms xhr.responseType = "json"; xhr.onload = () => { diff --git a/frontend/react/src/server/servermanager.ts b/frontend/react/src/server/servermanager.ts index dbb1fcd8..6c6e7051 100644 --- a/frontend/react/src/server/servermanager.ts +++ b/frontend/react/src/server/servermanager.ts @@ -19,7 +19,7 @@ import { MapOptionsChangedEvent, ServerStatusUpdatedEvent } from "../events"; export class ServerManager { #connected: boolean = false; #paused: boolean = false; - #REST_ADDRESS = "http://localhost:3001/olympus"; + #REST_ADDRESS = "./olympus"; #username: null | string = null; #password: null | string = null; #sessionHash: string | null = null; @@ -164,7 +164,7 @@ export class ServerManager { getConfig(callback: CallableFunction) { var xmlHttp = new XMLHttpRequest(); - xmlHttp.open("GET", getApp().getExpressAddress() + "config", true); + xmlHttp.open("GET", "./config", true); xmlHttp.onload = function (e) { var data = JSON.parse(xmlHttp.responseText); callback(data); @@ -175,12 +175,6 @@ export class ServerManager { xmlHttp.send(null); } - setAddress(address: string) { - this.#REST_ADDRESS = address; - - console.log(`Setting REST address to ${this.#REST_ADDRESS}`); - } - getAirbases(callback: CallableFunction, errorCallback: CallableFunction = () => {}) { this.GET(callback, errorCallback, AIRBASES_URI); } diff --git a/frontend/react/src/sessiondata.ts b/frontend/react/src/sessiondata.ts index aabb4828..f2a58738 100644 --- a/frontend/react/src/sessiondata.ts +++ b/frontend/react/src/sessiondata.ts @@ -87,7 +87,7 @@ export class SessionDataManager { body: JSON.stringify({ sessionHash }), // Send the data in JSON format }; - fetch(getApp().getExpressAddress() + `/resources/sessiondata/load/${getApp().getServerManager().getUsername()}`, requestOptions) + fetch(`./resources/sessiondata/load/${getApp().getServerManager().getUsername()}`, requestOptions) .then((response) => { if (response.status === 200) { console.log(`Session data for profile ${getApp().getServerManager().getUsername()} and session hash ${sessionHash} loaded correctly`); @@ -118,7 +118,7 @@ export class SessionDataManager { body: JSON.stringify({ sessionHash: this.#sessionHash, sessionData: this.#sessionData }), // Send the data in JSON format }; - fetch(getApp().getExpressAddress() + `/resources/sessiondata/save/${getApp().getServerManager().getUsername()}`, requestOptions) + fetch(`./resources/sessiondata/save/${getApp().getServerManager().getUsername()}`, requestOptions) .then((response) => { if (response.status === 200) { console.log(`Session data for profile ${getApp().getServerManager().getUsername()} and session hash ${this.#sessionHash} saved correctly`); diff --git a/frontend/react/src/ui/modals/loginmodal.tsx b/frontend/react/src/ui/modals/loginmodal.tsx index 80f5ab86..2a27796b 100644 --- a/frontend/react/src/ui/modals/loginmodal.tsx +++ b/frontend/react/src/ui/modals/loginmodal.tsx @@ -6,7 +6,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faArrowRight, faCheckCircle, faExternalLink } from "@fortawesome/free-solid-svg-icons"; import { getApp, VERSION } from "../../olympusapp"; import { sha256 } from "js-sha256"; -import { BLUE_COMMANDER, GAME_MASTER, LoginSubState, NO_SUBSTATE, OlympusState, RED_COMMANDER } from "../../constants/constants"; +import { LoginSubState, NO_SUBSTATE, OlympusState } from "../../constants/constants"; import { OlDropdown, OlDropdownItem } from "../components/oldropdown"; import { AppStateChangedEvent } from "../../events"; diff --git a/frontend/react/src/ui/panels/header.tsx b/frontend/react/src/ui/panels/header.tsx index 046529d7..345a571f 100644 --- a/frontend/react/src/ui/panels/header.tsx +++ b/frontend/react/src/ui/panels/header.tsx @@ -35,8 +35,7 @@ export function Header() { MapOptionsChangedEvent.on((mapOptions) => setMapOptions({ ...mapOptions })); MapSourceChangedEvent.on((source) => setMapSource(source)); ConfigLoadedEvent.on((config: OlympusConfig) => { - - var sources = Object.keys(config.frontend.mapMirrors).concat(Object.keys(config.frontend.mapLayers)).concat(getApp().getMap().getLayers()); + var sources = Object.keys(getApp().getMap().getMirrors()).concat(getApp().getMap().getLayers()); setMapSources(sources); }); CommandModeOptionsChangedEvent.on((commandModeOptions) => { diff --git a/frontend/react/src/unit/unitsmanager.ts b/frontend/react/src/unit/unitsmanager.ts index 48e47a44..3d797309 100644 --- a/frontend/react/src/unit/unitsmanager.ts +++ b/frontend/react/src/unit/unitsmanager.ts @@ -48,10 +48,10 @@ export class UnitsManager { constructor() { this.#unitDatabase = new UnitDatabase(); - this.#unitDatabase.load(getApp().getExpressAddress() + "api/databases/units/aircraftdatabase", "aircraft"); - this.#unitDatabase.load(getApp().getExpressAddress() + "api/databases/units/helicopterdatabase", "helicopter"); - this.#unitDatabase.load(getApp().getExpressAddress() + "api/databases/units/groundunitdatabase", "groundunit"); - this.#unitDatabase.load(getApp().getExpressAddress() + "api/databases/units/navyunitdatabase", "navyunit"); + this.#unitDatabase.load("./api/databases/units/aircraftdatabase", "aircraft"); + this.#unitDatabase.load("./api/databases/units/helicopterdatabase", "helicopter"); + this.#unitDatabase.load("./api/databases/units/groundunitdatabase", "groundunit"); + this.#unitDatabase.load("./api/databases/units/navyunitdatabase", "navyunit"); CommandModeOptionsChangedEvent.on(() => { Object.values(this.#units).forEach((unit: Unit) => unit.updateVisibility());