From ea1178a7decfbc2f1ce9f5ab099576eae1d52773 Mon Sep 17 00:00:00 2001 From: Fernando del Campo Date: Wed, 12 Apr 2023 16:45:54 -0400 Subject: [PATCH] refactor about the use of telemetries of the flight tracker and the styles --- love/src/Config.js | 10 + .../FlightTracker/FlightTracker.container.jsx | 41 ++-- .../FlightTracker/FlightTracker.jsx | 200 +++++++----------- .../FlightTracker/FlightTracker.module.css | 37 ++++ 4 files changed, 154 insertions(+), 134 deletions(-) diff --git a/love/src/Config.js b/love/src/Config.js index a711a68416..281fc8a113 100644 --- a/love/src/Config.js +++ b/love/src/Config.js @@ -1072,6 +1072,16 @@ export const mtdomeMotionStateMap = { 32: 'STOPPING MOTOR COOLING', }; +export const flightTrackerStateToMap = { + 0: 'DISCONNECTED', + 1: 'CONNECTED', +} + +export const flightTrackerStatetoStyle = { + DISCONNECTED: 'warning', + CONNECTED: 'running', +}; + export const mtdomeElevationEnabledStateToMap = { 0: 'DISABLED', 1: 'ENABLED', diff --git a/love/src/components/FlightTracker/FlightTracker.container.jsx b/love/src/components/FlightTracker/FlightTracker.container.jsx index 6f93d264ae..734b37bae6 100644 --- a/love/src/components/FlightTracker/FlightTracker.container.jsx +++ b/love/src/components/FlightTracker/FlightTracker.container.jsx @@ -1,7 +1,8 @@ import React from 'react'; +import PropTypes from 'prop-types'; import { connect } from 'react-redux'; import { addGroup, removeGroup } from 'redux/actions/ws'; -import { getStreamData } from 'redux/selectors'; +import { getFlightTracker } from 'redux/selectors'; import FlightTracker from './FlightTracker'; import SubscriptionTableContainer from 'components/GeneralPurpose/SubscriptionTable/SubscriptionTable.container'; @@ -24,36 +25,46 @@ export const schema = { }, }; -const FlightTrackerContainer = ({ - ...props -}) => { - if (props.isRaw) { - return ; +const FlightTrackerContainer = ({ isRaw, subscriptions, status, aircrafts }) => { + if (isRaw) { + return ; } return ( - + ); }; +const mapStateToProps = (state) => { + const data = getFlightTracker(state); + return { + status: data.status, + aircrafts: data.aircrafts, + } +} + const mapDispatchToProps = (dispatch, ownProps) => { const subscriptions = [ + 'telemetry-FlightTracker-0-data', ]; return { subscriptions, subscribeToStreams: () => { - subscriptions.forEach((s) => dispatch(addGroup(s))); + subscriptions.forEach((stream) => dispatch(addGroup(stream))); }, unsubscribeToStreams: () => { - subscriptions.forEach((s) => dispatch(removeGroup(s))); + subscriptions.forEach((stream) => dispatch(removeGroup(stream))); }, }; }; -const mapStateToProps = (state) => { - //const streams = getStreamsData(state, groupNames); - return { - //streams, - } -} +FlightTrackerContainer.propTypes = { + /** Wheter the component is in raw mode */ + isRaw: PropTypes.bool, + /** List of the component's subscriptions */ + subscriptions: PropTypes.array, +}; export default connect(mapStateToProps, mapDispatchToProps)(FlightTrackerContainer); diff --git a/love/src/components/FlightTracker/FlightTracker.jsx b/love/src/components/FlightTracker/FlightTracker.jsx index 52329a5b37..30020d631c 100644 --- a/love/src/components/FlightTracker/FlightTracker.jsx +++ b/love/src/components/FlightTracker/FlightTracker.jsx @@ -1,5 +1,5 @@ import React, { Component } from 'react'; -import styles from './FlightTracker.module.css'; +import PropTypes from 'prop-types'; import MapFlightTracker from './MapFlightTracker'; import Value from '../GeneralPurpose/SummaryPanel/Value'; import Title from '../GeneralPurpose/SummaryPanel/Title'; @@ -10,21 +10,43 @@ import SimpleTable from 'components/GeneralPurpose/SimpleTable/SimpleTable'; import ManagerInterface from 'Utils'; import ZoomInIcon from 'components/icons/Zoom/ZoomInIcon'; import ZoomOutIcon from 'components/icons/Zoom/ZoomOutIcon'; +import moment from 'moment'; +import { flightTrackerStateToMap, flightTrackerStatetoStyle } from 'Config'; +import styles from './FlightTracker.module.css'; const DEFAULT_POLLING_TIMEOUT = 5000; export default class FlightTracker extends Component { + static propTypes = { + status: PropTypes.number, + aircrafts: PropTypes.arrayOf(PropTypes.objectOf({ + id: PropTypes.string, + latitude: PropTypes.number, + longitude: PropTypes.number, + altitude: PropTypes.number, + track: PropTypes.number, + distance: PropTypes.number, + speed: PropTypes.number, + })), + + }; + + static defaultProps = { + status: 0, + aircrafts: [], + }; + constructor(props) { super(props); this.pollingInterval = null; this.countPollingIterval = null; this.state = { - planes: [], - planesState: {}, lastUpdate: 0, - planesDistance: {}, zoom: '200', + aircraftInRadius: 0, }; + this.RADIO1 = 160; // Distance of Warning + this.RADIO2 = 100; // Distance of Alert } /** @@ -48,95 +70,24 @@ export default class FlightTracker extends Component { return d; }; - componentDidUpdate = (prevProps, prevState) => { - const RADIO1 = 160; - const RADIO2 = 100; - - if (!isEqual(prevState.planes, this.state.planes)) { - // const newTimers = prevState.timers; - const newPlanesState = prevState.planesState; - const newPlanesDistance = {}; - - const listIdPlanes = []; - this.state.planes.map((value) => { - listIdPlanes.push(value.id); - }); - - //Delete the planes that are no longer there from planesState - prevState.planes.map((value) => { - if (!(value.id in listIdPlanes)) { - delete newPlanesState[id]; - } - }); - - this.state.planes.map((value) => { - const { loc, id } = value; - - const dist = this.planeDistance(loc); - newPlanesDistance[id] = dist; - //Add the new planes in planeState - if (!newPlanesState.hasOwnProperty(id)) newPlanesState[id] = 'running'; - - //Plane inside RADIO1 - if (dist < RADIO1) { - //Plane between RADIO1 and RADIO2 - if (!dist < RADIO2) { - if (this.state.planesState[id] != 'warning') newPlanesState[id] = 'warning'; - } - //Plane within RADIO2 - else { - if (this.state.planesState[id] != 'alert') newPlanesState[id] = 'alert'; - } - } else { - if (this.state.planesState[id] != 'running') { - newPlanesState[id] = 'running'; - } - } + componentDidUpdate = (prevProps) => { + if(!isEqual(prevProps.aircrafts, this.props.aircrafts)) { + const aircraftInRadius = this.props.aircrafts.filter((aircraft) => aircraft.id !== undefined && + aircraft.id !== null && aircraft.id !== '' ).length; + this.setState({ + aircraftInRadius: aircraftInRadius, + lastUpdate: Date.now(), }); - - //setState with the parameters newPlanesState - this.setState({ planesState: newPlanesState, planesDistance: newPlanesDistance }); } }; componentDidMount = () => { - //Get Planes's data from API initial - ManagerInterface.getDataFlightTracker('(-30.2326, -70.7312)', '200').then((res) => { - //Set up initial state planesState - const planesStateIN = {}; - // const timers = {}; - const planeDistance = {}; - res.map((value) => { - planesStateIN[value.id] = 'running'; - const distance = this.planeDistance(value.loc); - planeDistance[value.id] = distance; - if (distance < 160) { - if (distance < 100) planesStateIN[value.id] = 'alert'; - else planesStateIN[value.id] = 'warning'; - } - }); - - this.setState({ - planes: res, - lastUpdate: Date.now(), - planesState: planesStateIN, - planesDistance: planeDistance, - }); + const aircraftInRadius = this.props.aircrafts.filter((aircraft) => aircraft.id !== undefined && + aircraft.id !== null && aircraft.id !== '' ).length; + this.setState({ + aircraftInRadius: aircraftInRadius, + lastUpdate: Date.now(), }); - - //Get Planes's data from API every x seconds. - if (this.pollingInterval) clearInterval(this.pollingInterva); - this.pollingInterval = setInterval( - () => { - ManagerInterface.getDataFlightTracker('(-30.2326, -70.7312)', '200').then((res) => { - this.setState({ - planes: res, - lastUpdate: Date.now(), - }); - }); - }, - this.props.pollingTimeout ? this.props.pollingTimeout * 1000 : DEFAULT_POLLING_TIMEOUT, - ); }; /** @@ -157,12 +108,25 @@ export default class FlightTracker extends Component { else if (zoom === '160') this.setState({ zoom: '200' }); }; + /** + * Function to determine the status of the aircraft, from the distance to the radar + */ + distanceStatus = (distance) => { + if (distance < this.RADIO2) return 'alert'; + if (distance < this.RADIO1) return 'warning'; + return 'running'; + } + render() { - const headers = [ + const tableData = []; + const headers= [ { field: 'id', title: 'AirCraft ID', type: 'string', + render: (value) => { + return value ?? '-'; + }, }, { field: 'distance', @@ -170,61 +134,51 @@ export default class FlightTracker extends Component { type: 'array', className: styles.statusColumn, render: (value) => { - return ( - - {value[0].toString() + 'km'} + if (value) return ( + + {value.toString() + ' km'} ); + else return '-'; }, }, { field: 'latitude', title: 'Latitude', render: (value) => { - return Math.round(value * 100) / 100; + if (value) return Math.round(value * 100) / 100; + else return '-'; }, }, { field: 'longitude', title: 'Longitude', render: (value) => { - return Math.round(value * 1000) / 1000; + if (value) return Math.round(value * 1000) / 1000; + else return '-'; }, }, - { - field: 'vel', - title: 'Velocity', + field: 'speed', + title: 'Ground Speed', type: 'string', render: (value) => { - return value + 'mph'; + if (value) return value + ' mph'; + else return '-'; }, }, ]; - const { planes } = this.state; - const tableData = []; - planes.forEach((element) => { - const { id } = element; - tableData.push({ - ...element, - longitude: element['loc'][0] ?? 'undefined', - latitude: element['loc'][1] ?? 'undefined', - distance: [Math.round(this.state.planesDistance[id]) ?? 'undefined', this.state.planesState[id] ?? 'undefined'], - }); + const { aircrafts, status } = this.props; + aircrafts.forEach(element => { + tableData.push(element); }); const dateNow = Date.now(); - let timerLength = 0; - for (const [key, value] of Object.entries(this.state.planesState)) { - if (value != 'running') { - timerLength += 1; - } - } let zoomOut = this.state.zoom === '200' ? : ; let zoomIn = this.state.zoom === '100' ? : ; - const inRadius = timerLength > 0 ? 'warning' : 'ok'; + const inRadius = this.state.aircraftInRadius > 0 ? 'warning' : 'ok'; return (
@@ -235,8 +189,8 @@ export default class FlightTracker extends Component { Monitoring status
- - {'Connected'} + + {flightTrackerStateToMap[status]}
@@ -247,7 +201,7 @@ export default class FlightTracker extends Component {
- {timerLength.toString()} + {this.state.aircraftInRadius}
@@ -255,7 +209,11 @@ export default class FlightTracker extends Component {
- +
-
LAST UPDATE: {Math.round((dateNow - this.state.lastUpdate) / 1000)}SEC
+
+ LAST UPDATE: { moment(dateNow).format('HH:mm:ss') } + + UPDATE DELAY: {Math.round((dateNow - this.state.lastUpdate) / 1000)} SEC +
); diff --git a/love/src/components/FlightTracker/FlightTracker.module.css b/love/src/components/FlightTracker/FlightTracker.module.css index ca80882fb8..d7e070ca57 100644 --- a/love/src/components/FlightTracker/FlightTracker.module.css +++ b/love/src/components/FlightTracker/FlightTracker.module.css @@ -43,6 +43,14 @@ td.statusColumn { text-align: left; font-size: 80%; margin-block: 1em; + display: grid; + grid-template-columns: 1fr 1fr 1fr; + /* grid-auto-rows: 50px; */ + grid-gap: 10px; +} + +.divLastUp span { + display: flex; } .mapDiv { @@ -86,6 +94,10 @@ td.statusColumn { transform-box: 'fill-box'; } +.textPlane { + fill: var(--secondary-font-color); +} + .statusDiv { display: flex; width: 95%; @@ -137,3 +149,28 @@ td.statusColumn { height: 3em; width: 3em; } + + +.runningFill { + fill: #bcd8e2; +} + +.runningStroke { + stroke: #bcd8e2; +} + +.warningFill { + fill: #d9cd03; +} + +.warningStroke { + stroke: #d9cd03; +} + +.alertStroke { + stroke: #df5601; +} + +.alertFill { + fill: #df5601; +} \ No newline at end of file