diff --git a/webapp/package-lock.json b/webapp/package-lock.json index b39fa2e..81aebf5 100644 --- a/webapp/package-lock.json +++ b/webapp/package-lock.json @@ -12,6 +12,7 @@ "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", "bootstrap": "^5.3.2", + "leaflet": "^1.9.4", "leaflet-contextmenu": "^1.4.0", "milsymbol": "^2.2.0", "react": "^18.2.0", @@ -11822,8 +11823,7 @@ "node_modules/leaflet": { "version": "1.9.4", "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.4.tgz", - "integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==", - "peer": true + "integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==" }, "node_modules/leaflet-contextmenu": { "version": "1.4.0", diff --git a/webapp/package.json b/webapp/package.json index d770882..a6b2625 100644 --- a/webapp/package.json +++ b/webapp/package.json @@ -7,6 +7,7 @@ "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", "bootstrap": "^5.3.2", + "leaflet": "^1.9.4", "leaflet-contextmenu": "^1.4.0", "milsymbol": "^2.2.0", "react": "^18.2.0", diff --git a/webapp/src/components/Debug/Debug.jsx b/webapp/src/components/Debug/Debug.jsx index 232e343..289afec 100644 --- a/webapp/src/components/Debug/Debug.jsx +++ b/webapp/src/components/Debug/Debug.jsx @@ -1,6 +1,5 @@ import React from "react"; import {w3cwebsocket as W3CWebSocket} from "websocket" -import MyMap from "./components/map/map.jsx" import PerceivedTruth from "./components/perceivedTruth/perceivedTruth.jsx"; import "./Debug.scss" import { useEffect, useState } from 'react' @@ -20,6 +19,8 @@ const config = { function Scenarios() { const [trackList, settrackList] = useState([]); + const [entityTracklist, setEntityTracklist] = useState([]); + const [clientConnected, setclientConnected] = useState(false); // const [client, setclient] = useState(W3CWebSocket); @@ -55,14 +56,16 @@ useEffect(() => { if(message.data !== "null") { + // console.log(message.data); const dataFromServer = JSON.parse(message.data); - // console.log(dataFromServer); + if(dataFromServer.Data === "COP") { settrackList(dataFromServer.Entities); }else { - console.log(message.data); + // console.log(dataFromServer); + setEntityTracklist(dataFromServer) } } @@ -115,10 +118,10 @@ return(

Debug

- +
- + diff --git a/webapp/src/components/Debug/Debug.scss b/webapp/src/components/Debug/Debug.scss index 731aa18..ec0da5d 100644 --- a/webapp/src/components/Debug/Debug.scss +++ b/webapp/src/components/Debug/Debug.scss @@ -4,6 +4,6 @@ } .InfoPane{ - width: 70%; + width: 100%; padding-left: 1rem } \ No newline at end of file diff --git a/webapp/src/components/Debug/components/map/map.jsx b/webapp/src/components/Debug/components/map/map.jsx deleted file mode 100644 index 217c25e..0000000 --- a/webapp/src/components/Debug/components/map/map.jsx +++ /dev/null @@ -1,26 +0,0 @@ -import { useLeafletContext } from '@react-leaflet/core' -import { MapContainer, TileLayer} from 'react-leaflet' - -import L from 'leaflet' -import { useEffect, useRef } from 'react' - -import "./map.scss" - - - -const center = [54, 8]; - -function MyMap() { - return ( - -
- - - -
- ) - -} - export default MyMap; \ No newline at end of file diff --git a/webapp/src/components/Debug/components/perceivedTruth/map/map.jsx b/webapp/src/components/Debug/components/perceivedTruth/map/map.jsx new file mode 100644 index 0000000..d0a1d16 --- /dev/null +++ b/webapp/src/components/Debug/components/perceivedTruth/map/map.jsx @@ -0,0 +1,185 @@ +import { useLeafletContext } from '@react-leaflet/core' +import { MapContainer, TileLayer, Marker,Tooltip} from 'react-leaflet' + +import L, { Icon, icon } from 'leaflet' +import { useEffect, useState,useRef, useCallback,useMemo } from 'react' + +import "./map.scss" + +import { OwnShipIcon, createIcon } from '../../../../SimControl/components/OpenSeaMap/icon' + + + + +const zoom = 9 + +function DisplayPosition({ map,center }) { + const [position, setPosition] = useState(() => map.getCenter()) + + // const onClick = useCallback(() => { + // map.setView(center, zoom) + // }, [map]) + + const onMove = useCallback(() => { + + setPosition(map.getCenter()) + }, [map]) + + + useEffect(() => { + map.setView(center, zoom) + + + }, [center, map]) + + + useEffect(() => { + map.on('move', onMove) + return () => { + map.off('move', onMove) + } + }, [map, onMove]) + + return ( +

+ latitude: {position.lat.toFixed(4)}, longitude: {position.lng.toFixed(4)}{' '} + {/* */} +

+ ) +} + +function MyMap({center,Tracklist}) { + const [map, setMap] = useState(null) + const [mapcenter, setMapcenter] = useState([51.505, -0.09]) + const [isFocused, setIsFocused] = useState(false) + const [trackList,setTracklist] = useState([]) + +// const OwnShipIcon = L.icon({ +// iconUrl: 'Own_Ship.svg', + +// iconSize: [50, 50], // size of the icon + +// }); + + useEffect(() => { + // console.log(center); + if(center.length !== 0) + { + setMapcenter(center); + setIsFocused(true); + + } + + + }, [center]); + + useEffect(() => { + // console.log(Tracklist); + // makeList(Tracklist.Tracks) + var tracks = Tracklist.Tracks + + var list = []; + // var Symbol = { + // ID: "1234", + // Name:"Own Ship", + // Position: mapcenter , + // IconData: OwnShipIcon, + // } + // list.push(Symbol); + // setTracklist(list); + + if(tracks === undefined) + { + return; + } + tracks.forEach(element => { + console.log(element) + + var Symbol = { + ID: element.ID, + Name:element.Name, + Position: [element.Position.PositionGeodesic.lat, element.Position.PositionGeodesic.lon] , + IconData: createIcon(element.Type, element.Side), + } + + list.push(Symbol); + + + }); + // console.log(list); + setTracklist(list); + + + + }, [Tracklist, mapcenter]); + + + + // function makeList(tracks) + // { + + + // } + + + function makeIcons() + { + if(trackList === undefined) + { + return; + } + + var list =[]; + trackList.forEach(element => { + list.push( + + + {element.Name} + + ) + + }) + + return( + list + ) + } + + + const displayMap = useMemo( + () => ( + + + + {isFocused ? + + {"Own Ship"} + + :null } + { makeIcons()} + { + + } + + + ), + [isFocused, mapcenter, trackList], + ) + + return ( +
+ {map ? : null} + {displayMap } +
+ ) +} + +export default MyMap; diff --git a/webapp/src/components/Debug/components/map/map.scss b/webapp/src/components/Debug/components/perceivedTruth/map/map.scss similarity index 89% rename from webapp/src/components/Debug/components/map/map.scss rename to webapp/src/components/Debug/components/perceivedTruth/map/map.scss index 0e09714..2ca9f4d 100644 --- a/webapp/src/components/Debug/components/map/map.scss +++ b/webapp/src/components/Debug/components/perceivedTruth/map/map.scss @@ -2,7 +2,7 @@ // display: flex; // padding-top: 10px; height: 500px; - width: 500px; + width: 100%; // padding-left: 20%; display: inline-flex; // height: 80%; diff --git a/webapp/src/components/Debug/components/perceivedTruth/map/tmp.scss b/webapp/src/components/Debug/components/perceivedTruth/map/tmp.scss new file mode 100644 index 0000000..6fe61b0 --- /dev/null +++ b/webapp/src/components/Debug/components/perceivedTruth/map/tmp.scss @@ -0,0 +1,66 @@ +.App { + display: flex; + text-align: center; + } + + .App-logo { + height: 40vmin; + pointer-events: none; + } + + @media (prefers-reduced-motion: no-preference) { + .App-logo { + animation: App-logo-spin infinite 20s linear; + } + } + + .App-header { + background-color: #282c34; + min-height: 100vh; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + font-size: calc(10px + 2vmin); + color: white; + } + + .App-link { + color: #61dafb; + } + + @keyframes App-logo-spin { + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } + } + + .leaflet-container { + width: 70vw; + height: 100vh; + } + + .sidebar { + box-sizing: border-box; + padding: 2em; + width: 30vw; + } + + .sidebar h2, + .sidebar p, + .sidebar ul { + text-align: left; + } + + .sidebar h2 { + margin-top: 0; + } + + .sidebar button { + width: 100%; + font-weight: bold; + padding: .8em 1em; + } \ No newline at end of file diff --git a/webapp/src/components/Debug/components/perceivedTruth/perceivedTruth.jsx b/webapp/src/components/Debug/components/perceivedTruth/perceivedTruth.jsx index 94fcd76..37f67d4 100644 --- a/webapp/src/components/Debug/components/perceivedTruth/perceivedTruth.jsx +++ b/webapp/src/components/Debug/components/perceivedTruth/perceivedTruth.jsx @@ -1,13 +1,22 @@ import { useEffect, useState } from 'react' import { getWSTestMessage ,getTracklist } from '../../../api/APICalls'; +import MyMap from "./map/map.jsx" - +import "./perceivedTruth.scss" +import TrackList from './tracklist/tracklist.jsx'; function PerceivedTruth(props) { const [selectedOption, setSelectedOption] = useState('option1') + const [selectedOptionFull, setSelectedOptionFull] = useState({ + ID : null, + Label:"", + Position: [] + }) + + const [selectOptions, setSelectOptions] = useState([]) const [trackList, settrackList] = useState([]); @@ -16,6 +25,14 @@ function PerceivedTruth(props) const handleSubmit = (event) => { if(selectedOption !== "option1" && selectedOption !== "" ) { + + let updatedValue = getAttributesForID(selectedOption); + + setSelectedOptionFull(selectedOptionFull => ({ + ...selectedOptionFull, + ...updatedValue + })); + client.send(getTracklist(selectedOption)); event.preventDefault() console.log(`Submitted selected option: ${selectedOption}`) @@ -23,17 +40,40 @@ function PerceivedTruth(props) } } + function getAttributesForID(ID) + { + let attributes = { + ID: undefined, + Name: "", + Position : [] + + }; + + selectOptions.forEach(element => { + // console.log(element); + + if(element.value === ID) + { + attributes.ID = ID; + attributes.Name = element.label; + attributes.Position = element.position; + } + }) + return attributes; + } + function prepareTracklistForSelect(Tracklist) { if(Tracklist!== undefined) { var options = []; Tracklist.forEach(element => { - + var item = { value : element.id, - label : element.Name + label : element.Name, + position: element.Position }; @@ -49,36 +89,42 @@ function PerceivedTruth(props) useEffect(() => { //Runs on the first render //And any time any dependency value changes - // console.log(props); + console.log(props.EntityTracklist); setclient(props.Client); settrackList(props.Tracklist); prepareTracklistForSelect(trackList); - }, [props]); + + }, [props, trackList]); return( -
-
- +
+
+ + + + + - - - +

