diff --git a/client/public/stylesheets/atc.css b/client/public/stylesheets/atc.css index 7eb22afb..652d866e 100644 --- a/client/public/stylesheets/atc.css +++ b/client/public/stylesheets/atc.css @@ -67,17 +67,26 @@ border:1px solid #cc0000; } -.ol-strip-board-headers :nth-child(1), -.ol-strip-board-headers :nth-child(2), -.ol-strip-board-strip :nth-child(1), -.ol-strip-board-strip :nth-child(2) { +[data-board-type="ground"] .ol-strip-board-headers :nth-child(1), +[data-board-type="ground"] .ol-strip-board-headers :nth-child(2), +[data-board-type="ground"] .ol-strip-board-strip :nth-child(1), +[data-board-type="ground"] .ol-strip-board-strip :nth-child(2) { width:120px; } -.ol-strip-board-strip :nth-child(4) { +[data-board-type="ground"] .ol-strip-board-strip :nth-child(4) { text-align: center; } + + +[data-board-type="tower"] .ol-strip-board-strip :nth-child(2) input { + width:25px; +} + + + + .ol-strip-board-strip > [data-point="name"] { text-overflow: ellipsis; overflow:hidden; @@ -111,4 +120,13 @@ .ol-strip-board-add-flight input { border-bottom-left-radius: var( --border-radius-sm ); border-top-left-radius: var( --border-radius-sm ); +} + + +[data-board-type="ground"] { + translate: 0 100%; +} + +[data-board-type="tower"] { + translate: 0 -100%; } \ No newline at end of file diff --git a/client/routes/api/atc.js b/client/routes/api/atc.js index 517533cb..82e8865a 100644 --- a/client/routes/api/atc.js +++ b/client/routes/api/atc.js @@ -25,8 +25,9 @@ function uuidv4() { -function Flight( name ) { +function Flight( name, boardId ) { this.id = uuidv4(); + this.boardId = boardId; this.name = name; this.status = "unknown"; this.takeoffTime = -1; @@ -35,6 +36,7 @@ function Flight( name ) { Flight.prototype.getData = function() { return { "id" : this.id, + "boardId" : this.boardId, "name" : this.name, "status" : this.status, "takeoffTime" : this.takeoffTime @@ -116,7 +118,20 @@ const dataHandler = new ATCDataHandler( { app.get( "/flight", ( req, res ) => { - res.json( dataHandler.getFlights() ); + let flights = Object.values( dataHandler.getFlights() ); + + if ( flights && req.query.boardId ) { + + flights = flights.reduce( ( acc, flight ) => { + if ( flight.boardId === req.query.boardId ) { + acc[ flight.id ] = flight; + } + return acc; + }, {} ); + + } + + res.json( flights ); }); @@ -157,11 +172,15 @@ app.patch( "/flight/:flightId", ( req, res ) => { app.post( "/flight", ( req, res ) => { + if ( !req.body.boardId ) { + res.status( 400 ).send( "Invalid/missing boardId" ); + } + if ( !req.body.name ) { res.status( 400 ).send( "Invalid/missing flight name" ); } - const flight = new Flight( req.body.name ); + const flight = new Flight( req.body.name, req.body.boardId ); dataHandler.addFlight( flight ); diff --git a/client/src/atc/atc.ts b/client/src/atc/atc.ts index d63634bf..af8a682e 100644 --- a/client/src/atc/atc.ts +++ b/client/src/atc/atc.ts @@ -1,8 +1,10 @@ import { ATCBoard } from "./atcboard"; -import { ATCBoardFlight } from "./board/flight"; +import { ATCBoardGround } from "./board/ground"; +import { ATCBoardTower } from "./board/tower"; export interface FlightInterface { id : string; + boardId : string; name : string; status : "unknown"; takeoffTime : number; @@ -25,8 +27,16 @@ class ATCDataHandler { } - getFlights() { - return this.#flights; + getFlights( boardId:string ) { + + return Object.values( this.#flights ).reduce( ( acc:{[key:string]: FlightInterface}, flight ) => { + + if ( flight.boardId === boardId ) { + acc[ flight.id ] = flight; + } + + return acc; + }, {} ); } @@ -119,7 +129,22 @@ export class ATC { document.querySelectorAll( ".ol-strip-board" ).forEach( board => { if ( board instanceof HTMLElement ) { - this.addBoard( new ATCBoardFlight( this, board ) ); + + switch ( board.dataset.boardType ) { + + case "ground": + this.addBoard( new ATCBoardGround( this, board ) ); + return; + + case "tower": + this.addBoard( new ATCBoardTower( this, board ) ); + return; + + default: + console.warn( "Unknown board type for ATC board, got: " + board.dataset.boardType ); + + } + } }); diff --git a/client/src/atc/atcboard.ts b/client/src/atc/atcboard.ts index 0ab9f52d..5a54fd92 100644 --- a/client/src/atc/atcboard.ts +++ b/client/src/atc/atcboard.ts @@ -1,6 +1,6 @@ import { Draggable } from "leaflet"; import { Dropdown } from "../controls/dropdown"; -import { zeroAppend } from "../other/utils"; +import { generateUUIDv4, zeroAppend } from "../other/utils"; import { ATC } from "./atc"; export interface StripBoardStripInterface { @@ -12,6 +12,7 @@ export interface StripBoardStripInterface { export abstract class ATCBoard { #atc:ATC; + #boardId:string = ""; #templates: {[key:string]: string} = {}; // Elements @@ -27,7 +28,9 @@ export abstract class ATCBoard { #updateIntervalDelay:number = 1000; - constructor( atc:ATC, boardElement:HTMLElement ) { + constructor( atc:ATC, boardElement:HTMLElement, options?:{[key:string]: any} ) { + + options = options || {}; this.#atc = atc; this.#boardElement = boardElement; @@ -51,6 +54,24 @@ export abstract class ATCBoard { this.updateClock(); }, 1000 ); + + } + + + addFlight( flightName:string ) { + + return fetch( '/api/atc/flight/', { + method: 'POST', + headers: { + 'Accept': '*/*', + 'Content-Type': 'application/json' + }, + "body": JSON.stringify({ + "boardId" : this.getBoardId(), + "name" : flightName + }) + }); + } @@ -108,6 +129,11 @@ export abstract class ATCBoard { } + getBoardId(): string { + return this.getBoardElement().id; + } + + getStripBoardElement() { return this.#stripBoardElement; } @@ -130,11 +156,6 @@ export abstract class ATCBoard { } - protected update() { - console.warn( "No custom update method defined." ); - } - - setTemplates( templates:{[key:string]: string} ) { this.#templates = templates; } @@ -174,6 +195,11 @@ export abstract class ATCBoard { } + protected update() { + console.warn( "No custom update method defined." ); + } + + updateClock() { const now = this.#atc.getMissionDateTime(); diff --git a/client/src/atc/board/flight.ts b/client/src/atc/board/ground.ts similarity index 92% rename from client/src/atc/board/flight.ts rename to client/src/atc/board/ground.ts index b9830fc8..236f01a4 100644 --- a/client/src/atc/board/flight.ts +++ b/client/src/atc/board/ground.ts @@ -1,10 +1,9 @@ -import { getMissionData } from "../.."; import { Dropdown } from "../../controls/dropdown"; import { ATC } from "../atc"; -import { ATCBoard, StripBoardStripInterface } from "../atcboard"; +import { ATCBoard } from "../atcboard"; -export class ATCBoardFlight extends ATCBoard { +export class ATCBoardGround extends ATCBoard { constructor( atc:ATC, element:HTMLElement ) { @@ -45,16 +44,7 @@ export class ATCBoardFlight extends ATCBoard { return; } - fetch( '/api/atc/flight/', { - method: 'POST', - headers: { - 'Accept': '*/*', - 'Content-Type': 'application/json' - }, - "body": JSON.stringify({ - "name": flightName.value - }) - }); + this.addFlight( flightName.value ); form.reset(); @@ -71,7 +61,7 @@ export class ATCBoardFlight extends ATCBoard { update() { - const flights = Object.values( this.getATC().getDataHandler().getFlights() ); + const flights = Object.values( this.getATC().getDataHandler().getFlights( this.getBoardId() ) ); const stripBoard = this.getStripBoardElement(); const missionTime = this.getATC().getMissionDateTime().getTime(); diff --git a/client/src/other/utils.ts b/client/src/other/utils.ts index 5e591a94..69c164c7 100644 --- a/client/src/other/utils.ts +++ b/client/src/other/utils.ts @@ -69,6 +69,14 @@ export function distance(lat1: number, lon1: number, lat2: number, lon2: number) } +export function generateUUIDv4() { + return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { + var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); + return v.toString(16); + }); +} + + export function keyEventWasInInput( event:KeyboardEvent ) { const target = event.target; diff --git a/client/views/atc.ejs b/client/views/atc.ejs index 062f5738..fb007578 100644 --- a/client/views/atc.ejs +++ b/client/views/atc.ejs @@ -1,8 +1,35 @@ -
+
+

Tower

+
+
+ +
+
+
Flight
+
+
+
+ + + +
+ + +
+ +
+ +
+

Ground

diff --git a/client/views/navbar.ejs b/client/views/navbar.ejs index d7dad433..04296162 100644 --- a/client/views/navbar.ejs +++ b/client/views/navbar.ejs @@ -56,7 +56,7 @@
ATC
- +
\ No newline at end of file