feat: Enhance station label generation with detailed date ranges and resolution, and refine date range defaults and validation based on data resolution.
Browse files
server.R
CHANGED
|
@@ -1,23 +1,73 @@
|
|
| 1 |
# server.R for DWD App
|
| 2 |
|
| 3 |
# Helper function for label generation
|
| 4 |
-
generate_station_label <- function(name, id, state, start_date, end_date, detailed_summary
|
|
|
|
| 5 |
tryCatch(
|
| 6 |
{
|
| 7 |
-
|
| 8 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 9 |
|
| 10 |
paste0(
|
| 11 |
"<div style='font-size:18px; max-width: 400px;'>",
|
| 12 |
"<b>", htmltools::htmlEscape(name), "</b> (", id, ")<br>",
|
| 13 |
"<span style='font-size:80%;'>State: ", htmltools::htmlEscape(state), "</span><br>",
|
| 14 |
"<span style='font-size:80%; color:#555;'>",
|
| 15 |
-
"Station Active: ",
|
|
|
|
|
|
|
|
|
|
| 16 |
"</span><br>",
|
| 17 |
-
"<div style='font-size:80%; color:#333; font-weight:bold; margin-top:5px;'>
|
|
|
|
| 18 |
"<div style='font-size:75%; color:#333; line-height: 1.1;'>• ",
|
| 19 |
paste0(
|
| 20 |
-
gsub(", ", "<br>• ", htmltools::htmlEscape(
|
| 21 |
"<br><small><i>Note: 'Present' indicates ongoing monitoring;<br>",
|
| 22 |
"some parameters may have<br>",
|
| 23 |
"upload delays.</i></small>"
|
|
@@ -46,20 +96,25 @@ server <- function(input, output, session) {
|
|
| 46 |
{
|
| 47 |
session$sendCustomMessage("freezeUI", list(text = "Switching resolution..."))
|
| 48 |
|
| 49 |
-
# Update date range
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
|
|
|
|
|
|
|
| 55 |
new_start <- new_end - (365 * 6)
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
message("Note: Could not update date range for monthly: ", e$message)
|
| 60 |
}
|
| 61 |
-
|
| 62 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 63 |
},
|
| 64 |
priority = 1000,
|
| 65 |
ignoreInit = TRUE
|
|
@@ -191,9 +246,13 @@ server <- function(input, output, session) {
|
|
| 191 |
|
| 192 |
# Highlight & Zoom
|
| 193 |
# Generate Label
|
|
|
|
|
|
|
|
|
|
| 194 |
lbl <- generate_station_label(
|
| 195 |
s_meta$name[1], s_meta$id[1], s_meta$state[1],
|
| 196 |
-
s_meta$start_date[1], s_meta$end_date[1], s_meta$detailed_summary[1]
|
|
|
|
| 197 |
)
|
| 198 |
|
| 199 |
highlight_selected_station(leafletProxy("map"), lng_val, lat_val, lbl)
|
|
@@ -268,15 +327,24 @@ server <- function(input, output, session) {
|
|
| 268 |
# Update Markers
|
| 269 |
observe({
|
| 270 |
df <- filtered_stations()
|
| 271 |
-
req(df)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 272 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 273 |
|
| 274 |
# Pre-process label with HTML using Helper
|
| 275 |
-
df <-
|
| 276 |
-
|
| 277 |
-
|
| 278 |
-
|
| 279 |
-
)
|
|
|
|
| 280 |
)
|
| 281 |
|
| 282 |
proxy <- leafletProxy("map", data = df) %>%
|
|
@@ -323,9 +391,13 @@ server <- function(input, output, session) {
|
|
| 323 |
s_meta <- all_stations() %>% filter(id == id_val)
|
| 324 |
|
| 325 |
lbl <- if (nrow(s_meta) > 0) {
|
|
|
|
|
|
|
|
|
|
| 326 |
generate_station_label(
|
| 327 |
s_meta$name[1], s_meta$id[1], s_meta$state[1],
|
| 328 |
-
s_meta$start_date[1], s_meta$end_date[1], s_meta$detailed_summary[1]
|
|
|
|
| 329 |
)
|
| 330 |
} else {
|
| 331 |
paste0("<b>", id_val, "</b>")
|
|
@@ -362,9 +434,12 @@ server <- function(input, output, session) {
|
|
| 362 |
# Calculate current diff
|
| 363 |
diff <- as.numeric(difftime(d_end, d_start, units = "days"))
|
| 364 |
|
| 365 |
-
# Max window depends on resolution:
|
| 366 |
-
|
| 367 |
-
|
|
|
|
|
|
|
|
|
|
| 368 |
min_days <- 28
|
| 369 |
|
| 370 |
if (diff > max_days || diff < min_days) {
|
|
@@ -1042,9 +1117,13 @@ server <- function(input, output, session) {
|
|
| 1042 |
lng_val <- s$longitude[1]
|
| 1043 |
# Highlight & Zoom
|
| 1044 |
# Generate Label
|
|
|
|
|
|
|
|
|
|
| 1045 |
lbl <- generate_station_label(
|
| 1046 |
s$name[1], s$id[1], s$state[1],
|
| 1047 |
-
s$start_date[1], s$end_date[1], s$detailed_summary[1]
|
|
|
|
| 1048 |
)
|
| 1049 |
|
| 1050 |
leafletProxy("map") %>%
|
|
|
|
| 1 |
# server.R for DWD App
|
| 2 |
|
| 3 |
# Helper function for label generation
|
| 4 |
+
generate_station_label <- function(name, id, state, start_date, end_date, detailed_summary,
|
| 5 |
+
overall_start = NULL, overall_end = NULL, resolution = NULL) {
|
| 6 |
tryCatch(
|
| 7 |
{
|
| 8 |
+
format_range <- function(start_val, end_val) {
|
| 9 |
+
format_val <- function(value, is_end = FALSE) {
|
| 10 |
+
if (is.null(value) || is.na(value) || value == "") {
|
| 11 |
+
return("Unknown")
|
| 12 |
+
}
|
| 13 |
+
|
| 14 |
+
if (inherits(value, "Date")) {
|
| 15 |
+
return(format(value, "%Y-%m-%d"))
|
| 16 |
+
}
|
| 17 |
+
|
| 18 |
+
value <- as.character(value)
|
| 19 |
+
if (value == "99999999") {
|
| 20 |
+
return(if (is_end) "Present" else "Unknown")
|
| 21 |
+
}
|
| 22 |
+
if (value == "00000000") {
|
| 23 |
+
return("Unknown")
|
| 24 |
+
}
|
| 25 |
+
|
| 26 |
+
if (grepl("^\\d{4}-\\d{2}-\\d{2}$", value)) {
|
| 27 |
+
d <- as.Date(value)
|
| 28 |
+
} else {
|
| 29 |
+
d <- as.Date(value, format = "%Y%m%d")
|
| 30 |
+
}
|
| 31 |
+
if (is.na(d)) {
|
| 32 |
+
return("Unknown")
|
| 33 |
+
}
|
| 34 |
+
format(d, "%Y-%m-%d")
|
| 35 |
+
}
|
| 36 |
+
|
| 37 |
+
paste0(format_val(start_val, FALSE), " to ", format_val(end_val, TRUE))
|
| 38 |
+
}
|
| 39 |
+
|
| 40 |
+
res_label <- if (is.null(resolution) || is.na(resolution) || resolution == "") {
|
| 41 |
+
"Data"
|
| 42 |
+
} else {
|
| 43 |
+
paste0(toupper(substr(resolution, 1, 1)), substr(resolution, 2, nchar(resolution)))
|
| 44 |
+
}
|
| 45 |
+
|
| 46 |
+
station_range <- format_range(start_date, end_date)
|
| 47 |
+
coverage_start <- if (is.null(overall_start)) start_date else overall_start
|
| 48 |
+
coverage_end <- if (is.null(overall_end)) end_date else overall_end
|
| 49 |
+
coverage_range <- format_range(coverage_start, coverage_end)
|
| 50 |
+
summary_text <- if (is.null(detailed_summary) || is.na(detailed_summary) || detailed_summary == "") {
|
| 51 |
+
"No Data"
|
| 52 |
+
} else {
|
| 53 |
+
detailed_summary
|
| 54 |
+
}
|
| 55 |
|
| 56 |
paste0(
|
| 57 |
"<div style='font-size:18px; max-width: 400px;'>",
|
| 58 |
"<b>", htmltools::htmlEscape(name), "</b> (", id, ")<br>",
|
| 59 |
"<span style='font-size:80%;'>State: ", htmltools::htmlEscape(state), "</span><br>",
|
| 60 |
"<span style='font-size:80%; color:#555;'>",
|
| 61 |
+
"Station Active: ", station_range,
|
| 62 |
+
"</span><br>",
|
| 63 |
+
"<span style='font-size:80%; color:#555;'>",
|
| 64 |
+
res_label, " Coverage: ", coverage_range,
|
| 65 |
"</span><br>",
|
| 66 |
+
"<div style='font-size:80%; color:#333; font-weight:bold; margin-top:5px;'>",
|
| 67 |
+
"Data Availability (", res_label, "):</div>",
|
| 68 |
"<div style='font-size:75%; color:#333; line-height: 1.1;'>• ",
|
| 69 |
paste0(
|
| 70 |
+
gsub(", ", "<br>• ", htmltools::htmlEscape(summary_text)),
|
| 71 |
"<br><small><i>Note: 'Present' indicates ongoing monitoring;<br>",
|
| 72 |
"some parameters may have<br>",
|
| 73 |
"upload delays.</i></small>"
|
|
|
|
| 96 |
{
|
| 97 |
session$sendCustomMessage("freezeUI", list(text = "Switching resolution..."))
|
| 98 |
|
| 99 |
+
# Update date range based on resolution
|
| 100 |
+
res <- tolower(input$data_resolution)
|
| 101 |
+
|
| 102 |
+
tryCatch(
|
| 103 |
+
{
|
| 104 |
+
new_end <- Sys.Date()
|
| 105 |
+
if (res %in% c("monthly", "daily")) {
|
| 106 |
+
# For Monthly/Daily: default to last 6 years
|
| 107 |
new_start <- new_end - (365 * 6)
|
| 108 |
+
} else {
|
| 109 |
+
# For Hourly: default to last 1 year (366 days)
|
| 110 |
+
new_start <- new_end - 366
|
|
|
|
| 111 |
}
|
| 112 |
+
updateDateRangeInput(session, "date_range", start = new_start, end = new_end)
|
| 113 |
+
},
|
| 114 |
+
error = function(e) {
|
| 115 |
+
message("Note: Could not update date range: ", e$message)
|
| 116 |
+
}
|
| 117 |
+
)
|
| 118 |
},
|
| 119 |
priority = 1000,
|
| 120 |
ignoreInit = TRUE
|
|
|
|
| 246 |
|
| 247 |
# Highlight & Zoom
|
| 248 |
# Generate Label
|
| 249 |
+
res <- if (is.null(input$data_resolution)) NULL else tolower(input$data_resolution)
|
| 250 |
+
overall_start <- if ("station_overall_start" %in% names(s_meta)) s_meta$station_overall_start[1] else s_meta$start_date[1]
|
| 251 |
+
overall_end <- if ("station_overall_end" %in% names(s_meta)) s_meta$station_overall_end[1] else s_meta$end_date[1]
|
| 252 |
lbl <- generate_station_label(
|
| 253 |
s_meta$name[1], s_meta$id[1], s_meta$state[1],
|
| 254 |
+
s_meta$start_date[1], s_meta$end_date[1], s_meta$detailed_summary[1],
|
| 255 |
+
overall_start, overall_end, res
|
| 256 |
)
|
| 257 |
|
| 258 |
highlight_selected_station(leafletProxy("map"), lng_val, lat_val, lbl)
|
|
|
|
| 327 |
# Update Markers
|
| 328 |
observe({
|
| 329 |
df <- filtered_stations()
|
| 330 |
+
req(df, input$data_resolution, input$main_nav)
|
| 331 |
+
|
| 332 |
+
if (input$main_nav != "Map View") {
|
| 333 |
+
return()
|
| 334 |
+
}
|
| 335 |
|
| 336 |
+
res <- tolower(input$data_resolution)
|
| 337 |
+
n_rows <- nrow(df)
|
| 338 |
+
coverage_start <- if ("station_overall_start" %in% names(df)) df$station_overall_start else df$start_date
|
| 339 |
+
coverage_end <- if ("station_overall_end" %in% names(df)) df$station_overall_end else df$end_date
|
| 340 |
|
| 341 |
# Pre-process label with HTML using Helper
|
| 342 |
+
df$label_html <- purrr::pmap_chr(
|
| 343 |
+
list(
|
| 344 |
+
df$name, df$id, df$state, df$start_date, df$end_date,
|
| 345 |
+
df$detailed_summary, coverage_start, coverage_end, rep(res, n_rows)
|
| 346 |
+
),
|
| 347 |
+
generate_station_label
|
| 348 |
)
|
| 349 |
|
| 350 |
proxy <- leafletProxy("map", data = df) %>%
|
|
|
|
| 391 |
s_meta <- all_stations() %>% filter(id == id_val)
|
| 392 |
|
| 393 |
lbl <- if (nrow(s_meta) > 0) {
|
| 394 |
+
res <- if (is.null(input$data_resolution)) NULL else tolower(input$data_resolution)
|
| 395 |
+
overall_start <- if ("station_overall_start" %in% names(s_meta)) s_meta$station_overall_start[1] else s_meta$start_date[1]
|
| 396 |
+
overall_end <- if ("station_overall_end" %in% names(s_meta)) s_meta$station_overall_end[1] else s_meta$end_date[1]
|
| 397 |
generate_station_label(
|
| 398 |
s_meta$name[1], s_meta$id[1], s_meta$state[1],
|
| 399 |
+
s_meta$start_date[1], s_meta$end_date[1], s_meta$detailed_summary[1],
|
| 400 |
+
overall_start, overall_end, res
|
| 401 |
)
|
| 402 |
} else {
|
| 403 |
paste0("<b>", id_val, "</b>")
|
|
|
|
| 434 |
# Calculate current diff
|
| 435 |
diff <- as.numeric(difftime(d_end, d_start, units = "days"))
|
| 436 |
|
| 437 |
+
# Max window depends on resolution:
|
| 438 |
+
# Monthly/Daily: ~10 years (3652 days) to allow 6-year views
|
| 439 |
+
# Hourly: 1 year (366 days)
|
| 440 |
+
res <- tolower(input$data_resolution)
|
| 441 |
+
is_extended <- res %in% c("monthly", "daily")
|
| 442 |
+
max_days <- if (is_extended) 3652 else 366
|
| 443 |
min_days <- 28
|
| 444 |
|
| 445 |
if (diff > max_days || diff < min_days) {
|
|
|
|
| 1117 |
lng_val <- s$longitude[1]
|
| 1118 |
# Highlight & Zoom
|
| 1119 |
# Generate Label
|
| 1120 |
+
res <- if (is.null(input$data_resolution)) NULL else tolower(input$data_resolution)
|
| 1121 |
+
overall_start <- if ("station_overall_start" %in% names(s)) s$station_overall_start[1] else s$start_date[1]
|
| 1122 |
+
overall_end <- if ("station_overall_end" %in% names(s)) s$station_overall_end[1] else s$end_date[1]
|
| 1123 |
lbl <- generate_station_label(
|
| 1124 |
s$name[1], s$id[1], s$state[1],
|
| 1125 |
+
s$start_date[1], s$end_date[1], s$detailed_summary[1],
|
| 1126 |
+
overall_start, overall_end, res
|
| 1127 |
)
|
| 1128 |
|
| 1129 |
leafletProxy("map") %>%
|