I am wroking on an shiny app as a volonteer trying to produce an app that would register all of the calls citizens have in the these times of a lockdown for a local Red Cross office. I have managed to get the entry form and to review the DT, but I need to the DT editable so I have included some code to do that.
All is working, except when I write the changes in some of the columns the app changes the column -1 (one to left), overwrites its previous entry in column -1 that I didn't wanted to edit and leaves the entry I actually wanted to edit in the column I wanted to edit (if that makes any sense). What am I doing wrong? I am pasting the code, datasets stored on Dropbox.
## app.R ##
# load the required packages
library(shiny)
library(shinyjs)
require(shinydashboard)
library(ggplot2)
library(dplyr)
library(DT)
library(data.table)
# Obavezna polja
fieldsMandatory <- c("Ime", "Prezime", "Problem")
# Označiti obavezna polja s crvenim asteriksom
labelMandatory <- function(label) {
tagList(
label,
span("*", class = "mandatory_star")
)
}
# CSS za obavezna polja, *
appCSS <-
".mandatory_star { color: red; }"
# HumanTime za time stamp u csv
humanTime <- function() format(Sys.time(), "%Y%m%d-%H%M%OS")
# Čuvanje odgovora u folderu "reponses"
fieldsAll <- c("Ime", "Prezime", "Adresa", "BrojTel", "OIB",
"Problem", "Pomagac","Trajanje","Rjesenje")
# DropBox autorizacija
library(rdrop2)
# This will launch your browser and request access to your Dropbox account.
# You will be prompted to log in if you aren't already logged in.
#drop_auth()
# Once completed, close your browser window and return to R to complete authentication.
# The credentials are automatically cached (you can prevent this) for future use.
# If you wish to save the tokens, for local/remote use
#token <- drop_auth()
#saveRDS(token, file = "dropbox_token.rds")
# Then in any drop_* function, pass `dtoken = token
# Tokens are valid until revoked.
outputDir <- "responses"
outputJedan <- "reponsesJedanFajl"
loadData <- function() {
files_info <- drop_dir(outputDir)
file_paths <- files_info$path_display
# Only take the last 20 because each file takes ~1 second to download
file_paths <- tail(file_paths, 1)
zadnji <-
lapply(file_paths, drop_read_csv, stringsAsFactors = FALSE, encoding = 'UTF-8') %>%
do.call(rbind, .)
write.csv(zadnji, "zadnji.csv", row.names = FALSE, quote = TRUE, fileEncoding = "UTF-8")
# Upload the file to Dropbox
drop_upload("zadnji.csv", path = outputDir, mode = "overwrite")
# files_info2 <- drop_dir(outputJedan)
# file_paths2 <- files_info2$path_display
# Only take the last 20 because each file takes ~1 second to download
#file_paths2 <- tail(file_paths, 20)
data <-
lapply(c("responses/zadnji.csv", "reponsesJedanFajl/fajl.csv"),
drop_read_csv, stringsAsFactors = FALSE, encoding = 'UTF-8') %>%
do.call(rbind, .)
write.csv(data, "fajl.csv", row.names = FALSE, quote = TRUE, fileEncoding = "UTF-8")
# Upload the file to Dropbox
drop_upload("fajl.csv", path = outputJedan, mode = "overwrite")
data
}
# UI
ui <- dashboardPage(
dashboardHeader(title = "HDCK-ČK Dashboard"),
skin = "red",
## Sidebar content
dashboardSidebar(
collapsed = TRUE,
sidebarMenu(
#menuItem("Dashboard", tabName = "dashboard", icon = icon("dashboard")),
menuItem("Evidencija", tabName = "evidencija", icon = icon("th")),
#menuItem("Evidencija", tabName = "evidencija", icon = icon("th")),
menuItem("Sajt", icon = icon("send",lib='glyphicon'),
href = "http://www.crveni-kriz-cakovec.hr")
)
),
## Body content
dashboardBody(
tabItems(
# First tab content
tabItem(
tabName = "evidencija",
navbarPage("",
tabPanel("Upis",
fluidPage(
shinyjs::useShinyjs(),
shinyjs::inlineCSS(appCSS),
sidebarPanel(
width = 3,
id = "form",
textInput("Ime", labelMandatory("1. Ime")),
textInput("Prezime", labelMandatory("2. Prezime")),
textInput("Adresa", label = "3. Adresa (ulica i broj, mjesto)"),
textInput(inputId = "BrojTel", label = "4. Broj telefona",
value = NULL),
numericInput(inputId = "OIB", label = "5. OIB", value = NULL),
#checkboxInput("CZSS", "Označiti ako je korisnik CZSS", FALSE),
#sliderInput("Dob", "5. Dob", 1, 100, 50, ticks = FALSE),
textAreaInput("Problem", labelMandatory("6. Opis problema ili potrebe"),
"", height = 100),
textAreaInput("Rjesenje", "7. Na koji način je problem riješen?",
"", height = 50),
selectInput("Pomagac", "8. Pomagač",
c("", "Barbara", "Elizabeta",
"Ines", "Iva", "Lana", "Vlatka", "Željka")),
numericInput(inputId = "Trajanje", label = "9. Trajanje razgovora u min", value = 5),
actionButton("submit", "Unesi")#, class = "btn-primary")
),
mainPanel(
width = 9,
h3("Tablica s pregledom prethodnih zapisa:"),
DT::dataTableOutput("responsesTable"),
style = "overflow-y: scroll;overflow-x: scroll; overflow: auto;",
#downloadButton("downloadBtn", "Skini *.csv"),
# br(),
# actionButton("viewBtn","View"),
br(),
actionButton("saveBtn", "Zapiši rješenje", style="float:right")
# br(),
# DT::dataTableOutput("updated.df")
)
)),
tabPanel("Upute"
)
)
)
)
)
)
# Server
# Učitavnje podataka na prvom učitavnju app
tablica <- function() {
data <- drop_read_csv("reponsesJedanFajl/fajl.csv", fileEncoding = "UTF-8",
stringsAsFactors = FALSE)
data
}
server <- function(input, output, session) {
drop_auth(rdstoken = "dropbox_token.rds")
# Prikaži tablicu na onload
tablicica <- data.frame(tablica())
output$responsesTable <- DT::renderDataTable(
tablicica,
selection = "none",
editable = TRUE,
rownames = FALSE,
extensions = 'Buttons',
server = FALSE,
options = list(
paging = TRUE,
searching = TRUE,
scroller = TRUE,
dom = 'Bfrtip',
extensions = c('Responsive', 'Buttons'),
buttons = c('excel', 'pdf', 'copy', 'csv', 'print')
))
# Provjera obaveznih polja kod upisa
observe({
mandatoryFilled <-
vapply(fieldsMandatory,
function(x) {
!is.null(input[[x]]) && input[[x]] != ""
},
logical(1))
mandatoryFilled <- all(mandatoryFilled)
shinyjs::toggleState(id = "submit", condition = mandatoryFilled)
})
# Čuvanje pojedinih inputa u csv nakon upisa
formData <- reactive({
data <- sapply(fieldsAll, function(x) input[[x]])
data <- c(data, VremenskiPoredak = humanTime())
data <- t(data)
data
})
# Čuvanje inputa u pojedinim csv i što učiniti nakon što se stisne gumb
saveData <- function(data) {
#data <- t(data)
# Unique file name
fileName <- sprintf("%s_%s.csv", humanTime(), digest::digest(data))
# Čuvanje fajla u prvremenom direktoriju
filePath <- file.path(tempdir(), fileName)
write.csv(data, filePath, row.names = FALSE, quote = TRUE, fileEncoding = "UTF-8")
# Upload fajla na Dropbox
drop_upload(filePath, path = outputDir)
}
# akcija kad se pritisne gumb Zapiši, za zapisivanje novih upisa
observeEvent(input$submit, {
saveData(formData())
# I prikaži tablicu s novim upisima
output$responsesTable <- DT::renderDataTable(
datatable(
loadData(),
rownames = FALSE,
extensions = 'Buttons',
#server = FALSE,
options = list(
paging = TRUE,
searching = TRUE,
#fixedColumns = FALSE,
#autoWidth = TRUE,
#ordering = TRUE,
deferRender = TRUE,
#scrollY = 400,
scroller = TRUE,
dom = 'Bfrtip',
orientation ='landscape',
extensions = c('Responsive', 'Buttons'),
buttons = c('excel', 'pdf', 'copy', 'csv', 'print')
))
)
})
observeEvent(input$responsesTable_cell_edit, {
tablicica[input$responsesTable_cell_edit$row,
input$responsesTable_cell_edit$col] <<- input$responsesTable_cell_edit$value
})
observeEvent(input$saveBtn,{
write.csv(tablicica, "fajl.csv", row.names = FALSE, quote = TRUE, fileEncoding = "UTF-8")
# Upload the file to Dropbox
drop_upload("fajl.csv", path = outputJedan, mode = "overwrite")
# Prikaži tablicu nakon što su unesene promjene
output$responsesTable <- DT::renderDataTable(
datatable(
tablicica,
rownames = FALSE,
options = list(
searching = TRUE,
lengthChange = TRUE
# # fixedColumns = FALSE,
# # autoWidth = TRUE,
# # ordering = FALSE,
# dom = 'tB',
# buttons = c('copy', 'csv', 'excel', 'pdf')
# ),
# # class = "display", #if you want to modify via .css
# # extensions = "Buttons"
))
)
})
# # Download button
# output$downloadBtn <- downloadHandler(
# filename = function() {
# sprintf("evidencija-psihosocijalne_%s.csv", humanTime())
# },
# content = function(file) {
# write.csv(loadData(), file, row.names = FALSE)
# }
# )
# Reset formu nakon submita
observeEvent(input$submit, {
reset("form")
})
}
shinyApp(ui, server)
R and DT count columns differently. In R the leftmost column is column 1. In DT the leftmost column is column 0. This is also known as one or zero-based array indexing.
Adding a few strategic +1 or -1 will do the trick.
If you need help knowing where to put those, feel free to post a minimal example and we can help you work through it.
Related
I'm trying to save the result of dynamically filtered data into a csv file ; I created a button etc but the app freezes up when i press it... any help would be much appreciated i'm new to Shiny unfortunately
library(dplyr)
library(shinyWidgets)
fpath <- '/dbfs/May2022'
# Define UI
ui <- fluidPage(theme = shinytheme("spacelab"),
navbarPage(
"Display Data",
tabPanel(
"Select File",
sidebarPanel(
selectInput('selectfile','Select File',choice = list.files(fpath, pattern = ".csv")),
mainPanel("Main Panel",dataTableOutput("ftxtout"),style = "font-size:50%") # mainPanel
), #sidebarPanel
), #tabPanel
tabPanel("Subset Data",
sidebarPanel(
dropdown(
label = "Please Select Columns to Display",
icon = icon("sliders"),
status = "primary",
pickerInput(
inputId = "columns",
# label = "Select Columns",
choices = NULL,
multiple = TRUE
)#pickerInput
), #dropdown
selectInput("v_attribute1", "First Attribute to Filter Data", choices = NULL),
selectInput("v_attribute2", "Second Attribute to Filter Data", choices = NULL),
selectInput("v_filter1", "First Filter", choices = NULL),
selectInput("v_filter2", "Second Filter", choices = NULL),
textInput("save_file", "Save to file:", value=""),
actionButton("doSave", "Save Selected Data")
), #sidebarPanel
mainPanel(tags$br(),tags$br(),
h4("Data Selection"),
dataTableOutput("txtout"),style = "font-size:70%"
) # mainPanel
), # Navbar 1, tabPanel
tabPanel("Create Label", "This panel is intentionally left blank")
) # navbarPage
) # fluidPage
# Define server function
server <- function(input, output, session) {
output$fileselected<-renderText({
paste0('You have selected: ', input$selectfile)
})
info <- eventReactive(input$selectfile, {
fullpath <- file.path(fpath,input$selectfile)
read.csv(fullpath, header = TRUE, sep = ",")
})
observeEvent(info(), {
df <- info()
vars <- names(df)
# Update select input immediately after clicking on the action button.
updatePickerInput(session, "columns","Select Columns", choices = vars, selected=vars[1:2])
})
observeEvent(input$columns, {
vars <- input$columns
updateSelectInput(session, "v_attribute1","First Attribute to Filter Data", choices = vars)
updateSelectInput(session, "v_attribute2","Second Attribute to Filter Data", choices = vars, selected=vars[2])
})
observeEvent(input$v_attribute1, {
choicesvar1=unique(info()[[input$v_attribute1]])
req(choicesvar1)
updateSelectInput(session, "v_filter1","First Filter", choices = choicesvar1)
})
observeEvent(input$v_attribute2, {
choicesvar2=unique(info()[[input$v_attribute2]])
req(choicesvar2)
updateSelectInput(session, "v_filter2","Second Filter", choices = choicesvar2)
})
output$ftxtout <- renderDataTable({
head(info())
}, options =list(pageLength = 5))
output$txtout <- renderDataTable({
f <- info() %>% subset(select = input$columns)
f$var1 <- f[[input$v_attribute1]]
f$var2 <- f[[input$v_attribute2]]
ff <- f %>% dplyr::filter(var1 == input$v_filter1 & var2 == input$v_filter2)
fff <- ff %>% subset(select=-c(var1,var2))
head(fff)
}, options =list(pageLength = 5)
) #renderDataTable
#Saving data
observeEvent(input$doSave, {
req(input$columns,input$v_attribute1,input$v_attribute2,input$v_filter1,input$v_filter2)
f <- info() %>% subset(select = input$columns)
f$var1 <- f[[input$v_attribute1]]
f$var2 <- f[[input$v_attribute2]]
ff <- f %>% dplyr::filter(var1 == input$v_filter1 & var2 == input$v_filter2)
fff <- ff %>% subset(select=-c(var1,var2))
fullfpath <- paste0(file.path(fpath,input$save_file),".csv",sep="")
write.csv(fff,fullfpath, row.names = True)
Save_done <- showNotification(paste("Data Has been saved"), duration = NULL)
})
} # server
# Create Shiny object
shinyApp(ui = ui, server = server)
I've tried a few different things but can't get it work, i'm not sure what i'm doing wrong here!
You have a typo when calling write.csv. The argument row.names should be TRUE and not True.
I also took the time to write the last observeEvent used to save the data to avoid creating two columns just for doing the subsetting.
observeEvent(input$doSave, {
req(
input$columns, input$v_attribute1,
input$v_attribute2, input$v_filter1,
input$v_filter2, input$save_file
)
df <- info() %>% select(all_of(input$columns))
df_filtered <- df %>%
dplyr::filter(
.data[[input$v_attribute1]] == input$v_filter1 &
.data[[input$v_attribute2]] == input$v_filter2
)
fullfpath <- paste0(file.path(fpath, input$save_file), ".csv", sep = "")
write.csv(df_filtered, fullfpath, row.names = TRUE)
Save_done <- showNotification(paste("Data Has been saved"), duration = NULL)
})
Full app:
library(dplyr)
library(shinyWidgets)
library(shinythemes)
fpath <- "sample_datasets"
# Define UI
ui <- fluidPage(
theme = shinytheme("spacelab"),
navbarPage(
"Display Data",
tabPanel(
"Select File",
sidebarPanel(
selectInput("selectfile", "Select File", choice = list.files(fpath, pattern = ".csv")),
mainPanel("Main Panel", dataTableOutput("ftxtout"), style = "font-size:50%") # mainPanel
), # sidebarPanel
), # tabPanel
tabPanel(
"Subset Data",
sidebarPanel(
dropdown(
size = "xs",
label = "Please Select Columns to Display",
icon = icon("sliders"),
status = "primary",
pickerInput(
inputId = "columns",
# label = "Select Columns",
choices = NULL,
multiple = TRUE
) # pickerInput
), # dropdown
selectInput("v_attribute1", "First Attribute to Filter Data", choices = NULL),
selectInput("v_attribute2", "Second Attribute to Filter Data", choices = NULL),
selectInput("v_filter1", "First Filter", choices = NULL),
selectInput("v_filter2", "Second Filter", choices = NULL),
textInput("save_file", "Save to file:", value = ""),
actionButton("doSave", "Save Selected Data")
), # sidebarPanel
mainPanel(
tags$br(),
tags$br(),
h4("Data Selection"),
dataTableOutput("txtout"),
style = "font-size:70%"
) # mainPanel
), # Navbar 1, tabPanel
tabPanel("Create Label", "This panel is intentionally left blank")
) # navbarPage
) # fluidPage
# Define server function
server <- function(input, output, session) {
output$fileselected <- renderText({
paste0("You have selected: ", input$selectfile)
})
info <- eventReactive(input$selectfile, {
fullpath <- file.path(fpath, input$selectfile)
read.csv(fullpath, header = TRUE, sep = ",")
})
observeEvent(info(), {
df <- info()
vars <- names(df)
# Update select input immediately after clicking on the action button.
updatePickerInput(session, "columns", "Select Columns", choices = vars, selected = vars[1:2])
})
observeEvent(input$columns, {
vars <- input$columns
updateSelectInput(session, "v_attribute1", "First Attribute to Filter Data", choices = vars)
updateSelectInput(session, "v_attribute2", "Second Attribute to Filter Data", choices = vars, selected = vars[2])
})
observeEvent(input$v_attribute1, {
choicesvar1 <- unique(info()[[input$v_attribute1]])
req(choicesvar1)
updateSelectInput(session, "v_filter1", "First Filter", choices = choicesvar1)
})
observeEvent(input$v_attribute2, {
choicesvar2 <- unique(info()[[input$v_attribute2]])
req(choicesvar2)
updateSelectInput(session, "v_filter2", "Second Filter", choices = choicesvar2)
})
output$ftxtout <- renderDataTable(
{
head(info())
},
options = list(pageLength = 5)
)
output$txtout <- renderDataTable(
{
f <- info() %>% subset(select = input$columns)
f$var1 <- f[[input$v_attribute1]]
f$var2 <- f[[input$v_attribute2]]
ff <- f %>% dplyr::filter(var1 == input$v_filter1 & var2 == input$v_filter2)
fff <- ff %>% subset(select = -c(var1, var2))
head(fff)
},
options = list(pageLength = 5)
) # renderDataTable
# Saving data
observeEvent(input$doSave, {
req(
input$columns, input$v_attribute1,
input$v_attribute2, input$v_filter1,
input$v_filter2, input$save_file
)
df <- info() %>% select(all_of(input$columns))
df_filtered <- df %>%
dplyr::filter(
.data[[input$v_attribute1]] == input$v_filter1 &
.data[[input$v_attribute2]] == input$v_filter2
)
fullfpath <- paste0(file.path(fpath, input$save_file), ".csv", sep = "")
write.csv(df_filtered, fullfpath, row.names = TRUE)
showNotification(paste("Data Has been saved"), duration = NULL)
})
} # server
# Create Shiny object
shinyApp(ui = ui, server = server)
I have a shiny app linked to a duckdb. Since I have a very big dataset I just want to load in 10'000 rows. However as soon as the user downloads the dataset it should download the entire dataset and not just the first 10'000 rows. So I guess there should be some kind of if condition where i specify the "LIMIT 10000" which reacts on the download handler. However, I dont know how to change the LIMIT based on the download handler.
BestandeslisteDaten_UI <- function(id3, mydb, data_Vertrag){
ns <- NS(id3)
tagList(
fluidRow(
box(
title = "Daten Bestandesliste", status = "primary", solidHeader = TRUE,
collapsible = TRUE, width=9,
DTOutput(ns("dt31"))
),
box(
title = "Einschränkung des Datenset", status = "primary", solidHeader = TRUE,
collapsible = TRUE, width=3, height = "110em",
downloadButton(ns("download32"),"Download entire Table as csv")
)
)
)
}
BestandeslisteDaten_Server <- function(id3, mydb, data_Vertrag){
moduleServer(
id3,
function(input, output, session){
filter_BestandVertrag_Daten <- reactive({
query <- glue_sql("SELECT * FROM data_Vertrag",
.con = mydb)
add_where <- TRUE
query <- glue_sql(query, " LIMIT 10000", .con = mydb)
print(query)
dt <- as.data.table(dbGetQuery(mydb, query))
print(dt)
dt
})
# Data Table
output$dt31 <- renderDT({
filter_BestandVertrag_Daten() %>%
datatable(
extensions = 'Buttons',
options = list(
server = TRUE,
lengthMenu=c(10, 100),
scrollX = TRUE,
scrollY = "500px",
dom = 'Blfrtip'
))
})
# Download Datatable
output$download32 <- downloadHandler(
filename = function() {
paste("Bestandesliste_", Sys.Date(), ".csv", sep="")
},
content = function(file) {
write.csv(filter_BestandVertrag_Daten(), file)
}
)
}
)
}
Is there a way to automatically upload the excel file.
Right now, the user has to manually upload the excel file(file.xlsx) that is kept under project folder.
Now the expected output is the moment the user clicks on "Automatically Upload the exceil file", the file should get uploaded.
Is there a way to achieve this? Let me know if this makes sense
library(tidyverse)
library(shiny)
library(shinydashboard)
library(DT)
ui <-
dashboardPage(
skin = "green",
dashboardHeader(
title = "Test",
titleWidth = 280
),
dashboardSidebar(
width = 280,
sidebarMenu(
menuItem(text = "File(s) Upload", tabName = "Files", icon = icon("file-upload")),
menuItem(text = "Output", tabName = "Out1", icon = icon("file-upload"))
)
),
dashboardBody(
tabItems(
tabItem(
tabName = "Files",
fluidRow(
column(
width = 4,
inputPanel(
fileInput(inputId = "File1", label = "File", multiple = TRUE, accept = c(".xlsx")),
selectInput(inputId = "Sheet1", label = "Select sheet", choices = NULL, selected = NULL),
actionButton("sub", "Automatically Upload the exceil file")
)
)
)
),
tabItem(
tabName = "Out1",
fluidRow(column(width = 10, strong("Data")), align = "center"),
br(),
fluidRow(dataTableOutput("Data1"))
)
)
)
)
server <- function(input, output){
# Populate the drop down menu with the names of the different Excel Sheets, but
# only after a new file is supplied
observe({
sheet_names <- readxl::excel_sheets(input$File1$datapath)
shiny::updateSelectInput(
inputId = "Sheet1",
choices = sheet_names,
selected = sheet_names[[1]]
)
}) %>%
bindEvent(input$File1)
# When the drop down meny is populated, read the selected sheet from the Excel
# file
thedata <- reactive({
req(input$Sheet1)
readxl::read_xlsx(input$File1$datapath, sheet = input$Sheet1)
})
output$Data1 <-
renderDataTable(
thedata()
, extensions = "Buttons"
, options = list(
dom = "Bfrtip"
, buttons = c("copy", "csv", "excel", "pdf", "print")
)
)
# observe({
# print(reactiveValuesToList(input, all.names = FALSE))
# })
}
runApp(
list(ui = ui, server = server)
, launch.browser = TRUE
)
I have seen that this problem has happened to other people, but their solutions have not worked for me. I have my app.R file and a .RData file with the required inputs in the same ECWA_Strategic_Planning_Tool directory. When I run:
library(rsconnect)
rsconnect::deployApp('C:/Users/mikialynn/Documents/Duke/Spring2017/MP/GISTool/Final/ECWA_Strategic_Planning_Tool')
I get the following error on the web page that opens up:
ERROR: An error has occurred. Check your logs or contact the app author for clarification.
However, I cannot find anything wrong. I install all of my packages, I use relative pathways etc. I am pasting all of the code from my app below. If anyone can spot what I'm doing wrong, I would greatly appreciate it!
library(shiny)
library(leaflet)
library(sp)
library(rgdal)
library(rstudioapi) # For working directory
library(raster)
library(RColorBrewer)
library(rgeos) #Maybe use gSimplify to simplify polygon
library(DT) #To make interactive DataTable
library(plotly) #For pie chart
library(ggplot2) # for layout
# Set Working Directory
setwd(dirname(rstudioapi::getActiveDocumentContext()$path))
# Load R Workspace
load('Shiny.Strategies.RData')
# UI variables
neigh.names <- levels(merge.proj$View)
neigh.default <- c("Urban7")
dt.names <- c('PARCEL_ID', 'PIN', 'OWNER_NAME', 'SITE_ADDRE', 'OWNER_ADDR',
'SUM_ACRE', 'LANDUSE_DE', 'LAND_VALUE', 'TOTAL_VALU', 'SALE_PRICE',
'Pluvial_WtScore', 'Rest_WtScore', 'GI_WtScore', 'SC_WtScore',
'UNCWI_WtScore', 'Total_Score', 'View')
dt.default <- c('PARCEL_ID', 'Pluvial_WtScore', 'Rest_WtScore',
'GI_WtScore', 'SC_WtScore', 'UNCWI_WtScore', 'Total_Score', 'View')
# Build UI
ui <- fluidPage(
titlePanel("ECWA Strategic Planning Tool"),
HTML('<br>'),
column(2,
HTML("<strong>Instructions:</strong><br/><br/>"),
HTML("<p>1) Select weights for parameters and click 'Run' to
initiate tool.<br/><br/>
2) Use rightside panel to adjust Table and Map Settings.<br/>
<br/>
3) Use search/sort functions of Table to identify parcels.
Select row to display Total Score Chart.<br/><br/>
4) Input View and Parcel ID from Table to Map settings to
identify parcel in Map.<br/><br/>
5) When satisfied with weights, click 'Export Shapefile' to
save shapefile of all parcels.<p/><br/>"),
HTML("<strong>Calculate Parcel Scores: </strong><br/>"),
helpText('The sum of the weights must equal to 1.'),
sliderInput(inputId = "weightPluvial", label = "Weight for Pluvial
Flooding",
value = 0.20, min = 0, max = 1),
sliderInput(inputId = "weightRest", label = "Weight for
Restoration",
value = 0.20, min = 0, max = 1),
sliderInput(inputId = "weightGI", label = "Weight for Green
Infrastructure",
value = 0.20, min = 0, max = 1),
sliderInput(inputId = "weightSC", label = "Weight for City
Stormwater Controls",
value = 0.20, min = 0, max = 1),
sliderInput(inputId = "weightUNCWI", label = "Weight for UNCWI",
value = 0.20, min = 0, max = 1),
actionButton("run", "Run"),
actionButton("export", "Export Shapefile")),
column(8,
HTML("<h3><strong>Table Summary</strong></h3>"),
HTML("<br>"),
dataTableOutput("table")),
column(2,
HTML("<p><br><br></p>"),
HTML("<h4>Table Settings:</h4>"),
checkboxGroupInput(inputId = 'show_vars', label = 'Select column(s)
to display in Table:', choices = dt.names, selected = dt.default),
HTML("<strong>Total Score Chart:</strong>"),
helpText("Please select Table row to display pie chart."),
plotlyOutput("pie")
),
fluidRow(
column(8, offset = 2,
HTML("<br>"),
HTML("<h3><strong>Map Display</strong></h3>"),
leafletOutput("map", height = 800),
HTML("<br><br>")),
column(2,
HTML("<p><br><br><br></p>"),
HTML("<h4>Map Settings:</h4>"),
checkboxGroupInput(inputId = 'show_neigh', label = 'Select
View(s) to display in Map:', choices = neigh.names,
selected = neigh.default),
HTML("<br>"),
sliderInput("range", "Select score range to display in Map:", min
= 0.0, max= 10.0, value = as.numeric(c("0.0", "10.0")), step = 0.1),
HTML("<br>"),
HTML("<strong>Parcel Zoom:</strong>"),
helpText("The View and Score Range must contain the parcel of
interest to execute zoom."),
numericInput('parcel','Enter Parcel ID',0)
)
))
# SERVER
server <- function(input, output) {
defaultData <-
eventReactive(input$run, {
# Multiply by Weights
merge.proj#data$Pluvial_WtScore <-
round(merge.proj#data$Pluvial_Score*input$weightPluvial, digits = 1)
merge.proj#data$Rest_WtScore <-
round(merge.proj#data$Rest_Score*input$weightRest, digits = 1)
merge.proj#data$GI_WtScore <-
round(merge.proj#data$GI_Score*input$weightGI, digits = 1)
merge.proj#data$SC_WtScore <-
round(merge.proj#data$SC_Score*input$weightSC, digits = 1)
merge.proj#data$UNCWI_WtScore <-
round(merge.proj#data$UNCWI_Score*input$weightUNCWI, digits = 1)
# Find Total Score
merge.proj#data$Total_Score <- merge.proj#data$Pluvial_WtScore +
merge.proj#data$Rest_WtScore + merge.proj#data$GI_WtScore +
merge.proj#data$SC_WtScore + merge.proj#data$UNCWI_WtScore
return(merge.proj)
})
# Subset by neighborhood
neighData <- reactive ({
merge.proj <- defaultData()
merge.proj[merge.proj$View%in%input$show_neigh,]
})
# Plot with leaflet
# Palette for map
colorpal <- reactive({
merge.proj <- neighData()
colorNumeric(palette = "YlOrRd",
domain = merge.proj$Total_Score)
})
# Pop Up Option for map
# popup <- paste0("<strong>Parcel ID: </strong>",
# merge.proj#data$PARCEL_ID,
# "<br><strong>Total Score: </strong>",
# merge.proj#data$Total_Score)
# Label Option for map
labels <- reactive({
merge.proj <- neighData()
sprintf("<strong>Parcel ID: </strong>%s<br/><strong>Total Score:
</strong>%g",
merge.proj$PARCEL_ID,
merge.proj$Total_Score) %>% lapply(htmltools::HTML)
})
# Render Default Map
output$map <- renderLeaflet ({
merge.proj <- neighData()
pal <- colorpal()
lab <- labels()
leaflet() %>%
#addProviderTiles(provider='Esri.WorldImagery') %>%
# setView(zoom =) %>%
addTiles() %>%
addPolygons(
#data = merge.proj[input$show_neigh,, drop = FALSE],
data=merge.proj,
fillColor = ~pal(Total_Score),
weight = 1,
opacity = 1,
color = "white",
dashArray = "3",
fillOpacity = 0.7,
highlight = highlightOptions(
weight = 3,
color = "#666",
dashArray = "",
fillOpacity = 0.7,
bringToFront = TRUE),
# popup= popup) %>%
label = lab,
labelOptions = labelOptions(
style = list("font-weight" = "normal", padding = "3px 8px"),
textsize = "15px",
direction = "auto")) %>%
addLegend(position = "bottomleft",pal = pal, opacity = 0.7, values =
merge.proj$Total_Score, title = "<strong>Total Score</strong>")
})
# Build Data Table
output$table <- renderDataTable({
merge.proj <- defaultData()
table.dat <- merge.proj[, c('PARCEL_ID', 'PIN', 'OWNER_NAME',
'SITE_ADDRE', 'OWNER_ADDR', 'SUM_ACRE', 'LANDUSE_DE', 'LAND_VALUE',
'TOTAL_VALU', 'SALE_PRICE', 'Pluvial_WtScore', 'Rest_WtScore', 'GI_WtScore',
'SC_WtScore', 'UNCWI_WtScore', 'Total_Score', 'View')]
datatable(data = table.dat#data[, input$show_vars, drop = FALSE],
options = list(lengthMenu = c(5, 10, 20, 30), pageLength = 20), rownames =
FALSE)
})
# Plot-ly
output$pie <- renderPlotly({
merge.proj <- defaultData()
names <- c('Pluvial', 'Rest', 'GI', 'SC', 'UNCWI')
colors <- c('rgb(128,133,133)', 'rgb(211,94,96)', 'rgb(144,103,167)',
'rgb(114,147,203)', 'rgb(171,104,87)')
selectedrowindex <-
input$table_rows_selected[length(input$table_rows_selected)]
selectedrowindex <- as.numeric(selectedrowindex)
df <- data.frame(merge.proj[selectedrowindex, c('Pluvial_WtScore',
'Rest_WtScore', 'GI_WtScore', 'SC_WtScore', 'UNCWI_WtScore')])
vector <- unname(unlist(df[1,]))
if (!is.null(input$table_rows_selected)) {
par(mar = c(4, 4, 1, .1))
plot_ly(labels = names, values = vector, type = 'pie',
textposition = 'inside',
textinfo = 'label+percent',
insidetextfont = list(color = '#FFFFFF'),
hoverinfo = 'text',
text = ~paste('Score:', vector),
marker = list(colors = colors,
line = list(color = '#FFFFFF', width = 1)),
#The 'pull' attribute can also be used to create space between the sectors
showlegend = FALSE) %>%
layout(#title = '% Total Score',
xaxis = list(showgrid = FALSE, zeroline = FALSE, showticklabels = FALSE),
yaxis = list(showgrid = FALSE, zeroline = FALSE, showticklabels = FALSE))
}
else {return(NULL)}
})
# Update map to parcel score slider
# Subset data
filteredData <- reactive({
merge.proj <- neighData()
merge.proj[merge.proj#data$Total_Score >= input$range[1] &
merge.proj#data$Total_Score <= input$range[2],]
})
# New Palette
colorpal2 <- reactive({
merge.proj <- filteredData()
colorNumeric(palette = "YlOrRd",
domain = merge.proj$Total_Score)
})
# Pop Up Option
# popup <- paste0("<strong>Parcel ID: </strong>",
# merge.proj#data$PARCEL_ID,
# "<br><strong>Total Score: </strong>",
# merge.proj#data$Total_Score)
# Label Option
labels2 <- reactive({
merge.proj <- filteredData()
sprintf("<strong>Parcel ID: </strong>%s<br/><strong>Total Score:
</strong>%g",
merge.proj$PARCEL_ID,
merge.proj$Total_Score) %>% lapply(htmltools::HTML)
})
#Leaflet Proxy
observe({
merge.proj <- filteredData()
pal2 <- colorpal2()
lab2 <- labels2()
leaf <- leafletProxy("map", data = filteredData()) %>%
clearShapes() %>%
addPolygons(
fillColor = ~pal2(Total_Score),
weight = 1,
opacity = 1,
color = "white",
dashArray = "3",
fillOpacity = 0.7,
highlight = highlightOptions(
weight = 3,
color = "#666",
dashArray = "",
fillOpacity = 0.7,
bringToFront = TRUE),
# popup= popup) %>%
label = lab2,
labelOptions = labelOptions(
style = list("font-weight" = "normal", padding = "3px 8px"),
textsize = "15px",
direction = "auto"))
if(input$parcel>0){
sub.dat <- merge.proj[merge.proj$PARCEL_ID==input$parcel,]
zx <- mean(extent(sub.dat)[1:2])
zy <- mean(extent(sub.dat)[3:4])
leaf <- leaf %>%
setView(lng=zx,lat=zy,zoom=16)
}
leaf
})
#Update Legend
observe({
proxy <- leafletProxy("map", data = filteredData())
pal2 <- colorpal2()
proxy %>% clearControls()
proxy %>% addLegend(position = "bottomleft",pal = pal2, opacity = 0.7,
values = ~Total_Score, title = "<strong>Total Score</strong>")
})
# Export new shapefile
#make so that user can choose name and allow overwrite
observeEvent(input$export, {
merge.proj <- defaultData()
writeOGR(merge.proj, dsn = "Data", layer = "Strategies_Output", driver =
"ESRI Shapefile")
})
}
shinyApp(ui = ui, server = server)
Issue resolved! My initial suspicion was correct; it had to do with the .rdata file. It also relates to shinyapp.io's servers which run on a Linux based server. From my reading, Linux only handles lowercase file paths and extensions. The reason why it worked for the .csv file is because it's pretty common to have the file extension saved in all lowercase. This was not the case for the .RData file. Using the RStudio IDE and the physical "Save Workspace" button, the default file extension is .RData (case sensitive). I couldn't rename the file extension (for some reason, I'm not the most tech-savvy person). Similar to the load() function, there's the save() function. Previously, I used the save() file as follows (note the capitalized .RData at the end):
save(df_training_separated_with_models, file = "sample_data_with_models.RData")
However, using the same function in all lowercase fixes the issue:
save(df_training_separated_with_models, file = "sample_data_with_models.rdata")
Hope this helps any other poor soul with the same issue that is scouring the internet and other forums.
Cheers!
I have an app that has lots of tabItems and for each one of them I specify which files should be placed in a certain directory (in the example below I use getwd()) so that the app can run certain procedures.
These files will be listed in a "table", along with buttons and other features.
At times a file produced in one tabItem will be used as an input in another..
and I would like to hide the button created dynamically in the module for this file in the tabItem that uses the file as an input.
I've found how this can be done from within the module , but I would like to know if it possible to do it from the server.
Here is the small version of this app with what I've tried:
## global ----
library(shiny)
library(shinydashboard)
library(shinyBS)
library(shinyjs)
find_file_flex <- function(dir, extension, name_pattern, temp.rm=FALSE) {
files <- list.files(dir, pattern = name_pattern)
exts <- stringr::str_sub(files, -nchar(extension))
files <- files[exts == extension]
if(temp.rm) {
temp <- stringr::str_detect(files, pattern = "^([~][$])")
files <- files[!temp]
}
if (length(files) == 1){
file.path(dir, files)
} else if (length(files) > 1) {
date <- gsub(pattern = "-", replacement = "", basename(dir))
time_start <- unlist(gregexpr(pattern = date, files))
times <- stringr::str_sub(files, time_start, time_start + 13)
file.path(dir, files[times == max(times)])
} else { NA }
}
## dir_files ----
dir_files <- list(
file1 = list(
name_pattern = "-name_pattern1",
extension = ".txt",
sep = ";",
dec = ".",
label = "File1"
),
file2 = list(
name_pattern = "-name_pattern2",
extension = ".txt",
sep = ";",
dec = ".",
label = "File2"
)
)
## files_ui ----
files_ui <- tagList(
file1 = list(
button_icon = icon("download"),
info_modal_content = div("1. Much info! Such knowledge!")
),
file2 = list(
button_icon = icon("refresh"),
info_modal_content = div("2. Much info! Such knowledge!")
)
)
## chores_info ----
chores_info <- list(
home = list(
label = "Homez!",
input = c("file1","file2"),
output = "file2"
)
)
## modules ----
tr_fileOutput <- function(id) {
ns <- NS(id)
tagList(
tagList(
tags$tr(
# id = ns("tr"),
tags$td(uiOutput(ns("info_actionLink")), colspan = "1"),
tags$td(uiOutput(ns("labelLink")), colspan = "7"),
tags$td(uiOutput(ns("button")), colspan = "1")
),
tags$tr(
tags$td(uiOutput(ns("warn")), colspan = "10")
)
),
uiOutput(ns("info_modal"))
)
}
tr_file <- function(input, output, session, file, path) {
ns <- session$ns
file_path <- reactive({
invalidateLater(2000, session)
obj <- dir_files[[file]]
if(is.null(obj$dir)) obj$dir <- path()
find_file_flex(obj$dir, obj$extension, obj$name_pattern, temp.rm = TRUE)
})
output$info_actionLink <- renderUI({
actionLink(ns("info_actionLink"), label = NULL, icon = icon("info-circle"))
})
output$labelLink <- renderUI({
label <- dir_files[[file]]$label
if(is.na(file_path())) return(label)
actionLink(ns("labelLink"), label = label)
})
output$button <- renderUI({
icon <- files_ui[[file]]$button_icon
if(is.null(icon)) return(NULL)
bsButton(ns("button"), label = NULL, icon = icon,
size = "extra-small", class = "bvmf-blue")
})
output$info_modal <- renderUI({
content <- files_ui[[file]]$info_modal_content
title <- dir_files[[file]]$name_pattern
title <- div("Give me the Info ", tags$small(span("(", title, ")")))
bsModal(ns("info_modal"), title = title, trigger = NULL, content)
})
# trigger info_modal
observeEvent(input[["info_actionLink"]],
toggleModal(session, "info_modal", toggle = "open"))
# hyperlink para o labelLink
observeEvent(input[["labelLink"]], shell.exec(file_path()))
}
table_filesOutput <- function(id) {
ns <- NS(id)
tagList(
uiOutput(ns("info_modal")),
htmlOutput(ns("table"))
)
}
table_files <- function(input, output, session, files, path) {
ns <- session$ns
observe({
lapply(files, function(file) {
callModule(module = tr_file, id = file,
file = file, path = path)
})
})
output$table <- renderUI({
x <- lapply(files, function(file) tr_fileOutput(ns(file))[1] )
tags$table(x, id = ns("table"), style = "width: 100%;")
})
output$info_modal <- renderUI({
lapply(files, function(file) tr_fileOutput(ns(file))[2] )
})
}
## ui ----
ui <- dashboardPage(
skin = "blue",
dashboardHeader(
title = format(Sys.Date(), "%d/%m/%Y")
),
dashboardSidebar(
sidebarMenu(
id = "sidebarMenu",
menuItem("Home", tabName = "home", icon = icon("home"))
)
),
dashboardBody(
id = "dashboardBody",
useShinyjs(),
tabItems(
tabItem(
tabName = "home",
column(
width = 3,
wellPanel(
table_filesOutput("home-input")
),
wellPanel(
table_filesOutput("home-output")
)
)
)
)
)
)
## server ----
server <- shinyServer(function(input, output, session) {
date <- reactive({ Sys.Date() })
dir_date <- reactive({ getwd() })
callModule(table_files, "home-input",
files = chores_info[["home"]]$input, path = dir_date)
callModule(table_files, "home-output",
files = chores_info[["home"]]$output, path = dir_date)
observe({
# not sure why this is not hiding the button :(
hide("home-input-file2-button")
})
# code to deal with buttons and such
session$onSessionEnded(stopApp)
})
## ----
shinyApp(ui = ui, server = server)