jma / ui.R
alexdum's picture
feat: implement OpenFreeMap vector styles and a hybrid Sentinel-2 basemap with dynamic label visibility, replacing previous basemap options.
07004f3
# ui.R
ui <- page_navbar(
id = "main_nav",
header = tagList(
shinyjs::useShinyjs(),
tags$head(
tags$meta(charset = "utf-8"),
tags$meta(`http-equiv` = "X-UA-Compatible", content = "IE=edge"),
tags$meta(name = "viewport", content = "width=device-width, initial-scale=1"),
# Include external CSS and JS from www/ folder
tags$link(rel = "stylesheet", type = "text/css", href = "styles.css"),
tags$script(src = "app.js"),
# Layer Control Interactions
tags$script(HTML("
$(document).ready(function() {
// Layer Control Interactions
var $layerControl = $('.map-layer-control');
$layerControl.on('mouseenter', function() {
$(this).addClass('expanded');
});
$layerControl.on('mouseleave', function() {
$(this).removeClass('expanded');
});
// Auto-close when a radio button (basemap) is selected
$layerControl.on('change', 'input[type=\\'radio\\']', function() {
$layerControl.removeClass('expanded');
});
});
"))
),
# Frozen overlay div
div(
class = "frozen-overlay",
div(
class = "frozen-overlay-content",
tags$button(class = "frozen-overlay-close", "×", title = "Cancel loading"),
p(class = "frozen-overlay-station", ""),
div(class = "spinner-border text-primary", role = "status"),
p(class = "frozen-overlay-message", "Loading data...")
)
)
),
title = "JMA Explorer",
theme = bs_theme(version = 5, bootswatch = "cosmo"),
sidebar = sidebar(
title = "Filters",
# Data Resolution
radioButtons("data_resolution", "Time Resolution", choices = c("10 Minutes", "Hourly", "Daily", "Monthly"), selected = "Daily", inline = TRUE),
# Station Search
selectizeInput("station_selector", "Find Station", choices = NULL, multiple = FALSE, options = list(placeholder = "Type to search...")),
div(
style = "display: flex; align-items: center; gap: 8px;",
tags$label("Select Date Range"),
tooltip(
bsicons::bs_icon("info-circle", size = "1em"),
"Filter stations that have data overlapping with this date range."
)
),
dateRangeInput("date_range",
label = NULL,
start = Sys.Date() - 366,
end = Sys.Date(),
min = "1872-01-01",
max = Sys.Date(),
format = "yyyy-mm-dd",
separator = " to "
),
hr(),
strong(textOutput("visible_count", inline = TRUE)),
hr(),
p("Data source: JMA (Japan Meteorological Agency)"),
p(style = "font-size: 0.8em; color: #666;", "Includes: 10-min, Hourly, Daily, and Monthly data"),
hr(),
div(
style = "display: flex; align-items: flex-start; gap: 8px;",
tags$small("Tip: Click map points to view detailed weather plots.")
)
),
nav_panel(
title = "Map View",
div(
class = "outer",
maplibreOutput("map", height = "100%", width = "100%"),
# Layer Control Panel (Collapsible)
absolutePanel(
top = 130, left = 10,
class = "map-layer-control",
style = "z-index: 1000;",
div(class = "control-icon", icon("layer-group")),
div(
class = "control-content",
radioButtons(
inputId = "basemap",
label = "Basemap",
choices = c(
"OpenFreeMap Positron" = "ofm_positron",
"OpenFreeMap Bright" = "ofm_bright",
"Satellite (Sentinel-2)" = "sentinel"
),
selected = "ofm_positron"
),
hr(style = "margin: 8px 0;"),
checkboxInput(
inputId = "show_labels",
label = "Show Labels",
value = TRUE
)
)
),
# Home Button Overlay (matching DWD style)
absolutePanel(
id = "zoom_home_panel",
top = 80, left = 10,
actionButton("zoom_home", bsicons::bs_icon("house-fill"), class = "btn-home", title = "Zoom to all stations")
)
)
),
nav_panel(
title = "Station Info",
div(
class = "strict-table",
style = "padding: 20px;",
div(
style = "margin-bottom: 10px; color: #666; display: flex; align-items: center; gap: 6px;",
bsicons::bs_icon("info-circle"),
"Double-click a row to load station data and view the dashboard."
),
h4("Filtered Stations Metadata"),
p("List of stations matching the current resolution and date filters."),
DT::dataTableOutput("station_info_table")
)
),
nav_panel(
title = "Dashboard",
value = "Dashboard",
# Empty State
conditionalPanel(
condition = "!output.station_ready",
div(
style = "height: 600px; display: flex; align-items: center; justify-content: center;",
p("Select a station from the map or the dropdown to view the dashboard.", style = "color: #999; font-size: 1.2em;")
)
),
# Dashboard Content
conditionalPanel(
condition = "output.station_ready",
div(
class = "h-100 p-3",
uiOutput("station_info_header"),
navset_card_pill(
id = "dashboard_subtabs",
nav_panel(
title = "Plots",
div(
style = "padding: 0px;",
uiOutput("jma_plots_container")
)
),
nav_panel(
title = "Data",
div(
style = "margin-top: 10px;",
DT::dataTableOutput("daily_data")
)
)
)
)
)
),
nav_spacer(),
nav_item(
tooltip(
tags$a(
id = "fullscreen_toggle",
href = "#",
onclick = "toggleFullScreen(); return false;",
style = "display: flex; align-items: center; color: rgba(0,0,0,0.55); padding: 0.5rem 1rem; text-decoration: none;",
bsicons::bs_icon("arrows-fullscreen", size = "1.2rem")
),
"Toggle Fullscreen",
placement = "bottom"
)
)
)