| |
| ui <- page_navbar( |
| id = "main_nav", |
| header = tagList( |
| shinyjs::useShinyjs(), |
| tags$head( |
| tags$link(rel = "stylesheet", type = "text/css", href = "styles.css"), |
| tags$script(src = "app.js"), |
| |
| 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'); |
| }); |
| }); |
| ")) |
| ), |
| |
| tags$script(HTML("document.body.classList.add('ui-frozen');")), |
| div( |
| class = "frozen-overlay active", |
| div( |
| class = "frozen-overlay-content", |
| tags$button(class = "frozen-overlay-close", style = "display: none;", "×", title = "Cancel loading"), |
| div(class = "spinner-border text-primary", role = "status"), |
| p(class = "frozen-overlay-message", "Loading base map..."), |
| div( |
| id = "fetch_progress_container", |
| style = "display: none; width: 100%; margin-top: 20px;", |
| div( |
| class = "progress", |
| style = "height: 8px;", |
| div( |
| id = "fetch_progress_bar", |
| class = "progress-bar progress-bar-striped progress-bar-animated", |
| role = "progressbar", |
| style = "width: 0%; transition: width 0.3s ease;" |
| ) |
| ), |
| p(id = "fetch_progress_status", style = "font-size: 0.85rem; color: #666; margin-top: 8px;", "") |
| ) |
| ) |
| ) |
| ), |
| title = "EuroMeteo Explorer", |
| theme = bs_theme(version = 5, bootswatch = "cosmo"), |
| fillable = c("Map View", "Stations Info"), |
| sidebar = sidebar( |
| id = "main_sidebar", |
| title = "Filters", |
| open = list(desktop = "open", mobile = "closed"), |
|
|
| |
| selectizeInput( |
| "country_selector", |
| label = span( |
| "Zoom to Country", |
| tooltip( |
| bs_icon("info-circle", size = "0.9em", class = "ms-1", style = "cursor: help; color: #0056b3;"), |
| "Filter the list of stations by country. Selecting a country will automatically zoom the map to its extent.", |
| placement = "right" |
| ) |
| ), |
| choices = NULL, |
| multiple = TRUE, |
| options = list(placeholder = "All Countries", maxItems = 1, plugins = list("remove_button")) |
| ), |
|
|
| |
| selectizeInput( |
| "station_selector", |
| label = span( |
| "Find Station", |
| tooltip( |
| bs_icon("info-circle", size = "0.9em", class = "ms-1", style = "cursor: help; color: #0056b3;"), |
| "Search for a specific station by name or ID. Selecting a station will load its data in the Dashboard tab.", |
| placement = "right" |
| ) |
| ), |
| choices = NULL, |
| multiple = FALSE, |
| options = list(placeholder = "Type to search...") |
| ), |
| |
| dateRangeInput( |
| "date_range", |
| label = span( |
| "Select Period", |
| tooltip( |
| bs_icon("info-circle", size = "0.9em", class = "ms-1", style = "cursor: help; color: #0056b3;"), |
| "This range controls the available data for the dashboard. The map's time slider (0-23h) is anchored to the 23:00 UTC hour of your selected End Date.", |
| placement = "right" |
| ) |
| ), |
| start = default_start_date, |
| end = default_end_date, |
| min = "2026-03-05", |
| max = Sys.Date() |
| ), |
|
|
| |
| selectInput( |
| "map_parameter", |
| label = span( |
| "Map Parameter", |
| tooltip( |
| bs_icon("info-circle", size = "0.9em", class = "ms-1", style = "cursor: help; color: #0056b3;"), |
| "Choose the weather parameter to visualize on the map. Data is fetched for the specific hour selected on the map's time slider.", |
| placement = "right" |
| ) |
| ), |
| choices = c( |
| "Air Temperature" = "air_temperature", |
| "Precipitation" = "precipitation_amount", |
| "Sea Level Pressure" = "air_pressure_at_mean_sea_level", |
| "Wind Speed" = "wind_speed" |
| ), |
| selected = "air_temperature" |
| ), |
| hr(), |
| textOutput("station_count_filtered"), |
| uiOutput("temp_data_info"), |
| hr(), |
| p("Data source: MeteoGate / E-SOH"), |
| p(style = "font-size: 0.8em; color: #666;", "Includes: Air Temperature, Precip, Wind, Solar* all parameters processed"), |
| p(style = "font-size: 0.8em; color: #666; margin-top: 5px;", "Note: For the current hour, not all stations may have data due to delays between measurement time and loading on the MeteoGate server."), |
| hr(), |
| div( |
| style = "font-size: 0.7em; color: #aaa; margin-top: 5px;", |
| "Map data \u00a9 ", tags$a(href = "https://www.openstreetmap.org/copyright", target = "_blank", "OpenStreetMap"), " contributors via ", tags$a(href = "https://openfreemap.org", target = "_blank", "OpenFreeMap") |
| ) |
| ), |
| nav_panel( |
| title = "Map View", |
| div( |
| class = "outer", |
| maplibreOutput("map", height = "100%", width = "100%"), |
|
|
| |
| 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 |
| ), |
| checkboxInput( |
| inputId = "detailed_tooltips", |
| label = "Detailed Hover Cards (slower)", |
| value = FALSE |
| ) |
| ) |
| ), |
|
|
| |
| absolutePanel( |
| bottom = 200, right = 10, |
| class = "map-legend-panel", |
| style = "z-index: 1000;", |
| uiOutput("map_legend") |
| ), |
|
|
| |
| 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") |
| ), |
|
|
| |
| absolutePanel( |
| id = "time_slider_panel", |
| bottom = 10, left = 60, right = 60, |
| class = "time-slider-panel-outer", |
| style = "z-index: 1000; background: rgba(255,255,255,0.95); padding: 5px 20px; border-radius: 8px; box-shadow: 0 2px 6px rgba(0,0,0,0.15);", |
| div( |
| style = "display: flex; flex-direction: column; align-items: center;", |
| div( |
| style = "display: flex; align-items: center; gap: 15px; width: 100%;", |
| bsicons::bs_icon("clock-history", size = "1.2em"), |
| div( |
| style = "flex: 1;", |
| uiOutput("time_slider_ui") |
| ) |
| ), |
| div( |
| style = "margin-top: -5px; padding-bottom: 5px; font-weight: 500;", |
| textOutput("selected_time_label", inline = TRUE) |
| ) |
| ) |
| ) |
| ) |
| ), |
| nav_panel( |
| title = "Stations Info", |
| card( |
| card_header( |
| div( |
| style = "display: flex; align-items: center; gap: 10px;", |
| bsicons::bs_icon("info-circle-fill", class = "text-primary"), |
| span(class = "d-none d-md-inline", "Double-click a row to load station data and view the dashboard."), |
| span(class = "d-inline d-md-none", "Tap a row to load station data and view the dashboard.") |
| ) |
| ), |
| DT::dataTableOutput("table") |
| ) |
| ), |
| nav_panel( |
| title = "Dashboard", |
| value = "Dashboard", |
| 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 double-click a row in the Stations Info table to view the dashboard.", style = "color: #999;") |
| ) |
| ), |
| conditionalPanel( |
| condition = "output.station_ready", |
| uiOutput("station_info_header"), |
| navset_card_pill( |
| id = "dashboard_subtabs", |
| nav_panel( |
| title = "Plots", |
| uiOutput("details_tabs") |
| ), |
| nav_panel( |
| title = "Data", |
| div( |
| style = "margin-top: 10px;", |
| uiOutput("param_definitions_ui"), |
| DT::dataTableOutput("hourly_data_table") |
| ) |
| ) |
| ) |
| ) |
| ), |
| 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" |
| ) |
| ) |
| ) |
|
|