0

`Hello everyone,

My Rshiny app allows users to input data and show it interactively in the map and table. However, I want to allow user to upload his own coordinates file. then bind the other informations interactively. Simply put: User upload coordinates => see them on the map => click on given point on the map => coordinates will be added to the XY values(in the form) => user inputs other information => update the coordinates file he uploaded and see changes interactively to keep track of the remaining coordinates to complete. For this, I created a logical column called : Collected(0,1) to keep track of collected data.

Here is my Code. Thank your for your help.

C'A `

# Load the required package

library(shiny)
library(leaflet)
library(readxl)

## Generate coordinates files 

data.frame( Date=as.Date(NA),
            X=runif(n=100, min = 65, max=72), 
            Y=runif(n=100, min = 40, max=47),
            Elevation= runif(n=100, min = 50, max=250), 
            Grid=NA, 
            Group=NA, 
            Line=NA, 
            Station=NA, 
            Activity=NA, 
            Comments=NA, 
            Collected=NA)|>
  write.xlsx("Coordinates_files.xlsx")


# Create a data frame to store the collected data
collected_data <- data.frame(Date = as.Date(character()),
                             X = numeric(),
                             Y = numeric(),
                             Elevation = numeric(),
                             Grid = character(),
                             Group = numeric(),
                             Line = numeric(),
                             Station = numeric(),
                             Activity = character(),
                             Comments = character(), 
                             collected=logical())

# Define UI
ui <- fluidPage(
  
  titlePanel("Field Data Collection"),
  
  sidebarLayout(
    sidebarPanel(
      fileInput(inputId = "coords_file", label = "Upload coordinate data set"),
      dateInput(inputId = "date", label = "Date", value = Sys.Date()),
      numericInput(inputId = "x", label = "X", value = 0),
      numericInput(inputId = "y", label = "Y", value = 0),
      numericInput(inputId = "elevation", label = "Elevation", value = 0),
      textInput(inputId = "grid", label = "Grid Name", value = ""),
      numericInput(inputId = "group", label = "Group Number", value = 0),
      numericInput(inputId = "line", label = "Line Number", value = 0),
      numericInput(inputId = "station", label = "Station Number", value = 0),
      selectInput(inputId = "activity", label = "Activity Type",
                  choices = c("Walking", "Sampling", "Surveying")),
      textInput(inputId = "comments", label = "Comments", value = ""),
      actionButton(inputId = "submit", label = icon("check-circle", "Submit"))
    ),
    
    mainPanel(
      tabsetPanel(
        tabPanel("Data Table", tableOutput(outputId = "data")),
        tabPanel("Map", leafletOutput(outputId = "map"))
      )
    )
  )
)
# Define server
# Define server
server <- function(input, output, session) {
  
  # Define a reactive value to store the collected data
  collected_data <- reactiveValues(df = data.frame(Date = as.Date(character()),
                                                   X = numeric(),
                                                   Y = numeric(),
                                                   Elevation = numeric(),
                                                   Grid = character(),
                                                   Group = numeric(),
                                                   Line = numeric(),
                                                   Station = numeric(),
                                                   Activity = character(),
                                                   Comments = character(),
                                                   Collected = logical()), 
                                   file_path = "")
  
  # Function to update the map with new coordinates
  update_map <- function(df) {
    leaflet() %>%
      addTiles() %>%
      addMarkers(data = df, ~X, ~Y, 
                 popup = ~paste("Station: ", Station, "<br>",
                                "Collected: ", ifelse(Collected, "Yes", "No")))
  }
  
  # Function to read in uploaded file
  read_data <- reactive({
    req(input$coords_file)
    data <- read_excel(input$coords_file$datapath)
    data
  })
  
  # Add an upload button for the user to import a file
  observeEvent(input$coords_file, {
    collected_data$df <- read_data()
    update_map(collected_data$df)
    collected_data$file_path <- input$coords_file$datapath
  })
  
  # Function to add a new row of data to the collected_data data frame
  add_row <- function() {
    new_row <- reactive({
      data.frame(Date = as.Date(input$date),
                 X = input$x,
                 Y = input$y,
                 Elevation = input$elevation,
                 Grid = input$grid,
                 Group = input$group,
                 Line = input$line,
                 Station = input$station,
                 Activity = input$activity,
                 Comments = input$comments,
                 Collected = FALSE,
                 stringsAsFactors = FALSE)
    })
    collected_data$df <- rbind(collected_data$df, new_row())
    updateActionButton(session, "submit", label = tags$i(class = "fa fa-check"))
  }
  
  # Create a reactive expression to store the mapped data for the day
  mapped_data <- reactive({
    if (!is.null(input$date)) {
      subset(collected_data$df, Date == as.Date(input$date))
    } else {
      collected_data$df <- NA
    }
  })
  
  # Update the map with the mapped data for the day
  output$map <- renderLeaflet({
    update_map(mapped_data())
  })
  
  # Show the collected data in the table
  output$data <- renderTable({
    collected_data$df
  })
  
  # Add new row to the collected_data data frame when the user clicks "Submit"
  observeEvent(input$submit, {
    add_row()
  })
  
  # Save the collected data to a CSV file when the app is closed
  session$onSessionEnded(function() {
    write.csv(collected_data$df, file = collected_data$file_path,
              row.names = FALSE)
  })
  
  # Update data and map when user clicks on marker
  observe({
    req(collected_data$df)
    if (input$map_marker_click$id != "NULL") {
      clicked_id <- as.numeric(input$map_marker_click$id)
      if (!is.na(clicked_id)) {
        collected_data$df[clicked_id, "Collected"] <- TRUE
        update_map(mapped_data())
      }
    }
  })
}


shinyApp(ui, server)


0 Answers0