{ selectedOptionFull.Label}

- - + + +
+
+ +
)} diff --git a/webapp/src/components/Debug/components/perceivedTruth/perceivedTruth.scss b/webapp/src/components/Debug/components/perceivedTruth/perceivedTruth.scss index e69de29..2da860b 100644 --- a/webapp/src/components/Debug/components/perceivedTruth/perceivedTruth.scss +++ b/webapp/src/components/Debug/components/perceivedTruth/perceivedTruth.scss @@ -0,0 +1,14 @@ +.box{ + display: flex; + width: 100%; +} +.EntityTracklist +{ + width: 50%; +} + +.SideMap{ + width: 40%; + justify-content: center; + margin: 0 auto; +} \ No newline at end of file diff --git a/webapp/src/components/Debug/components/perceivedTruth/tracklist/tracklist.jsx b/webapp/src/components/Debug/components/perceivedTruth/tracklist/tracklist.jsx new file mode 100644 index 0000000..85a9f6b --- /dev/null +++ b/webapp/src/components/Debug/components/perceivedTruth/tracklist/tracklist.jsx @@ -0,0 +1,89 @@ +import React, { useEffect, useState } from 'react' +import "./tracklist.scss" + +import round from "../../../../Utils.jsx" + +function TrackList(props) +{ + const [tracklist, setTracklist] = useState(Array) + + useEffect(() => { + + setTracklist(Array); + // console.log(props) + + }, []); + useEffect(() => { + + if(props.Tracklist.Tracks !== undefined) + { + setTracklist(props.Tracklist.Tracks); + + } + // console.log(props) + + }, [props]); + + function MakeSensorList(props) + { + if(props === undefined) + { + return; + } + + var list = []; + props.Sensors.forEach(element => { + list.push( {element.Name} Range: {element.Range} NM ) + + }); + + return(list); + + } + + return ( +
+
+
+
+
NR
+
Name
+
Position
+
Bearing
+
Range
+
Sensors
+
+ {/* {} */} + + { + tracklist.map( (elem,index) => { + if(elem.Position !== undefined) + { + // console.log(elem) + + return( +
+ +
{index}
+
{elem.Name}
+
{round(elem.Position.PositionGeodesic.lat,4)}, {round(elem.Position.PositionGeodesic.lon,4)}
+
{round(elem.Bearing,2)}
+
{round(elem.Distance,2)}
+
{MakeSensorList(elem) }
+
+ ) + } + }) + } + + +
+
+ + + + +
+ )} + +export default TrackList; diff --git a/webapp/src/components/Debug/components/perceivedTruth/tracklist/tracklist.scss b/webapp/src/components/Debug/components/perceivedTruth/tracklist/tracklist.scss new file mode 100644 index 0000000..c1a44e1 --- /dev/null +++ b/webapp/src/components/Debug/components/perceivedTruth/tracklist/tracklist.scss @@ -0,0 +1,30 @@ +/* DivTable.com */ +.divTable{ + display: table; + width: 100%; +} +.divTableRow { + display: table-row; +} +.divTableHeading { + background-color: #EEE; + display: table-header-group; +} +.divTableCell, .divTableHead { + border: 1px solid #999999; + display: table-cell; + padding: 3px 10px; +} +.divTableHeading { + background-color: #EEE; + display: table-header-group; + font-weight: bold; +} +.divTableFoot { + background-color: #EEE; + display: table-footer-group; + font-weight: bold; +} +.divTableBody { + display: table-row-group; +} \ No newline at end of file diff --git a/webapp/src/components/SimControl/SimControl.jsx b/webapp/src/components/SimControl/SimControl.jsx index 6f69743..5b81d0d 100644 --- a/webapp/src/components/SimControl/SimControl.jsx +++ b/webapp/src/components/SimControl/SimControl.jsx @@ -14,7 +14,7 @@ import Track from "./Track.tsx"; import './SimControl.scss' import EntityTrackList from "./components/EntityTrackList"; -import { getWSTestMessage } from "../api/APICalls"; +import { getCOP, getWSTestMessage } from "../api/APICalls"; @@ -126,7 +126,7 @@ class SimControl extends Component { // Data: "COP" // } - client.send(getWSTestMessage()); + client.send(getCOP()); } getEntityFromID(Entities, SelectedEntity)