Working on drawer
This commit is contained in:
331
api/Cargo.lock
generated
331
api/Cargo.lock
generated
@@ -239,21 +239,6 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "actix-web-httpauth"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "456348ed9dcd72a13a1f4a660449fafdecee9ac8205552e286809eb5b0b29bd3"
|
||||
dependencies = [
|
||||
"actix-utils",
|
||||
"actix-web",
|
||||
"base64",
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
"log",
|
||||
"pin-project-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "addr2line"
|
||||
version = "0.24.2"
|
||||
@@ -371,17 +356,13 @@ dependencies = [
|
||||
"actix-cors",
|
||||
"actix-multipart",
|
||||
"actix-web",
|
||||
"actix-web-httpauth",
|
||||
"argon2",
|
||||
"byteorder",
|
||||
"chrono",
|
||||
"dotenv",
|
||||
"env_logger",
|
||||
"futures",
|
||||
"futures-util",
|
||||
"geo-types",
|
||||
"log",
|
||||
"moka",
|
||||
"rand 0.9.0",
|
||||
"rand_chacha 0.9.0",
|
||||
"redis",
|
||||
@@ -395,15 +376,6 @@ dependencies = [
|
||||
"uuid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "approx"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "arc-swap"
|
||||
version = "1.7.1"
|
||||
@@ -422,17 +394,6 @@ dependencies = [
|
||||
"password-hash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-lock"
|
||||
version = "3.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18"
|
||||
dependencies = [
|
||||
"event-listener",
|
||||
"event-listener-strategy",
|
||||
"pin-project-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-trait"
|
||||
version = "0.1.87"
|
||||
@@ -769,24 +730,6 @@ dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-channel"
|
||||
version = "0.5.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2"
|
||||
dependencies = [
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-epoch"
|
||||
version = "0.9.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
|
||||
dependencies = [
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-queue"
|
||||
version = "0.3.12"
|
||||
@@ -1031,16 +974,6 @@ dependencies = [
|
||||
"pin-project-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "event-listener-strategy"
|
||||
version = "0.5.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93"
|
||||
dependencies = [
|
||||
"event-listener",
|
||||
"pin-project-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fastrand"
|
||||
version = "2.3.0"
|
||||
@@ -1204,19 +1137,6 @@ dependencies = [
|
||||
"slab",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "generator"
|
||||
version = "0.8.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cc6bd114ceda131d3b1d665eba35788690ad37f5916457286b32ab6fd3c438dd"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"log",
|
||||
"rustversion",
|
||||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.14.7"
|
||||
@@ -1227,17 +1147,6 @@ dependencies = [
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "geo-types"
|
||||
version = "0.7.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3bd1157f0f936bf0cd68dec91e8f7c311afe60295574d62b70d4861a1bfdf2d9"
|
||||
dependencies = [
|
||||
"approx",
|
||||
"num-traits",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.15"
|
||||
@@ -1557,7 +1466,7 @@ dependencies = [
|
||||
"iana-time-zone-haiku",
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
"windows-core 0.52.0",
|
||||
"windows-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1873,28 +1782,6 @@ version = "0.4.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
|
||||
|
||||
[[package]]
|
||||
name = "loom"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "419e0dc8046cb947daa77eb95ae174acfbddb7673b4151f56d1eed8e93fbfaca"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"generator",
|
||||
"scoped-tls",
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "matchers"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558"
|
||||
dependencies = [
|
||||
"regex-automata 0.1.10",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "maybe-async"
|
||||
version = "0.2.10"
|
||||
@@ -1964,28 +1851,6 @@ dependencies = [
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "moka"
|
||||
version = "0.12.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a9321642ca94a4282428e6ea4af8cc2ca4eac48ac7a6a4ea8f33f76d0ce70926"
|
||||
dependencies = [
|
||||
"async-lock",
|
||||
"crossbeam-channel",
|
||||
"crossbeam-epoch",
|
||||
"crossbeam-utils",
|
||||
"event-listener",
|
||||
"futures-util",
|
||||
"loom",
|
||||
"parking_lot",
|
||||
"portable-atomic",
|
||||
"rustc_version",
|
||||
"smallvec",
|
||||
"tagptr",
|
||||
"thiserror 1.0.69",
|
||||
"uuid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "native-tls"
|
||||
version = "0.2.14"
|
||||
@@ -2003,16 +1868,6 @@ dependencies = [
|
||||
"tempfile",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nu-ansi-term"
|
||||
version = "0.46.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84"
|
||||
dependencies = [
|
||||
"overload",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-bigint"
|
||||
version = "0.4.6"
|
||||
@@ -2145,12 +2000,6 @@ dependencies = [
|
||||
"hashbrown 0.14.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "overload"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
|
||||
|
||||
[[package]]
|
||||
name = "parking"
|
||||
version = "2.2.1"
|
||||
@@ -2430,17 +2279,8 @@ checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-automata 0.4.9",
|
||||
"regex-syntax 0.8.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
|
||||
dependencies = [
|
||||
"regex-syntax 0.6.29",
|
||||
"regex-automata",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2451,7 +2291,7 @@ checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax 0.8.5",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2460,12 +2300,6 @@ version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "53a49587ad06b26609c52e423de037e7f57f20d53535d66e08c695f347df952a"
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.29"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.8.5"
|
||||
@@ -2712,12 +2546,6 @@ dependencies = [
|
||||
"parking_lot",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scoped-tls"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294"
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.2.0"
|
||||
@@ -2834,15 +2662,6 @@ dependencies = [
|
||||
"digest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sharded-slab"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "1.3.0"
|
||||
@@ -3208,12 +3027,6 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tagptr"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417"
|
||||
|
||||
[[package]]
|
||||
name = "tempfile"
|
||||
version = "3.18.0"
|
||||
@@ -3268,16 +3081,6 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thread_local"
|
||||
version = "1.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.3.39"
|
||||
@@ -3473,36 +3276,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"valuable",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-log"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3"
|
||||
dependencies = [
|
||||
"log",
|
||||
"once_cell",
|
||||
"tracing-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-subscriber"
|
||||
version = "0.3.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008"
|
||||
dependencies = [
|
||||
"matchers",
|
||||
"nu-ansi-term",
|
||||
"once_cell",
|
||||
"regex",
|
||||
"sharded-slab",
|
||||
"smallvec",
|
||||
"thread_local",
|
||||
"tracing",
|
||||
"tracing-core",
|
||||
"tracing-log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3601,12 +3374,6 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "valuable"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65"
|
||||
|
||||
[[package]]
|
||||
name = "vcpkg"
|
||||
version = "0.2.15"
|
||||
@@ -3740,38 +3507,6 @@ dependencies = [
|
||||
"wasite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows"
|
||||
version = "0.58.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6"
|
||||
dependencies = [
|
||||
"windows-core 0.58.0",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.52.0"
|
||||
@@ -3781,41 +3516,6 @@ dependencies = [
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.58.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99"
|
||||
dependencies = [
|
||||
"windows-implement",
|
||||
"windows-interface",
|
||||
"windows-result 0.2.0",
|
||||
"windows-strings 0.1.0",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-implement"
|
||||
version = "0.58.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-interface"
|
||||
version = "0.58.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-link"
|
||||
version = "0.1.0"
|
||||
@@ -3828,20 +3528,11 @@ version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4286ad90ddb45071efd1a66dfa43eb02dd0dfbae1545ad6cc3c51cf34d7e8ba3"
|
||||
dependencies = [
|
||||
"windows-result 0.3.1",
|
||||
"windows-strings 0.3.1",
|
||||
"windows-result",
|
||||
"windows-strings",
|
||||
"windows-targets 0.53.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-result"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e"
|
||||
dependencies = [
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-result"
|
||||
version = "0.3.1"
|
||||
@@ -3851,16 +3542,6 @@ dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-strings"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10"
|
||||
dependencies = [
|
||||
"windows-result 0.2.0",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-strings"
|
||||
version = "0.3.1"
|
||||
|
||||
@@ -12,7 +12,6 @@ license = "GPL-3.0-or-later"
|
||||
[dependencies]
|
||||
actix-web = "4.10.2"
|
||||
actix-cors = "0.7.1"
|
||||
actix-web-httpauth = "0.8.2"
|
||||
actix-multipart = "0.7.2"
|
||||
chrono = { version = "0.4.40", features = ["serde"] }
|
||||
dotenv = "0.15.0"
|
||||
@@ -31,7 +30,4 @@ futures-util = "0.3.31"
|
||||
rust-s3 = "0.35.1"
|
||||
rand = "0.9.0"
|
||||
rand_chacha = "0.9.0"
|
||||
geo-types = "0.7.15"
|
||||
byteorder = "1.5.0"
|
||||
futures = "0.3.31"
|
||||
moka = { version = "0.12.10", features = ["future"] }
|
||||
|
||||
@@ -27,7 +27,7 @@ impl MetarCheck {
|
||||
status,
|
||||
updated_at: Utc::now(),
|
||||
last_metar: None,
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -993,10 +993,7 @@ impl Metar {
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn find_all_distinct(
|
||||
client: &Client,
|
||||
icao_list: &Vec<String>
|
||||
) -> ApiResult<Vec<Self>> {
|
||||
pub async fn find_all_distinct(client: &Client, icao_list: &Vec<String>) -> ApiResult<Vec<Self>> {
|
||||
if icao_list.is_empty() {
|
||||
return Ok(Vec::new());
|
||||
}
|
||||
|
||||
25
ui/package-lock.json
generated
25
ui/package-lock.json
generated
@@ -17,6 +17,7 @@
|
||||
"d3": "^7.9.0",
|
||||
"js-cookie": "^3.0.5",
|
||||
"leaflet": "^1.9.4",
|
||||
"lodash.debounce": "^4.0.8",
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0",
|
||||
"react-leaflet": "^5.0.0",
|
||||
@@ -27,6 +28,7 @@
|
||||
"@types/d3": "^7.4.3",
|
||||
"@types/js-cookie": "^3.0.6",
|
||||
"@types/leaflet": "^1.9.16",
|
||||
"@types/lodash.debounce": "^4.0.9",
|
||||
"@types/node": "^22.13.10",
|
||||
"@types/react": "^19.0.10",
|
||||
"@types/react-dom": "^19.0.4",
|
||||
@@ -1881,6 +1883,23 @@
|
||||
"@types/geojson": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/lodash": {
|
||||
"version": "4.17.16",
|
||||
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.16.tgz",
|
||||
"integrity": "sha512-HX7Em5NYQAXKW+1T+FiuG27NGwzJfCX3s1GjOa7ujxZa52kjJLOr4FUxT+giF6Tgxv1e+/czV/iTtBw27WTU9g==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/lodash.debounce": {
|
||||
"version": "4.0.9",
|
||||
"resolved": "https://registry.npmjs.org/@types/lodash.debounce/-/lodash.debounce-4.0.9.tgz",
|
||||
"integrity": "sha512-Ma5JcgTREwpLRwMM+XwBR7DaWe96nC38uCBDFKZWbNKD+osjVzdpnUSwBcqCptrp16sSOLBAUb50Car5I0TCsQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/lodash": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "22.13.10",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.10.tgz",
|
||||
@@ -3741,6 +3760,12 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/lodash.debounce": {
|
||||
"version": "4.0.8",
|
||||
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
|
||||
"integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lodash.merge": {
|
||||
"version": "4.6.2",
|
||||
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
"d3": "^7.9.0",
|
||||
"js-cookie": "^3.0.5",
|
||||
"leaflet": "^1.9.4",
|
||||
"lodash.debounce": "^4.0.8",
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0",
|
||||
"react-leaflet": "^5.0.0",
|
||||
@@ -30,6 +31,7 @@
|
||||
"@types/d3": "^7.4.3",
|
||||
"@types/js-cookie": "^3.0.6",
|
||||
"@types/leaflet": "^1.9.16",
|
||||
"@types/lodash.debounce": "^4.0.9",
|
||||
"@types/node": "^22.13.10",
|
||||
"@types/react": "^19.0.10",
|
||||
"@types/react-dom": "^19.0.4",
|
||||
|
||||
@@ -10,7 +10,7 @@ import { Header } from '@components/Header';
|
||||
import AirportLayer from '@components/AirportLayer.tsx';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { Airport } from '@lib/airport.types.ts';
|
||||
import AirportDrawer from '@components/AirportDrawer.tsx';
|
||||
import Index from '@components/AirportDrawer';
|
||||
import { getWeatherMapUrl } from '@lib/rainViewer.ts';
|
||||
import Cookies from 'js-cookie';
|
||||
// import { createRoot } from 'react-dom/client';
|
||||
@@ -150,7 +150,7 @@ function App() {
|
||||
<div className='App'>
|
||||
<Header />
|
||||
<div className='map-wrapper'>
|
||||
<AirportDrawer airport={airport} setAirport={setAirport} />
|
||||
<Index airport={airport} setAirport={setAirport} />
|
||||
<MapContainer
|
||||
className='leaflet-container'
|
||||
attributionControl={false}
|
||||
|
||||
3
ui/src/components/AirportDrawer/AirportDrawer.module.css
Normal file
3
ui/src/components/AirportDrawer/AirportDrawer.module.css
Normal file
@@ -0,0 +1,3 @@
|
||||
.drawer {
|
||||
background: #32495f;
|
||||
}
|
||||
@@ -1,11 +1,12 @@
|
||||
import { Badge, Box, Divider, Drawer, Group, Tabs, TabsList, Text, Tooltip } from '@mantine/core';
|
||||
import { Badge, Box, Divider, Drawer, Group, Tabs, TabsList, Text, Tooltip, UnstyledButton } from '@mantine/core';
|
||||
import { Airport, AirportCategory } from '@lib/airport.types.ts';
|
||||
import { getMarkerColor, Metar } from '@lib/metar.types.ts';
|
||||
import { forwardRef, ReactNode, useEffect, useState } from 'react';
|
||||
import { CSSProperties, forwardRef, ReactNode, useEffect, useState } from 'react';
|
||||
import { getMetars } from '@lib/metar.ts';
|
||||
import { useMediaQuery } from '@mantine/hooks';
|
||||
import { IconViewfinder } from '@tabler/icons-react';
|
||||
|
||||
export default function AirportDrawer({
|
||||
export default function Index({
|
||||
airport,
|
||||
setAirport
|
||||
}: {
|
||||
@@ -48,7 +49,7 @@ export default function AirportDrawer({
|
||||
onClose={() => setAirport(null)}
|
||||
withinPortal
|
||||
zIndex={1000}
|
||||
styles={{ root: { padding: 0, margin: 0, width: 0, height: 0 } }}
|
||||
styles={{ root: { padding: 0, margin: 0, width: 0, height: 0, backgroundColor: 'red' } }}
|
||||
padding='md'
|
||||
size={isMobile ? '100%' : 'md'}
|
||||
position='left'
|
||||
@@ -68,7 +69,7 @@ export default function AirportDrawer({
|
||||
justify='space-between'
|
||||
mb='md'
|
||||
style={{
|
||||
backgroundColor: '#272f38',
|
||||
backgroundColor: '#32495f',
|
||||
borderTop: '1px solid #1a242f',
|
||||
borderBottom: '1px solid #1a242f',
|
||||
padding: '10px'
|
||||
@@ -102,21 +103,22 @@ export default function AirportDrawer({
|
||||
);
|
||||
}
|
||||
|
||||
function AirportInfoSlot({ title, value, units }: { title: string; value: string | number; units?: string }) {
|
||||
function AirportInfoSlot({ title, style, children }: { title?: string; style?: CSSProperties; children?: ReactNode }) {
|
||||
return (
|
||||
<div>
|
||||
<div style={{ ...style }}>
|
||||
{title && (
|
||||
<Text size='xs' color='dimmed'>
|
||||
{title}
|
||||
</Text>
|
||||
<Text fw={500} size='sm'>
|
||||
{value}
|
||||
{units}
|
||||
</Text>
|
||||
)}
|
||||
<Box fw={500} size='sm'>
|
||||
{children}
|
||||
</Box>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function AirportInfoRow({ children }: { children: ReactNode }) {
|
||||
function AirportInfoRow({ style, children }: { style?: CSSProperties; children: ReactNode }) {
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
@@ -124,7 +126,8 @@ function AirportInfoRow({ children }: { children: ReactNode }) {
|
||||
justifyContent: 'space-between',
|
||||
alignContent: 'center',
|
||||
padding: 'var(--mantine-spacing-sm) var(--mantine-spacing-lg)',
|
||||
borderTop: '1px solid light-dark(var(--mantine-color-gray-2), var(--mantine-color-dark-5))'
|
||||
borderTop: '1px solid light-dark(var(--mantine-color-gray-2), var(--mantine-color-dark-5))',
|
||||
...style
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
@@ -136,16 +139,21 @@ function AirportInfo({ airport }: { airport: Airport }) {
|
||||
return (
|
||||
<div>
|
||||
<AirportInfoRow>
|
||||
<AirportInfoSlot title={'ICAO'} value={airport.icao} />
|
||||
<AirportInfoSlot title={'IATA'} value={airport.iata} />
|
||||
<AirportInfoSlot title={'LOCAL'} value={airport.local} />
|
||||
<AirportInfoSlot title={'Category'} value={airportCategoryToText(airport.category)} />
|
||||
<AirportInfoSlot title={'ICAO'} children={airport.icao} />
|
||||
<AirportInfoSlot title={'IATA'} children={airport.iata} />
|
||||
<AirportInfoSlot title={'LOCAL'} children={airport.local} />
|
||||
<AirportInfoSlot title={'Category'} children={airportCategoryToText(airport.category)} />
|
||||
</AirportInfoRow>
|
||||
<AirportInfoRow>
|
||||
<AirportInfoSlot title={'Latitude'} value={airport.latitude} units={'°'} />
|
||||
<AirportInfoSlot title={'Longitude'} value={airport.longitude} units={'°'} />
|
||||
<AirportInfoSlot title={'Elevation'} value={airport.elevation_ft} units={' ft'} />
|
||||
Zoom To
|
||||
<AirportInfoRow style={{ justifyContent: 'flex-start' }}>
|
||||
<AirportInfoSlot title={'Location'}>
|
||||
{airport.latitude}°, {airport.longitude}°
|
||||
</AirportInfoSlot>
|
||||
<AirportInfoSlot title={'Elevation'} style={{ paddingLeft: '1rem' }} children={`${airport.elevation_ft} ft`} />
|
||||
<AirportInfoSlot style={{ marginLeft: 'auto', paddingLeft: '1rem', paddingTop: '0.5rem' }}>
|
||||
<UnstyledButton>
|
||||
<IconViewfinder />
|
||||
</UnstyledButton>
|
||||
</AirportInfoSlot>
|
||||
</AirportInfoRow>
|
||||
<Divider />
|
||||
</div>
|
||||
@@ -1,15 +1,12 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { Airport, AirportCategory } from '@lib/airport.types.ts';
|
||||
import { useMapEvents } from 'react-leaflet';
|
||||
import debounce from 'lodash.debounce';
|
||||
import { getAirports } from '@lib/airport.ts';
|
||||
import AirportMarker from '@components/AirportMarker.tsx';
|
||||
import { LeafletEvent } from 'leaflet';
|
||||
import { LayerInfo } from '@/App.tsx';
|
||||
|
||||
interface Bounds {
|
||||
northEast: { lat: number; lon: number };
|
||||
southWest: { lat: number; lon: number };
|
||||
}
|
||||
const EXPANSION_FACTOR = 0.5;
|
||||
|
||||
export default function AirportLayer({
|
||||
setAirport,
|
||||
@@ -21,76 +18,48 @@ export default function AirportLayer({
|
||||
selectedLayer: LayerInfo;
|
||||
}) {
|
||||
const [airports, setAirports] = useState<Airport[]>([]);
|
||||
const lastBoundsRef = useRef<{ ne: any; sw: any } | null>(null);
|
||||
|
||||
function loadAirports(event: LeafletEvent) {
|
||||
const map = event.target;
|
||||
const bounds = map.getBounds();
|
||||
const debouncedLoad = useRef(
|
||||
debounce(async (map: any) => {
|
||||
const b = map.getBounds();
|
||||
const north = b.getNorth(),
|
||||
south = b.getSouth();
|
||||
const east = b.getEast(),
|
||||
west = b.getWest();
|
||||
const latDelta = (north - south) * EXPANSION_FACTOR;
|
||||
const lonDelta = (east - west) * EXPANSION_FACTOR;
|
||||
|
||||
const boundsParam: Bounds = {
|
||||
northEast: {
|
||||
lat: bounds.getNorth(),
|
||||
lon: bounds.getEast()
|
||||
},
|
||||
southWest: {
|
||||
lat: bounds.getSouth(),
|
||||
lon: bounds.getWest()
|
||||
}
|
||||
};
|
||||
// expanded bbox
|
||||
const ne = { lat: north + latDelta, lon: east + lonDelta };
|
||||
const sw = { lat: south - latDelta, lon: west - lonDelta };
|
||||
lastBoundsRef.current = { ne, sw };
|
||||
|
||||
getAirports({
|
||||
bounds: boundsParam,
|
||||
try {
|
||||
const resp = await getAirports({
|
||||
bounds: { northEast: ne, southWest: sw },
|
||||
metars: true,
|
||||
categories: [AirportCategory.HELIPORT, AirportCategory.SMALL, AirportCategory.MEDIUM, AirportCategory.LARGE]
|
||||
})
|
||||
.then((response) => {
|
||||
setAirports(response.data);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Error fetching airports:', error);
|
||||
setAirports([]);
|
||||
});
|
||||
setAirports(resp.data);
|
||||
} catch (err) {
|
||||
console.error('fetch error', err);
|
||||
setAirports([]);
|
||||
}
|
||||
}, 300)
|
||||
).current;
|
||||
|
||||
const map = useMapEvents({
|
||||
moveend: loadAirports
|
||||
move: () => debouncedLoad(map)
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (map) {
|
||||
loadAirports({ target: map } as LeafletEvent);
|
||||
}
|
||||
if (map) debouncedLoad(map);
|
||||
return () => {
|
||||
debouncedLoad.cancel();
|
||||
};
|
||||
}, [map]);
|
||||
|
||||
// const categoryOrder: { [key in AirportCategory]?: number } = {
|
||||
// [AirportCategory.LARGE]: 3,
|
||||
// [AirportCategory.MEDIUM]: 2,
|
||||
// [AirportCategory.SMALL]: 1,
|
||||
// [AirportCategory.HELIPORT]: 0
|
||||
// };
|
||||
|
||||
// const sortedAirports = airports.slice().sort((a, b) => {
|
||||
// // Compare by airport category first.
|
||||
// const categoryA = categoryOrder[a.category] ?? 4;
|
||||
// const categoryB = categoryOrder[b.category] ?? 4;
|
||||
// if (categoryA !== categoryB) {
|
||||
// return categoryA - categoryB;
|
||||
// }
|
||||
//
|
||||
// // Then compare by flight category if available.
|
||||
// // Assuming that latest_metar.flight_category is a string and "UNKN" needs to come last.
|
||||
// const fcA = a.latest_metar?.flight_category ?? 'UNKN';
|
||||
// const fcB = b.latest_metar?.flight_category ?? 'UNKN';
|
||||
//
|
||||
// if (fcA === 'UNKN' && fcB !== 'UNKN') return 1;
|
||||
// if (fcB === 'UNKN' && fcA !== 'UNKN') return -1;
|
||||
//
|
||||
// // If both flight categories are not "UNKN", do a simple alphabetical comparison.
|
||||
// // (You may wish to customize this logic based on the actual flight category values.)
|
||||
// if (fcA < fcB) return -1;
|
||||
// if (fcA > fcB) return 1;
|
||||
// return 0;
|
||||
// });
|
||||
|
||||
return (
|
||||
<>
|
||||
{airports.map((airport, index) => (
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
.header {
|
||||
height: 56px;
|
||||
padding: 0 16px 0 16px;
|
||||
background-color: var(--mantine-color-body);
|
||||
/*background-color: var(--mantine-color-body);*/
|
||||
background: #32495f;
|
||||
border-bottom: 1px solid light-dark(var(--mantine-color-gray-3), var(--mantine-color-dark-4));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user