From 05d7f848b28e9eb4fafc7ad38b101e75e73fa766 Mon Sep 17 00:00:00 2001 From: LeoKle Date: Tue, 22 Aug 2023 14:54:04 +0200 Subject: [PATCH 01/21] add checkbox to show vertical limits of sectors --- frontend/src/components/Map.tsx | 6 ++- frontend/src/components/Sectors.tsx | 64 +++++++++++++++++++++++++++-- 2 files changed, 65 insertions(+), 5 deletions(-) diff --git a/frontend/src/components/Map.tsx b/frontend/src/components/Map.tsx index 6f4fc09..5565217 100644 --- a/frontend/src/components/Map.tsx +++ b/frontend/src/components/Map.tsx @@ -13,6 +13,7 @@ import { WaypointRecord } from 'interfaces/waypointRecord.interface'; import { DisplayAirspaces } from './Sectors'; import Airspace from '@shared/interfaces/sector.interface'; import sectorService from 'services/sector.service'; +import { Checkbox } from 'primereact/checkbox'; export default function LoaViewerMap() { const [conditions, setConditions] = useState([]); @@ -29,6 +30,8 @@ export default function LoaViewerMap() { const [selectedSector, setSelectedSector] = useState('GIN'); const [selectedFir, setSelectedFir] = useState('EDGG'); + const [showVerticalLimits, setShowVerticalLimits] = useState(false); + useEffect(() => { conditionService.getConditions().then((data: FrontendCondition[]) => { const convertedData: FrontendCondition[] = data.map((element: FrontendCondition) => { @@ -106,6 +109,7 @@ export default function LoaViewerMap() { setSearchInput(e.target.value)} /> setSelectedSector(e.value)} /> setSelectedFir(e.value)} /> + setShowVerticalLimits(!showVerticalLimits)} checked={showVerticalLimits} /> @@ -113,7 +117,7 @@ export default function LoaViewerMap() { url="https://{s}.basemaps.cartocdn.com/dark_nolabels/{z}/{x}/{y}{r}.png" attribution='© OpenStreetMap contributors © CARTO' /> - + diff --git a/frontend/src/components/Sectors.tsx b/frontend/src/components/Sectors.tsx index faddabd..56b3e05 100644 --- a/frontend/src/components/Sectors.tsx +++ b/frontend/src/components/Sectors.tsx @@ -1,14 +1,15 @@ -import { Polygon } from 'react-leaflet'; +import { Marker, Polygon } from 'react-leaflet'; import Airspace from '@shared/interfaces/sector.interface'; -import { LatLngExpression } from 'leaflet'; +import { DivIcon, Icon, LatLngExpression, PointExpression } from 'leaflet'; import React from 'react'; +import { renderToStaticMarkup } from 'react-dom/server'; interface SectorsProps { airspaces: Airspace[]; - combineSectors: Boolean; + showVerticalLimits: Boolean; } -export function DisplayAirspaces({ airspaces, combineSectors }: SectorsProps) { +export function DisplayAirspaces({ airspaces, showVerticalLimits }: SectorsProps) { return (
{airspaces.map((airspace, airspaceIndex) => ( @@ -17,6 +18,7 @@ export function DisplayAirspaces({ airspaces, combineSectors }: SectorsProps) { {airspace.sectors.map((sector, sectorIndex) => ( + {showVerticalLimits && } ))}
@@ -25,6 +27,60 @@ export function DisplayAirspaces({ airspaces, combineSectors }: SectorsProps) { ); } + +function SectorLevelWidget(min: number, max: number) { + let className = 'Marker'; + let iconAnchor = [0, 0] as PointExpression; + let htmlContent; + + if (min === 0) { + htmlContent = ( + + FL{max + 1} +
+ GND +
+ ); + } else { + htmlContent = ( + + FL{max + 1}
+ FL{min} +
+ ); + } + + return new DivIcon({ + className: className, + iconAnchor: iconAnchor, + html: renderToStaticMarkup(htmlContent), + }); +} + +function getAverageOfCoordinates(coordinates: string[][]): LatLngExpression { + let latSum = 0; + let lngSum = 0; + let count = 0; + + coordinates.forEach(([lat, lng]) => { + const latNum = convertLatitudeToNumber(lat); + const lngNum = convertLongitudeToNumber(lng); + + latSum += latNum; + lngSum += lngNum; + + count++; + }); + + const avgLat = latSum / count; + const avgLng = lngSum / count; + + // console.log(avgLat); + // console.log(avgLng); + + return [avgLat, avgLng]; +} + function convertCoordinatestoLatLngExpression(coordinates: string[][]): LatLngExpression[] { return coordinates.map(([lat, lng]) => { const latNum = convertLatitudeToNumber(lat); From 7a0410a2c288ad69430a9c1caa253627fe2f3d93 Mon Sep 17 00:00:00 2001 From: LeoKle Date: Tue, 22 Aug 2023 15:11:25 +0200 Subject: [PATCH 02/21] fix misnamed function --- frontend/src/components/Map.tsx | 2 +- frontend/src/services/sector.service.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/frontend/src/components/Map.tsx b/frontend/src/components/Map.tsx index 6f4fc09..ca0d6db 100644 --- a/frontend/src/components/Map.tsx +++ b/frontend/src/components/Map.tsx @@ -49,7 +49,7 @@ export default function LoaViewerMap() { }); setConditions(convertedData); }); - sectorService.getWaypoints().then((data: Airspace[]) => { + sectorService.getSectors().then((data: Airspace[]) => { const convertedData: Airspace[] = data.map((element: Airspace) => { return { id: element.id, diff --git a/frontend/src/services/sector.service.ts b/frontend/src/services/sector.service.ts index 8877fbf..8c065c2 100644 --- a/frontend/src/services/sector.service.ts +++ b/frontend/src/services/sector.service.ts @@ -1,6 +1,6 @@ import axios from 'axios'; -async function getWaypoints() { +async function getSectors() { try { const response = await axios.get('/api/v1/sectors'); return response.data; @@ -10,5 +10,5 @@ async function getWaypoints() { } export default { - getWaypoints, + getSectors, }; From 0d689fb3046329f4e099084e195f5ee2974a9895 Mon Sep 17 00:00:00 2001 From: LeoKle Date: Tue, 22 Aug 2023 15:27:20 +0200 Subject: [PATCH 03/21] add country property to airspace --- backend/src/models/sector.model.ts | 1 + backend/src/services/sector.service.ts | 1 + shared/src/interfaces/sector.interface.ts | 1 + 3 files changed, 3 insertions(+) diff --git a/backend/src/models/sector.model.ts b/backend/src/models/sector.model.ts index bed8212..2939673 100644 --- a/backend/src/models/sector.model.ts +++ b/backend/src/models/sector.model.ts @@ -10,6 +10,7 @@ export const sectorSchema = new mongoose.Schema({ }); export const airspaceSchema = new mongoose.Schema({ + country: { type: String, required: true }, id: { type: String, required: true }, group: { type: String, required: true }, owner: { type: [String], required: true }, diff --git a/backend/src/services/sector.service.ts b/backend/src/services/sector.service.ts index fce46a6..c57c741 100644 --- a/backend/src/services/sector.service.ts +++ b/backend/src/services/sector.service.ts @@ -23,6 +23,7 @@ async function retrieveAirspacesFromCountries(countries: string[]): Promise Date: Tue, 22 Aug 2023 15:27:37 +0200 Subject: [PATCH 04/21] filter selectable airspaces based on country property --- frontend/src/components/Map.tsx | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/frontend/src/components/Map.tsx b/frontend/src/components/Map.tsx index ca0d6db..06eec09 100644 --- a/frontend/src/components/Map.tsx +++ b/frontend/src/components/Map.tsx @@ -31,7 +31,7 @@ export default function LoaViewerMap() { useEffect(() => { conditionService.getConditions().then((data: FrontendCondition[]) => { - const convertedData: FrontendCondition[] = data.map((element: FrontendCondition) => { + const convertedConditionData: FrontendCondition[] = data.map((element: FrontendCondition) => { return { _id: element._id, aerodrome: element.aerodrome, @@ -47,18 +47,19 @@ export default function LoaViewerMap() { to_fir: element.to_fir, }; }); - setConditions(convertedData); + setConditions(convertedConditionData); }); sectorService.getSectors().then((data: Airspace[]) => { - const convertedData: Airspace[] = data.map((element: Airspace) => { + const convertedAirspaceData: Airspace[] = data.map((element: Airspace) => { return { + country: element.country, id: element.id, group: element.group, owner: element.owner, sectors: element.sectors, }; }); - setAirspaces(convertedData); + setAirspaces(convertedAirspaceData); }); setLoading(false); @@ -77,15 +78,8 @@ export default function LoaViewerMap() { useEffect(() => { const stationsSet: Set = new Set(); for (const airspace of airspaces) { - if (airspace.group === selectedFir) { - const owner = airspace.owner[0]; - // filter approach stations not belonging to vACC Germany - all approach sectors are not using Vatsim callsigns i.e. no _ in their name - const isNonGermanApproachStation = owner.includes('_'); - // filter Maastricht Sectors belonging to vACC Germany - sectors belonging to vACC Germany have 3 or more characters - const isGermanMaastrichtSector = owner.length > 2; - if (!isNonGermanApproachStation && isGermanMaastrichtSector) { - stationsSet.add(owner); - } + if (airspace.country === 'germany' && airspace.group === selectedFir) { + stationsSet.add(airspace.owner[0]); } } From b2a12c740145962e8e2e890cfe3ee75354ac8c33 Mon Sep 17 00:00:00 2001 From: LeoKle Date: Tue, 22 Aug 2023 15:33:13 +0200 Subject: [PATCH 05/21] add switch to first sector if new FIR is selected --- frontend/src/components/Map.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/src/components/Map.tsx b/frontend/src/components/Map.tsx index 06eec09..512329f 100644 --- a/frontend/src/components/Map.tsx +++ b/frontend/src/components/Map.tsx @@ -86,6 +86,7 @@ export default function LoaViewerMap() { const stations: string[] = Array.from(stationsSet); const sortedStations = stations.sort((a, b) => a.localeCompare(b)); setAllStations(sortedStations); + setSelectedSector(sortedStations[0]); }, [selectedFir, loading, airspaces]); useEffect(() => { From c6aa92ed82f57b5f53d22fa4703c01d949afc862 Mon Sep 17 00:00:00 2001 From: LeoKle Date: Wed, 23 Aug 2023 11:47:23 +0200 Subject: [PATCH 06/21] add button to toggle vertical limits of airspaces --- frontend/src/components/Map.tsx | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/frontend/src/components/Map.tsx b/frontend/src/components/Map.tsx index 5565217..590e62b 100644 --- a/frontend/src/components/Map.tsx +++ b/frontend/src/components/Map.tsx @@ -13,7 +13,7 @@ import { WaypointRecord } from 'interfaces/waypointRecord.interface'; import { DisplayAirspaces } from './Sectors'; import Airspace from '@shared/interfaces/sector.interface'; import sectorService from 'services/sector.service'; -import { Checkbox } from 'primereact/checkbox'; +import { Button } from 'primereact/button'; export default function LoaViewerMap() { const [conditions, setConditions] = useState([]); @@ -30,8 +30,6 @@ export default function LoaViewerMap() { const [selectedSector, setSelectedSector] = useState('GIN'); const [selectedFir, setSelectedFir] = useState('EDGG'); - const [showVerticalLimits, setShowVerticalLimits] = useState(false); - useEffect(() => { conditionService.getConditions().then((data: FrontendCondition[]) => { const convertedData: FrontendCondition[] = data.map((element: FrontendCondition) => { @@ -102,6 +100,20 @@ export default function LoaViewerMap() { setDrawnAirspaces(filtered); }, [selectedFir, loading, airspaces, selectedSector]); + // Vertical limits of airspaces + const [showVerticalLimits, setShowVerticalLimits] = useState(false); + const [showVerticalLimitsButtonSeverity, setShowVerticalLimitsButtonServerity] = useState<'success' | 'danger'>('danger'); + const [showVerticalLimitsButtonIcon, setShowVerticalLimitsButtonIcon] = useState<'pi pi-check' | 'pi pi-times'>('pi pi-times'); + + const handleShowVerticalLimitsClick = () => { + // Change style of button + setShowVerticalLimitsButtonServerity(prevSeverity => (prevSeverity === 'danger' ? 'success' : 'danger')); + setShowVerticalLimitsButtonIcon(prevIcon => (prevIcon === 'pi pi-times' ? 'pi pi-check' : 'pi pi-times')); + + // hide / show vertical limits of airspaces + setShowVerticalLimits(!showVerticalLimits); + }; + return ( <>
@@ -109,7 +121,7 @@ export default function LoaViewerMap() { setSearchInput(e.target.value)} /> setSelectedSector(e.value)} /> setSelectedFir(e.value)} /> - setShowVerticalLimits(!showVerticalLimits)} checked={showVerticalLimits} /> +
From 91f80029f3e39a8f33cb0fa77e176f2d187f4c9c Mon Sep 17 00:00:00 2001 From: LeoKle Date: Wed, 23 Aug 2023 11:47:49 +0200 Subject: [PATCH 07/21] change color of airspace borders --- frontend/src/components/Sectors.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/components/Sectors.tsx b/frontend/src/components/Sectors.tsx index 56b3e05..a6d97f4 100644 --- a/frontend/src/components/Sectors.tsx +++ b/frontend/src/components/Sectors.tsx @@ -17,7 +17,7 @@ export function DisplayAirspaces({ airspaces, showVerticalLimits }: SectorsProps
{airspace.sectors.map((sector, sectorIndex) => ( - + {showVerticalLimits && } ))} From c2973950b404b2773d27a082192988b60c0dfa5c Mon Sep 17 00:00:00 2001 From: LeoKle Date: Wed, 23 Aug 2023 12:09:10 +0200 Subject: [PATCH 08/21] update FIR change logic --- frontend/src/components/Map.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/frontend/src/components/Map.tsx b/frontend/src/components/Map.tsx index 512329f..2b27c95 100644 --- a/frontend/src/components/Map.tsx +++ b/frontend/src/components/Map.tsx @@ -86,7 +86,11 @@ export default function LoaViewerMap() { const stations: string[] = Array.from(stationsSet); const sortedStations = stations.sort((a, b) => a.localeCompare(b)); setAllStations(sortedStations); - setSelectedSector(sortedStations[0]); + + // If the FIR changes, select the first station from the FIR + if (!sortedStations.includes(selectedSector as string) && sortedStations.length !== 0) { + setSelectedSector(sortedStations[0]); + } }, [selectedFir, loading, airspaces]); useEffect(() => { From 69562c71b9f22e84605e7cd004b6db8183850698 Mon Sep 17 00:00:00 2001 From: LeoKle Date: Wed, 23 Aug 2023 12:21:32 +0200 Subject: [PATCH 09/21] v2.2.0 --- backend/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/package.json b/backend/package.json index 5ff353d..08b1fb8 100644 --- a/backend/package.json +++ b/backend/package.json @@ -1,6 +1,6 @@ { "name": "loa-viewer-backend", - "version": "2.1.0", + "version": "2.2.0", "description": "", "main": "app.js", "scripts": { From 52f620a83abea81f32ad8dc1b378f314d35f17ac Mon Sep 17 00:00:00 2001 From: LeoKle Date: Wed, 23 Aug 2023 15:03:02 +0200 Subject: [PATCH 10/21] refactor button element --- frontend/src/components/Map.tsx | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/frontend/src/components/Map.tsx b/frontend/src/components/Map.tsx index 01d6f05..0a5b2a4 100644 --- a/frontend/src/components/Map.tsx +++ b/frontend/src/components/Map.tsx @@ -101,17 +101,6 @@ export default function LoaViewerMap() { // Vertical limits of airspaces const [showVerticalLimits, setShowVerticalLimits] = useState(false); - const [showVerticalLimitsButtonSeverity, setShowVerticalLimitsButtonServerity] = useState<'success' | 'danger'>('danger'); - const [showVerticalLimitsButtonIcon, setShowVerticalLimitsButtonIcon] = useState<'pi pi-check' | 'pi pi-times'>('pi pi-times'); - - const handleShowVerticalLimitsClick = () => { - // Change style of button - setShowVerticalLimitsButtonServerity(prevSeverity => (prevSeverity === 'danger' ? 'success' : 'danger')); - setShowVerticalLimitsButtonIcon(prevIcon => (prevIcon === 'pi pi-times' ? 'pi pi-check' : 'pi pi-times')); - - // hide / show vertical limits of airspaces - setShowVerticalLimits(!showVerticalLimits); - }; return ( <> @@ -120,7 +109,12 @@ export default function LoaViewerMap() { setSearchInput(e.target.value)} /> setSelectedSector(e.value)} /> setSelectedFir(e.value)} /> -
From 1dea703cef9ce5ede246fa94e3e9c08daf338233 Mon Sep 17 00:00:00 2001 From: LeoKle Date: Thu, 24 Aug 2023 21:44:28 +0200 Subject: [PATCH 11/21] extract coordinate utility functions --- frontend/src/components/Sectors.tsx | 66 +------------------------- frontend/src/util/coordinate.util.ts | 71 ++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 64 deletions(-) create mode 100644 frontend/src/util/coordinate.util.ts diff --git a/frontend/src/components/Sectors.tsx b/frontend/src/components/Sectors.tsx index a6d97f4..026485b 100644 --- a/frontend/src/components/Sectors.tsx +++ b/frontend/src/components/Sectors.tsx @@ -1,8 +1,9 @@ import { Marker, Polygon } from 'react-leaflet'; import Airspace from '@shared/interfaces/sector.interface'; -import { DivIcon, Icon, LatLngExpression, PointExpression } from 'leaflet'; +import { DivIcon, PointExpression } from 'leaflet'; import React from 'react'; import { renderToStaticMarkup } from 'react-dom/server'; +import { convertCoordinatestoLatLngExpression, getAverageOfCoordinates } from 'util/coordinate.util'; interface SectorsProps { airspaces: Airspace[]; @@ -57,69 +58,6 @@ function SectorLevelWidget(min: number, max: number) { }); } -function getAverageOfCoordinates(coordinates: string[][]): LatLngExpression { - let latSum = 0; - let lngSum = 0; - let count = 0; - - coordinates.forEach(([lat, lng]) => { - const latNum = convertLatitudeToNumber(lat); - const lngNum = convertLongitudeToNumber(lng); - - latSum += latNum; - lngSum += lngNum; - - count++; - }); - - const avgLat = latSum / count; - const avgLng = lngSum / count; - - // console.log(avgLat); - // console.log(avgLng); - - return [avgLat, avgLng]; -} - -function convertCoordinatestoLatLngExpression(coordinates: string[][]): LatLngExpression[] { - return coordinates.map(([lat, lng]) => { - const latNum = convertLatitudeToNumber(lat); - const lngNum = convertLongitudeToNumber(lng); - - return [latNum, lngNum]; - }); -} - -function convertLatitudeToNumber(latitude: string): number { - let latSign = 1; - - if (latitude.startsWith('-')) { - latitude = latitude.slice(1); // Remove the '-' character - latSign = -1; - } - const latDegrees = parseInt(latitude.slice(0, 2)); - const latMinutes = parseInt(latitude.slice(2, 4)); - const latSeconds = parseInt(latitude.slice(4, 9)); - const latNum = (latDegrees + latMinutes / 60 + latSeconds / 3600) * latSign; - - return latNum; -} - -function convertLongitudeToNumber(longitude: string): number { - let latSign = 1; - - if (longitude.startsWith('-')) { - longitude = longitude.slice(1); // Remove the '-' character - latSign = -1; - } - const lngDegrees = parseInt(longitude.slice(0, 3)); - const lngMinutes = parseInt(longitude.slice(3, 5)); - const lngSeconds = parseInt(longitude.slice(5, 8)); - const lngNum = (lngDegrees + lngMinutes / 60 + lngSeconds / 3600) * latSign; - - return lngNum; -} - export default { Sectors: DisplayAirspaces, }; diff --git a/frontend/src/util/coordinate.util.ts b/frontend/src/util/coordinate.util.ts new file mode 100644 index 0000000..0a1ec0e --- /dev/null +++ b/frontend/src/util/coordinate.util.ts @@ -0,0 +1,71 @@ +import { LatLngExpression } from 'leaflet'; + +export function getAverageOfCoordinates(coordinates: string[][]): LatLngExpression { + let latSum = 0; + let lngSum = 0; + let count = 0; + + coordinates.forEach(([lat, lng]) => { + const latNum = convertLatitudeToNumber(lat); + const lngNum = convertLongitudeToNumber(lng); + + latSum += latNum; + lngSum += lngNum; + + count++; + }); + + const avgLat = latSum / count; + const avgLng = lngSum / count; + + // console.log(avgLat); + // console.log(avgLng); + + return [avgLat, avgLng]; +} + +export function convertCoordinatestoLatLngExpression(coordinates: string[][]): LatLngExpression[] { + return coordinates.map(([lat, lng]) => { + const latNum = convertLatitudeToNumber(lat); + const lngNum = convertLongitudeToNumber(lng); + + return [latNum, lngNum]; + }); +} + +export function convertLatitudeToNumber(latitude: string): number { + let latSign = 1; + + if (latitude.startsWith('-')) { + latitude = latitude.slice(1); // Remove the '-' character + latSign = -1; + } + const latDegrees = parseInt(latitude.slice(0, 2)); + const latMinutes = parseInt(latitude.slice(2, 4)); + const latSeconds = parseInt(latitude.slice(4, 9)); + const latNum = (latDegrees + latMinutes / 60 + latSeconds / 3600) * latSign; + + return latNum; +} + +export function convertLongitudeToNumber(longitude: string): number { + let latSign = 1; + + if (longitude.startsWith('-')) { + longitude = longitude.slice(1); // Remove the '-' character + latSign = -1; + } + const lngDegrees = parseInt(longitude.slice(0, 3)); + const lngMinutes = parseInt(longitude.slice(3, 5)); + const lngSeconds = parseInt(longitude.slice(5, 8)); + const lngNum = (lngDegrees + lngMinutes / 60 + lngSeconds / 3600) * latSign; + + return lngNum; +} + +export default { + getAverageOfCoordinates, + convertCoordinatestoLatLngExpression, + convertLatitudeToNumber, + convertLongitudeToNumber, +}; From 561d053706c91d5cb88e9a6b16bb636bee833353 Mon Sep 17 00:00:00 2001 From: LeoKle Date: Thu, 24 Aug 2023 22:07:20 +0200 Subject: [PATCH 12/21] minor fix --- frontend/src/components/Map.tsx | 2 +- frontend/src/components/Sectors.tsx | 4 ---- frontend/src/util/coordinate.util.ts | 7 ------- 3 files changed, 1 insertion(+), 12 deletions(-) diff --git a/frontend/src/components/Map.tsx b/frontend/src/components/Map.tsx index 0a5b2a4..057159a 100644 --- a/frontend/src/components/Map.tsx +++ b/frontend/src/components/Map.tsx @@ -92,7 +92,7 @@ export default function LoaViewerMap() { if (!sortedStations.includes(selectedSector as string) && sortedStations.length !== 0) { setSelectedSector(sortedStations[0]); } - }, [selectedFir, loading, airspaces]); + }, [selectedSector, selectedFir, loading, airspaces]); useEffect(() => { const filtered = airspaces.filter(airspace => airspace.owner[0] === selectedSector); diff --git a/frontend/src/components/Sectors.tsx b/frontend/src/components/Sectors.tsx index 026485b..fd269ff 100644 --- a/frontend/src/components/Sectors.tsx +++ b/frontend/src/components/Sectors.tsx @@ -57,7 +57,3 @@ function SectorLevelWidget(min: number, max: number) { html: renderToStaticMarkup(htmlContent), }); } - -export default { - Sectors: DisplayAirspaces, -}; diff --git a/frontend/src/util/coordinate.util.ts b/frontend/src/util/coordinate.util.ts index 0a1ec0e..718dd7c 100644 --- a/frontend/src/util/coordinate.util.ts +++ b/frontend/src/util/coordinate.util.ts @@ -62,10 +62,3 @@ export function convertLongitudeToNumber(longitude: string): number { return lngNum; } - -export default { - getAverageOfCoordinates, - convertCoordinatestoLatLngExpression, - convertLatitudeToNumber, - convertLongitudeToNumber, -}; From a9f7f47bd98ca45cdc11e41171c37558bb22ddca Mon Sep 17 00:00:00 2001 From: LeoKle Date: Fri, 25 Aug 2023 17:03:46 +0200 Subject: [PATCH 13/21] replace table by PrimeReact table --- frontend/src/components/MapConditionTable.tsx | 48 ++++++++++++ frontend/src/components/Markers.tsx | 75 +------------------ 2 files changed, 52 insertions(+), 71 deletions(-) create mode 100644 frontend/src/components/MapConditionTable.tsx diff --git a/frontend/src/components/MapConditionTable.tsx b/frontend/src/components/MapConditionTable.tsx new file mode 100644 index 0000000..7d9e46d --- /dev/null +++ b/frontend/src/components/MapConditionTable.tsx @@ -0,0 +1,48 @@ +import { WaypointRecord } from 'interfaces/waypointRecord.interface'; +import { Column } from 'primereact/column'; +import { DataTable } from 'primereact/datatable'; + +interface PropsTable { + conditions: WaypointRecord; +} + +export function MapConditionTable({ conditions }: PropsTable) { + const agreements = conditions.conditions; + + const values = agreements.map(condition => { + return { + id: `${condition._id}`, + adep_ades: `${condition.adep_ades === 'ADEP' ? '\u2191' : condition.adep_ades === 'ADES' ? '\u2193' : ''}${condition.aerodrome}`, + cop: `${condition.cop}`, + level: `${condition.feet ? 'A' : 'FL'} + ${condition.level} + ${condition.xc === null ? '' : condition.xc === 'A' ? '\u2193' : '\u2191'}`, + sc: `${condition.special_conditions}`, + from_sector: `${condition.from_sector}`, + to_sector: `${condition.to_sector}`, + from_fir: `${condition.from_fir}`, + to_fir: `${condition.to_fir}`, + }; + }); + + const hasSpecialConditions = agreements.some(condition => condition.special_conditions); + + const columns = [ + , + , + , + hasSpecialConditions && , + , + , + , + , + ]; + + return ( + <> + + {columns} + + + ); +} diff --git a/frontend/src/components/Markers.tsx b/frontend/src/components/Markers.tsx index 22eb236..2b94553 100644 --- a/frontend/src/components/Markers.tsx +++ b/frontend/src/components/Markers.tsx @@ -5,6 +5,7 @@ import { useEffect, useState } from 'react'; import { WaypointRecord } from 'interfaces/waypointRecord.interface'; import location from '../img/location.png'; import React from 'react'; +import { MapConditionTable } from './MapConditionTable'; interface ExtendedWaypointRecord extends WaypointRecord { drawn: boolean; @@ -98,7 +99,7 @@ function Markers({ conditions }: { conditions: WaypointRecord[] }) { handleMarkerClick(waypoint.name) }} zIndexOffset={condition.zIndex} /> @@ -125,79 +126,11 @@ function MarkerNameWidget(name: string) { }); } -function MarkerConditionTable(condition: WaypointRecord, zoom: number) { +function MarkerConditionTable(condition: WaypointRecord) { return new DivIcon({ className: 'custom-icon', - html: renderToStaticMarkup(), + html: renderToStaticMarkup(), }); } -interface PropsTable { - zoom: number; - conditions: WaypointRecord; -} - -function ConditionTableIcon({ zoom, conditions }: PropsTable) { - const tableStyle = { - fontSize: 1 / zoom + 10, - }; - - const agreements = conditions.conditions; - let hasSpecialConditions = false; - let columnSpan = 3; - - agreements.forEach(condition => { - if (condition.special_conditions) { - hasSpecialConditions = true; - columnSpan = 4; - } - }); - - return ( - - - - - - - - - - - {hasSpecialConditions ? : null} - - - - - - - - {agreements.map((condition, index) => ( - - - - - {hasSpecialConditions ? : null} - - - - - - ))} - -
- - Sector - - FIR -
ADCOPLevelSpecial ConditionsFromToFromTo
- {condition.adep_ades === 'ADEP' ? '\u2191' : condition.adep_ades === 'ADES' ? '\u2193' : ''} {condition.aerodrome} - {condition.cop} - {condition.feet ? 'A' : 'FL'} - {condition.level} - {condition.xc} - {condition.special_conditions}{condition.from_sector}{condition.to_sector}{condition.from_fir}{condition.to_fir}
- ); -} - export default Markers; From 281c51dee4e0020e5d5058939c4fd0a50dda70df Mon Sep 17 00:00:00 2001 From: LeoKle Date: Fri, 25 Aug 2023 18:01:36 +0200 Subject: [PATCH 14/21] add toolbar --- frontend/src/components/Map.tsx | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/frontend/src/components/Map.tsx b/frontend/src/components/Map.tsx index 057159a..7234a2d 100644 --- a/frontend/src/components/Map.tsx +++ b/frontend/src/components/Map.tsx @@ -14,6 +14,7 @@ import { DisplayAirspaces } from './Sectors'; import Airspace from '@shared/interfaces/sector.interface'; import sectorService from 'services/sector.service'; import { Button } from 'primereact/button'; +import { Toolbar } from 'primereact/toolbar'; export default function LoaViewerMap() { const [conditions, setConditions] = useState([]); @@ -102,19 +103,21 @@ export default function LoaViewerMap() { // Vertical limits of airspaces const [showVerticalLimits, setShowVerticalLimits] = useState(false); + const startContent = [ + setSearchInput(e.target.value)} />, + setSelectedSector(e.value)} />, + setSelectedFir(e.value)} />, + ]; + + const endContent = [ +