#' mod_update_data UI Function
#'
#' @description A shiny Module.
#'
#' @param id,input,output,session Internal parameters for {shiny}.
#' @param original_data put the internal/default data
#' @param type_data character. Type of data that is used. Could be "azienda", "camp_drupe", "polifenoli"....(to be updated)
#' @param confronto_aziende The updated dataframe of dati_monitoraggio. If type_data != "azienda", you have to use this param (simply write: confronto_aziende = data). It's used for a codice_azienda control (e.g. if in drupe there is a codice_azienda that there isn't in data(), the app returns an error)
#'
#' @noRd
#'
#' @import shiny
#' @import rhandsontable
#' @importFrom DataEditR dataEditUI dataEditServer
#' @importFrom shinyWidgets sendSweetAlert awesomeRadio
#' @importFrom shinyBS bsModal
#' @importFrom shinycssloaders withSpinner
#' @importFrom readr read_delim locale
#' @importFrom janitor remove_empty
#' @importFrom dplyr bind_rows
#'
#' @examples \dontrun{
#' #### in Server ###
#' drupe = mod_update_data_server("updatadrupe", original_data = drupe2, type_data = "camp_drupe", confronto_aziende = data)
#'
#' #drupe will be the drupe() file used in plots, tables etc.
#'
#' ### in UI ###
#' mod_update_data_ui("updatadrupe")
#'
#' }
#'
mod_update_data_ui <- function(id){
ns <- NS(id)
tagList(
actionButton(ns("upaziendedata"), HTML(" Aggiorna i dati"), icon("file-upload"), class = "btn-success", width = "180px", style='padding:10px; font-size:130%; font-weight: bold;' ),
shinyBS::bsModal(ns("upaziendetab"), "Aggiorna i dati", trigger = ns("upaziendedata"), size = "large",
fluidPage(
fluidRow(
column(3, fileInput(ns("fileupaziendedata"), "Carica il file csv")),
column(3, awesomeRadio(ns("selupdtaziende"), "Dati da mostrare", choices = c("solo nuovi", "entrambi"))),
conditionalPanel(condition = "output.type_data_ui != 'azienda'", ns = ns,
column(3, br(), actionButton(ns("button_test"), HTML(" Esegui controllo"), icon("spell-check"), class = "btn-info", width = "170px", style='padding:10px; font-size:110%; font-weight: bold;'))
),
column(3, br(), actionButton(ns("mergeaziende"), HTML(" Unisci/Rimuovi"), icon("edit"),class = "btn-success", width = "170px", style='padding:10px; font-size:110%; font-weight: bold;'))
),
conditionalPanel(
condition = "input.selupdtaziende == 'solo nuovi'", ns = ns,
DataEditR::dataEditUI(ns("edit-1"))
),
conditionalPanel(
condition = "input.selupdtaziende == 'entrambi'", ns = ns,
rhandsontable::rHandsontableOutput(ns("dttable2"))
)
)
)
)
}
#' mod_update_data Server Functions
#'
#' @noRd
mod_update_data_server <- function(id, original_data, type_data, confronto_aziende){
moduleServer( id, function(input, output, session){
ns <- session$ns
output$type_data_ui <- reactive(type_data)
outputOptions(output, "type_data_ui", suspendWhenHidden = FALSE)
userFile <- reactive({
# If no file is selected, don't do anything
# input$fileupaziendedata == ns("fileupaziendedata")
validate(need(input$fileupaziendedata, message = FALSE))
input$fileupaziendedata
})
#carico il nuovo csv file
dataupdated = reactive({
readr::read_delim(userFile()$datapath, delim = ";", col_names = TRUE,na = "", local = readr::locale(decimal_mark = ",", date_format = "%d/%m/%Y", encoding = "windows-1252")) %>%
janitor::remove_empty("rows")
})
#creo la tabella del nuovo file che posso editare e la salvo come "data_to_edit"
data_to_edit <- DataEditR::dataEditServer("edit-1", data = reactive(dataupdated()))
#DataEditR mi trasforma il tibble in un dataframe facendomi perdere tutte le informazioni sulle colonne
#compresa la data. Quando si ritrasforma in tibble, legge le date come char. e quindi il bind non va.
#dunque trasformo il data.frame in un tibble e trasformo la colonna Data_camp (se presente) nel formato data.
data_to_edit_tibble = reactive({
x = data_to_edit() %>% as_tibble()
if("Data_campionamento" %in% colnames(x)){
x$Data_campionamento = as.Date(x$Data_campionamento, "%Y-%m-%d")
return(x)
}else{
return(x)
}
})
#faccio un rbind tra i data originali e i nuovi ( mi serve per il rhandsontable)
databinded = reactive({
dplyr::bind_rows(original_data(), data_to_edit_tibble())
})
#creo una tabella di prova con l'unione dei dati
output$dttable2 = rhandsontable::renderRHandsontable({
databinded() %>% rhandsontable::rhandsontable(readOnly = TRUE)
})
#inizializzo un counter che ad ogni click aumenta di 1
counter <- reactiveVal(0)
#increment per click
observeEvent(input$mergeaziende,{
counter(counter() + 1)
})
#se è stato caricato il nuovo file ed è stato cliccato sul bottone, unisci, altrimenti dati originali
final_data = reactive({
if(!is.null(input$fileupaziendedata) && counter() > 0){
dplyr::bind_rows(original_data(), data_to_edit_tibble())
}else{
original_data()
}
})
#avvisa se ci sono più colnames dei dati originali (problema nei nomi delle colonne)
observe({
if(length(databinded()) > length(original_data())){
shinyWidgets::sendSweetAlert(session = session, title = "Attenzione!", type = "warning",
text = "Alcuni nomi delle colonne non coincidono. Controllare i nomi delle colonne prima di procedere con l'unione.")
}
})
#avvisa quando è stato fatto il rbind
observe({
if(counter() == 1) {
showNotification("Nuovi dati aggiunti.", type = "message")
}
})
#avvisa quando sono stati cancellati i nuovi file e resetta il counter a 0
observe({
#WHEN you want the count reset
if(counter() > 1) {
counter(0)
showNotification("Nuovi dati rimossi.", type = "message")
}
})
observeEvent(input$button_test,{
if(type_data != "azienda" && !is.null(input$fileupaziendedata)){
#se è stato caricato il nuovo file ed è stato cliccato sul bottone, unisci, altrimenti dati originali
test_data = reactive(dplyr::bind_rows(original_data(), data_to_edit_tibble()))
if(FALSE %in% (test_data()$Codice_azienda %in% confronto_aziende()$Codice_azienda)){
shinyWidgets::sendSweetAlert(session = session, title = "Attenzione!", type = "warning",
text = "Mancata corrispondenza con i Codici_azienda. Hai aggiornato anche i dati delle aziende?")
}else{
shinyWidgets::sendSweetAlert(session = session, title = "Ok!", type = "success",
text = "I codici azienda coincidono.")
}
}
})
#ritorna il dataframe che verrà usato nell'app
return(reactive({
x = final_data()
if(type_data == "camp_drupe"){
x$Indice_maturazione = factor(x$Indice_maturazione, levels = c(0:8), ordered = TRUE)
x$Fase_fenologica = factor(x$Fase_fenologica, levels = c(51, 55, 59, 61, 65, 69, 71, 75, 79, 81, 85, 89), ordered = TRUE)
}else if(type_data == "polifenoli"){
x$Presenza_larve = readr::parse_factor(as.character(x$Presenza_larve), levels = c("0","1","2"), ordered = TRUE)
}
return(x)
}))
})
}
## To be copied in the UI
# mod_update_data_ui("mod_update_data_ui_1")
## To be copied in the server
# mod_update_data_server("mod_update_data_ui_1")
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.