ive something pretty weird and I don't know how to get my head around.
I just want to make an leaflet app accessible via shiny apps. It uses mapbox as a basemap.
No matter how I turn it, I get an error and the app crashes. This happens most of the time as soon as two users want to use the app. The logs confuse me.
I need some assistance on how to deploy and store tokens on shinyapp, especially the mapbox one and making it accessible for two instances. I have google API Tokens inside and they work without any problems.
On my computer the script works nicely.
If I Do
mb_access_token("MAPBOX_TOKEN", install = TRUE)
readRenviron("~/.Renviron")
I get an app shutdown with the logs
Warning: Error in : A MAPBOX_PUBLIC_TOKEN already exists. You can overwrite it with the argument overwrite=TRUE
when I change my code to overwrite = TRUE instead, I get the Error
Error: Mapbox Token already exists
The whole code is shown here:
library(leaflet)
library(mapboxapi)
library(mapview)
library(shiny)
library(shinydashboard)
library(remotes)
library(dplyr)
library(googleway)
library(tidyverse)
library(pagedown)
dashboard <- dashboardPage(
skin = "black",
dashboardHeader(title = "Analytics Tool"),
dashboardSidebar(
sidebarMenu(
menuItem("Kartengrundlage", tabName = "kgl"),
menuItem("Erreichbarkeit", tabName = "iso")
)
),
dashboardBody(
tags$style(type = "text/css", "#map {height: calc(100vh - 80px) !important;}"),
tabItems(
# First tab content
tabItem(tabName = "kgl",
fluidRow(box(width = 12, textInput("ort", "Ort", "TurmstraBe 20, 10551"))),
fluidRow(box(width = 12, height = 780, solidHeader = TRUE, leaflet::leafletOutput(outputId = "mymap", height = 720), title = "Map"),
fluidRow(box(width = 12, solidHeader = TRUE, title = downloadButton("exportmaphtml","Export as HTML"),downloadButton("exportmappdf","Export as pdf"), downloadButton("exportmappng","Export as jpeg"))
))),
# Second tab content
tabItem(tabName = "iso",
fluidRow(
))
))
)
db_server <- function(input, output,session) {
output$exportmappdf <- downloadHandler(
filename = "map.pdf",
content = function(file) {
mapshot(map$dat, url = "/map.html", remove_controls = c("zoomControl", "layersControl", "homeButton", "scaleBar",
"drawToolbar", "easyButton", "control"))
chrome_print("map.html", output = "map.pdf" )
file.copy("map.pdf", file)
}
)
output$exportmaphtml <- downloadHandler(
filename = "map.html",
content = function(file) {
mapshot(map$dat, url = paste0(getwd(), "/map.html"), remove_controls = c("zoomControl", "layersControl", "homeButton", "scaleBar",
"drawToolbar", "easyButton", "control"))
file.copy(paste0(getwd(), "/map.html"), file)
}
)
output$exportmappng <- downloadHandler(
filename = "map.png",
content = function(file) {
mapshot(map$dat, url = "map.html", remove_controls = c("zoomControl", "layersControl", "homeButton", "scaleBar",
"drawToolbar", "easyButton", "control"))
chrome_print("map.html", output = "map.png", format = "png")
file.copy(paste0(getwd(), "/map.png"), file)
}
)
Ort_geocode <- reactive({
Places <-
google_geocode(
address = input$ort, #'TurmstraBe 20, 10551',#
simplify = TRUE,
set_key("GOOGLE_KEY"))
keeps2 <- c("geometry", "formatted_address", "place_id")
Location_Clean = Places$results[keeps2]
Location_Clean_2 <- Location_Clean %>%
unnest(geometry) %>%
unnest(location) %>%
subset(select = c("lat", "lng"))
return(Location_Clean_2)
})
set_key( "GOOGLE_KEY" )
mb_access_token("MAPBOX_TOKEN", install = TRUE)
readRenviron("~/.Renviron")
map <- reactiveValues(dat = 0)
output$mymap <- renderLeaflet({
map$dat <-leaflet(Ort_geocode()) %>%
setView(Ort_geocode()$lng, Ort_geocode()$lat, zoom = 12) %>%
addMapboxTiles(style_id = "xyz",
username = "xyz") %>%
addMarkers(lat= Ort_geocode()$lat, lng= Ort_geocode()$lng, group = "Standort") %>%
addLayersControl(
overlayGroups = c("Standort"),
options = layersControlOptions(collapsed = TRUE))
})
}
shinyApp (ui = dashboard , server = db_server)
Best regards,
Sebastian
Related
Simply put, I'd like my app to allow the user to filter images with certain characteristics and consequently allow them to download the selected images into a zip file. The images are stored locally.
I've been able to add the images as thumbnails and allow the user to download the data associated with it (as a .csv) but not the actual images.
Here's what I have:
df <- read.csv("./imagedata.csv")
thumbnails <- list.files(path = "./localstore/", pattern = NULL, all.files = FALSE,
full.names = F, recursive = FALSE,
ignore.case = FALSE, include.dirs = FALSE, no.. = FALSE)
thumbnail_path = "./localstore/"
#----------------------------------Process Thumbnnail----------------------------------#
steps <- 0
out <- vector(mode = "list", length = nrow(df))
for (i in df$Thumbnail) {
out[i] <- knitr::image_uri(i)
steps <- steps + 1
}
print(steps)
ProcessedIcon <- as.data.frame(unlist(out))
Icon <- paste("<img src=", ProcessedIcon$`unlist(out)` ,"></img>", sep = "")
df_Icon <- cbind(df, Icon)
#--------------------------------------- UI ---------------------------------------#
ui <- dashboardPage(
skin = "green",
dashboardHeader(title = span(img(src = "logo.png", height = 35), img(src = "logo2.png", height = 35))),
dashboardSidebar(
sidebarMenu(
menuItem("Item Category", tabName = "category", icon = icon("file"),
selectInput(inputId = "ItemCategory",
label = "",
choices = unique(df$ItemCategory),
selected = unique(df$ItemCategory),
multiple = TRUE,
selectize = TRUE,
width = NULL,
size = NULL)
),
menuItem("Item Sub-category", tabName = "subcategory", icon = icon("copy"),
selectInput(inputId = "ItemSubCategory",
label = "",
choices = unique(df$SubCategory),
selected = unique(df$SubCategory),
multiple = TRUE,
selectize = TRUE,
width = NULL,
size = NULL)
),
br(),
br(),
column(11, align = "center",
downloadButton("downloadData", "Download Data"), class = "butt"),
tags$head(tags$style(".butt{font:black;}")),
br(),
br(),
column(11, align = "center",
downloadButton("downloadImages", "Download Images"), class = "butt"),
tags$head(tags$style(".butt{font:black;}"))
)
),
dashboardBody(
DT::dataTableOutput('dftable'),
)
)
#--------------------------------------- Server ---------------------------------------#
server <- function(input, output) {
#------------------------------------Download table-------------------------------#
Info_Database <- reactive ({
df %>%
filter(ItemCategory %in% c(input$ItemCategory)) %>%
filter(SubCategory %in% c(input$ItemSubCategory)) %>%
select(-Thumbnail)
})
#------------------------------------Display table-------------------------------#
table <- reactive ({
df_Icon %>%
select(Icon, ItemCategory, SubCategory, QualityOfImage, Recognisability)%>%
filter(ItemCategory %in% c(input$ItemCategory)) %>%
filter(SubCategory %in% c(input$ItemSubCategory)) %>%
})
output$dftable <- DT::renderDataTable({
DT::datatable(table(), escape = FALSE, options = list(scrollX = TRUE))
})
# download handler- Database
output$downloadData <- downloadHandler(
filename = function() {
paste('ImageDatabase_', Sys.Date(), '.csv', sep='')
},
content = function(con) {
write.csv(Info_Database(), con)
}
)
# here's where I'm totally lost
# download handler- Images
#output$downloadImages <- downloadHandler(
#)
}
imagedata.csv should look like:
ItemCategory
SubCategory
QualityOfImage
Recognisability
Animal
Cat
5
4
Animal
Dog
4
3
Food
Banana
3
4
Objects
House
5
5
Display table should look like:
Icon
ItemCategory
SubCategory
QualityOfImage
Recognisability
Animal
Cat
5
4
Animal
Dog
4
3
Food
Banana
3
4
Objects
House
5
5
First things first
A reprex would tremendously increase your chances of getting an answer, because nobody wants first to re-create your data structure first to be able to help you.
Aproach
I would follow a slightly different approach. Rather than encoding the pictures, I would use an <img> tag to include them.
Setup
N.B. All My SO answers are sitting in Project Root - this is not important for this solution, but necessary to re-run the example. Pics are taken from your example.
Project Root
|- .Rproj
|- Download
|- app.R
|- www
|- pic-1.jpg
|- pic-2.png
|- pic-3.png
|- pic-4.jpg
app.R
library(shiny)
library(tibble)
library(DT)
library(dplyr)
library(here)
library(purrr)
all_pics <- list.files(here("Download", "www"), pattern = "\\.jpg$|\\.png$")
my_data <- tibble(Icon = all_pics,
ItemCategory = c("Animal", "Objects", "Objects", "Animal"),
SubCategory = c("Cat", "Banana", "House", "Dog"))
ui <- fluidPage(
titlePanel("Download Pics and Table"),
sidebarPanel(
selectInput("category", "Category:",
c("All", my_data %>% pull(ItemCategory)),
"All"),
downloadButton("dwnld_data", "Download Data"),
downloadButton("dwnld_pics", "Download Pictures")
),
mainPanel(
DTOutput("tbl")
)
)
server <- function(input, output, session){
get_data <- reactive({
my_data %>%
filter(input$category == "All" |
ItemCategory == input$category) %>%
mutate(IconPath = map_chr(Icon, ~ as.character(img(src = .x,
height = "50px",
width = "50px"))))
})
output$tbl <- renderDataTable({
datatable(
get_data() %>%
select(Icon = IconPath, Category = ItemCategory,
"Sub Category" = SubCategory),
escape = FALSE
)
})
output$dwnld_data <- downloadHandler(
filename = function() {
paste0("data-", Sys.Date(), ".csv")
},
content = function(file) {
write.csv(get_data() %>%
select(Icon, Category = ItemCategory,
"Sub Category" = SubCategory), file,
row.names = FALSE)
}
)
output$dwnld_pics <- downloadHandler(
filename = function() {
paste0("pics-", Sys.Date(), ".zip")
},
content = function(file) {
fns <- get_data() %>%
pull(Icon)
zip(file,
file.path(here("Download", "www"), fns),
flags = "-r9Xj")
}
)
}
shinyApp(ui, server)
Explanation
All pics are in the www folder, from where shiny can add them to the page via the <img> tag.
In my my_data reactive, I filter the data according to the selections and add a string representation of the <img> tag, where I set height and width for the thumbnail sized pictures.
In renderDatatable I use escape = FALSE to not escape the HTML code and to render the picture.
Then the downloadHandler is rather straight forward, loop through all selected files and add them to a zip.
N.B. Theoretically you could also stay with your URI encoding strategy if you must. Your downloadHandler would become a bit more complicated in this case then however. You would first need to decode the encoded image string, store it to a temporary file and add this temporary file to the zip. Unless there are good reasons to go for this approach, I would not add this layer of complication.
library(needs)
needs(
shiny,
ggplot2,
tidyverse,
shinydashboard,
DT
)
source("~/functions.R",local = T)
# Define UI for application that draws a histogram
header = dashboardHeader(
# tags$li(class = "dropdown",
# tags$style(".main-header {max-height: 80px}"),
# tags$style(".main-header .logo {height: 80px}")),
#title = tags$img(src='logo.png',height='100',width='200')
)
sidebar = dashboardSidebar(
menuItem("Full data",tabName="Data",icon=icon("table"),startExpanded = F,
fileInput("file","Upload CSV files",multiple=TRUE,accept=("text/comma"))),
menuItem(text = 'Simulate',tabName = 'simulate',icon=icon('chart-line'),
helpText('Simulation Parameters'),
radioButtons('type',"Please choose the type of analysis:",choices = list("Gender" = 1,"US Minority Status" = 2),selected = 1),
sliderInput("numSims","Number of simulations:",min = 1, max = 10000,step = 1000,value = 10000),
sliderInput("numYears","Number of years to simulate:",min = 1,max = 5,value = 3,step = 1),
numericInput('turnover','Total Turnover', value = 10),
sliderInput('promoRate','Set Promo rate', value = 25, min = 1, max = 100, step = 5),
sliderInput('growthRate','Set growth rate',value = 0,min=0,max=100,step = 1),
helpText('0% Growth Rate assumes a flat, constant headcount'),
actionButton('go',label = "Update"),width = 4)
)
body <- dashboardBody(
tabItems(
tabItem(
tabName = 'data',
fluidRow(wellPanel(
fileInput(
inputId = 'file',
label = "File Upload:",
accept = c("csv", ".csv")))),
wellPanel(DT::dataTableOutput('table'))),
tabItem(
tabName = 'simulate',
fluidRow(
wellPanel(
DT:::dataTableOutput('simDataTable')
))
)
))
ui = shinydashboard::dashboardPage(header,sidebar,body,skin='red')
server = server <- function(input, output) {
options(shiny.maxRequestSize = 30 * 1024 ^ 2)
dataset <- reactive({
req(input$file)
read.csv(input$file$datapath)
})
output$table = renderDataTable(dataset(), filter = 'top',options = list(scrollX = TRUE))
simulate = eventReactive(input$go,{
req(input$numSims,input$type)
x = dataset()
temp = dataSim(x,type=input$type,
numSims = input$numSims)
})
simulateAvg = reactive({
x = simulate()
y = x %>% group_by(Role) %>% summarise(mean(freq))
})
output$simDataTable = renderDataTable(simulateAvg())
}
shinyApp(ui,server)
I'm having some trouble with two issues.
1.) The formatting of the shiny dashboard is odd. The text on the side bar seems very compacted and not what other shiny dashboards look like. I'm not sure what the issue is.
2.) After upload, a table is suppose to appear on the dashboard body but it doesn't
3.) Once a table appears and I head to the simulate tab, will the dashboard body change accordingly and display the simulateAvgData set that I populated?
The dataSim function is from the source file on top. I don't receive any errors when I run anything so looking for guidance and inputs to whether or not this shiny dashboard work as intended. I'm newer to the dashboard packages from shiny.
You have a couple of issues here. You do not need a fileInput statement inside dashboardBody. Next, within dashboardSidebar, you can define fileInput at the top level of menuItem (option 1 in the code below), or a sub-level of the first menuItem (option 2 below). In either case, you need to have a menuItem with a tabName where you want to display the file that was read in. Once you read the input file, you need to select the appropriate tab to see the displayed data. Try this code
header <- dashboardHeader()
### option 1: fileInput at the first menuItem level
# sidebar <- dashboardSidebar(width=320,
# menuItem("Full data",tabName="Data",icon=icon("table"),startExpanded = F),
# fileInput("file","Upload CSV files",multiple=FALSE,accept=c("csv", ".csv"))
# )
### option 2 - fileInput as a subitem
sidebar <- dashboardSidebar(width=320,
menuItem("Full data",tabName="noData",icon=icon("table"),startExpanded = F, ## data not displayed for this tabName
menuItem("Full_data",tabName="Data", icon=icon("table")),
fileInput("file","Upload CSV files",multiple=FALSE,accept=c("csv", ".csv")))
)
body <- dashboardBody(
tabItems(
tabItem(
tabName = 'Data',
fluidRow(DTOutput('table')))
))
ui <- shinydashboard::dashboardPage(header,sidebar,body,skin='red')
server <- function(input, output, session) {
data1 <- reactive({
req(input$file)
data <- read.csv(input$file$datapath,sep = ",", header = TRUE)
})
output$table <- renderDT(data1())
}
shinyApp(ui,server)
Thanks for taking your valuable time to pitch in into this question. :-)
I'm building a shiny app that would take user inputs through rhandsontable and save it as a .rds file for data persistence.
The code is as follows:
Global.r
library(shiny)
library(shinydashboard)
library(shinycssloaders
library(rhandsontable)
library(htmltools)
library(plotly)
library(shinyjs)
library(tidyverse)
library(DT)
# Reads the data stored already
raw_data_projects <- readRDS("Projects.rds")
# code to refresh app so as to display the newly added data
jsResetCode <- "shinyjs.reset = function() {history.go(0)}"
ui.R
dashboardPage(skin = "black",
dashboardHeader(dropdownMenuOutput("dropdownmenu"),title = "PMO Dashboard",
tags$li(div(img(src = 'TechM_logo.png',
height = "35px"),
style = "padding-top:10px; padding-bottom:10px;"),
class = "dropdown"),dropdownMenuOutput("msgOutput")) ,
dashboardSidebar(
sidebarMenu(
menuItem("Home", tabName = "home", icon = icon("home")),
menuItem("Projects", tabName = "pros", icon = icon("briefcase")),
menuItem("About Team", tabName = "teamstr", icon = icon("user-friends")),
menuItem("Training & Skills",tabName = "skills",icon = icon("book"))
)),
dashboardBody(
useShinyjs(), # Include shinyjs in the UI
extendShinyjs(text = jsResetCode),
tags$link(rel = "stylesheet", type = "text/css", href = "style_2.css"),
tabItems(
tabItem(tabName = "pros",
fluidPage(tabBox(width = "500px",
tabPanel("Metrics",
fluidRow(
valueBoxOutput("Completed", width = 3),
valueBoxOutput("WIP", width = 3),
valueBoxOutput("Delayed", width = 3),
valueBoxOutput("OnHold", width = 3)
),
fluidRow(
box(plotlyOutput("Project_category"), width = 4,solidHeader = TRUE, status = "primary", title = "Project Category", collapsible = TRUE),
box(plotlyOutput("Project_status"), width = 8,solidHeader = TRUE, status = "primary", title = "Project Status", collapsible = TRUE),
box(plotlyOutput("Complexity"), width = 4,solidHeader = TRUE, status = "primary", title = "Project Complexity", collapsible = TRUE),
box(plotlyOutput("Audits"), width = 4,solidHeader = TRUE, status = "primary", title = "Audit Status", collapsible = TRUE)
)),
tabPanel("Data",
box(withSpinner(rHandsontableOutput("Projects")), width = 12),
actionButton("saveBtnProjects", "Save Projects", icon = icon("save")),
actionButton("BtnResetProjects", "Reset Filters", icon = icon("eraser")))))
)))
server.r
shinyServer(function(input, output, session){
dt_projects <- reactive({ raw_data_projects })
vals <- reactiveValues()
output$Projects <- renderRHandsontable({
rhandsontable(dt_projects(), readOnly = FALSE, search = TRUE, selectCallback = TRUE ) %>%
hot_cols(columnSorting = TRUE, manualColumnMove = TRUE, manualColumnResize = TRUE ) %>%
hot_table(highlightRow = TRUE, highlightCol = TRUE) %>%
#hot_col("PROJECT.STATUS", renderer = text_renderer, type = "autocomplete") %>%
hot_rows(fixedRowsTop = 1)
})
# on click of button the file will be saved to the working directory
observeEvent(input$saveBtnProjects,
#write.csv(hot_to_r(input$Projects), file = "./Data/project_tracker.csv",row.names = FALSE)
saveRDS(hot_to_r(input$Projects),"Projects.rds")
)
# refresh the page
observeEvent(input$saveBtnProjects, {js$reset()})
})
So when I run the app I get the table I desire as below:
As we can see, as I was inserting values to the first column, all the other columns greyed out and I couldn't insert any values into it. Please help me with this issue.
Also please suggest if my code will display the data reactively as soon as I save the data by pressing Save Projects button.
Thanks a ton in advance!!
P.S : I have included the server code only for the table considering the length of the question leaving the code of other tabs. But still this code is reproducible.
I am working on an app where the user can upload either one file or multiple files of individual-level data to get analyzed.
So far if the user uploads multiple files the app combines all the files in one dataset and analyzes all of them combined. I have different outputs 2 tables and a graph.
What I am struggling to do is when the user uploads multiple files I want to keep the compiled result but I want to add dynamic tabs to each box according to the number of files uploaded to present the table/graph for that file alone.
I added a checkbox so the user checks it if they are uploading multiple files. The idea was to write an observeEvent code to insert tabs according to the number of files being uploaded, that code got complicated because I had to put the renderTable chunk within it, and it is not working.
So my question is, is there a better way of doing what I am trying to do? and If my idea makes sense what is wrong with my code and why isn't it working? Thank you
Here is a sample of the code;
library(shiny)
library(dplyr)
library(shinydashboard)
library(tidyr)
library(shinyjs)
ui <- dashboardPage(
dashboardHeader(title = "Treatment and Care Cascade",
titleWidth = 300),
#Sidebar contents (tabs)
dashboardSidebar(
sidebarMenu(
menuItem("HIV Cascade", tabName = "hiv")
)),
#Main panel for displaying outputs
dashboardBody(
tabItems(
#First tab content
tabItem(tabName = "hiv",
h2("HIV Treatment and Care Cascade"),
fluidRow(
#Input: Select a file for hcv data
box(fluidRow(
box(fileInput("dt_hiv","Choose CSV File",
multiple = TRUE,
accept = c("text/csv",
"text/comma-separated-values,tesxt/plain",".csv")),width = 12,solidHeader = TRUE, height = 75),
#Input: Checkbox if file has header
box(checkboxInput("multiplehiv", "Uploading multiple files",TRUE),width = 3,solidHeader = TRUE, height = 50)), width = 12, height = 255),
#Outputs
tabBox(id = "hivcasbox", tabPanel(id = "tab1", title ="HIV Cascade",tableOutput("hivcascade"))),
box(tableOutput("hivCascadeduration"), title = "HIV Cascade - duration", solidHeader = TRUE)
))
)))
server <- function(input, output){
#Combining the datasets together
dthiv <- reactive({req(input$dt_hiv)
rbindlist(lapply(input$dt_hiv$datapath, fread, header = input$hivheader, quote = input$hivquote, sep = input$hivsep),
use.names = TRUE, fill = TRUE)
})
#The analysis chunk
cascade_hiv <- reactive({dthiv() %>% summarize("Diagnosed" = sum(hiv_posresult,na.rm = T),
"Linkage to care" = sum(linkagetocare_hiv,na.rm = T))})
cascade_hiv1 <- reactive({as.data.frame(t(cascade_hiv()))})
Percentage <- reactive({(round((cascade_hiv1()$V1*100/cascade_hiv1()$V1[1]),1))})
cascade_hiv3 <- reactive({cbind(cascade_hiv1(),Percentage())})
cascade_hiv4 <- reactive({cascade_hiv3() %>% rename(Total = V1, Percentage = "Percentage()")})
output$hivcascade <- renderTable({
cascade_hiv5 <- as.data.frame(cascade_hiv4())
rownames(cascade_hiv5) <- c("Diagnosed","Linkage to care")
cascade_hiv5},include.rownames = TRUE)
observeEvent(input$multiplehiv, {
for (i in 1:length(input$dt_hiv$datapath)) {
insertTab(inputId = "hivcasbox",
tabPanel(paste("Region",i), renderTable({
dthiv_r <- input$dt_hiv$datapath[i] %>% summarize("Diagnosed" = sum(hiv_posresult,na.rm = T),
"Linkage to care" = sum(linkagetocare_hiv,na.rm = T))
cascade_hiv1_r <- as.data.frame(t(dthiv_r))
Percentage_r <- round((cascade_hiv1_r$V1*100/cascade_hiv1_r$V1[1]),1)
cascade_hiv3_r <- cbind(cascade_hiv1_r,Percentage_r)
cascade_hiv4_r <- cascade_hiv3_r %>% rename(Total = V1, Percentage = "Percentage_r")
cascade_hiv5_r <- as.data.frame(cascade_hiv4_r)
rownames(cascade_hiv5_r) <- c("Diagnosed","Linkage to care")
cascade_hiv5_r},include.rownames = FALSE)),
target = "tab1")
}
})
}
shinyApp(ui, server)
Created on 2019-08-01 by the reprex package (v0.3.0)
the app runs but when I check the multiple files box, no tabs get inserted
I couldn't get the above code to work but I found another one that works using "str and eval(parse(text = str))",
however, it is not the most elegant or concise code, so I would appreciate it if someone has a better way of doing it. Thank you!
ibrary(shiny)
library(dplyr)
library(shinydashboard)
library(tidyr)
library(shinyjs)
library(data.table)
ui <- dashboardPage(
dashboardHeader(title = "Treatment and Care Cascade",
titleWidth = 300),
dashboardSidebar(
sidebarMenu(
menuItem("HIV Cascade", tabName = "hiv")
)),
dashboardBody(
tabItems(
#First tab content
tabItem(tabName = "hiv",
h2("HIV Treatment and Care Cascade"),
fluidRow(
#Input: Select a file for hcv data
box(fluidRow(
box(fileInput("dt_hiv","Choose CSV File",
multiple = TRUE,
accept = c("text/csv",
"text/comma-separated-values,tesxt/plain", ".csv")),width = 12,solidHeader = TRUE, height = 75),
#actionButton("multiplehiv", "Add 'Dynamic' tab"),
#Input: Checkbox if file has header
box(checkboxInput("multiplehiv", "Uploading multiple files",FALSE),
width = 3,solidHeader = TRUE, height = 50)
), width = 12, height = 255),
#Outputs
uiOutput("tabs")
))
)))
server <- function(input, output){
dthiv <- reactive({req(input$dt_hiv)
rbindlist(lapply(input$dt_hiv$datapath, fread),
use.names = TRUE, fill = TRUE)
})
cascade_hiv <- reactive({dthiv() %>% summarize("Diagnosed" = sum(hiv_posresult,na.rm = T),
"Linkage to care" = sum(linkagetocare_hiv,na.rm = T))})
cascade_hiv1 <- reactive({as.data.frame(t(cascade_hiv()))})
Percentage <- reactive({(round((cascade_hiv1()$V1*100/cascade_hiv1()$V1[1]),1))})
cascade_hiv3 <- reactive({cbind(cascade_hiv1(),Percentage())})
cascade_hiv4 <- reactive({cascade_hiv3() %>% rename(Total = V1, Percentage = "Percentage()")})
n_files <- reactive({length(input$dt_hiv$datapath)})
output$tabs <- renderUI({
if (input$multiplehiv == 1) {
str <- "tabBox(id = 'hivcasbox',
tabPanel(id = 'taball', title = 'HIV Cascade' ,tableOutput('hivcascade')),"
for (i in 1:n_files()) {str <- paste0(str, "tabPanel(id = paste('tab', ",i,") , title = paste('Data', ",i,") , tableOutput('hivcascader_",i,"')),")}
str <- gsub(",$",")",str)
eval(parse(text = str))
}
else {
tabBox(id = "hivcasbox",
tabPanel(id = "tab1", title = "HIV Cascade",tableOutput("hivcascade")))
}
})
output$hivcascade <- renderTable({
cascade_hiv5 <- as.data.frame(cascade_hiv4())
rownames(cascade_hiv5) <- c("Diagnosed","Linkage to care")
cascade_hiv5},include.rownames = TRUE)
dt_files <- reactive({lapply(input$dt_hiv$datapath[1:n_files()],read.csv)})
observe({
for (i in 1:n_files())
{str1 <- paste0("dthiv_r_",i,"<- reactive({dt_files()[[",i,"]] %>% summarize('Diagnosed' = sum(hiv_posresult,na.rm = T),
'Linkage to care' = sum(linkagetocare_hiv,na.rm = T))})
cascade_hiv1_r_",i,"<- reactive({as.data.frame(t(dthiv_r_",i,"()))})
Percentage_r_",i,"<- reactive({round((cascade_hiv1_r_",i,"()$V1*100/cascade_hiv1_r_",i,"()$V1[1]),1)})
cascade_hiv3_r_",i," <- reactive({cbind(cascade_hiv1_r_",i,"(),Percentage_r_",i,"())})
cascade_hiv4_r_",i,"<- reactive({cascade_hiv3_r_",i,"() %>% rename(Total = V1, Percentage = 'Percentage_r_",i,"()')})")
eval(parse(text = str1))}
for (i in 1:n_files()) {
str2 <- paste0("output$hivcascader_",i," <- renderTable({
cascade_hiv5_r_",i," <- as.data.frame(cascade_hiv4_r_",i,"())
rownames(cascade_hiv5_r_",i,") <- c('Diagnosed','Linkage to care')
cascade_hiv5_r_",i,"},include.rownames = TRUE)")
eval(parse(text = str2))}
})
}
shinyApp(ui, server)
I configured my map to fit the size of my internet window. Unfortunately, when I change this size, my map returns to its basic configuration (setView for example), and my shapefile previously imported disappears.
Is there a way to go beyond that?
# server.R
#--------- ADD PACKAGES --------#
library(shiny)
library(shinydashboard)
library(leaflet)
library(rgdal)
library(rgeos)
library(shinyjs)
library(sp)
library(V8)
library(shinyalert)
library(leaflet.extras)
library(raster)
#--------- APPLICATION INSTRUCTIONS --------#
shinyServer(function(input, output, session){
#--------- BOX CONTAINING THE MAP --------#
output$ui <- renderUI( {
req(input$box_height)
box(height = paste0(input$box_height, "px"), width = 9,
leafletOutput("map", height = input$box_height - 20)
)
})
#--------- ADD LEAFLET MAP --------#
output$map <- renderLeaflet({
leaflet() %>%
enableTileCaching() %>%
addProviderTiles("Esri.WorldImagery", group = "Esri World Imagery",
options = providerTileOptions(minZoom = 2, maxZoom = 17),
tileOptions(useCache = TRUE, crossOrigin = TRUE)) %>%
addTiles(group = "OSM", urlTemplate = "https://{s}.tile.openstreetmap.de/tiles/osmde/{z}/{x}/{y}.png",
attribution = '© OpenStreetMap contributors',
options = providerTileOptions(minZoom = 2, maxZoom = 17),
tileOptions(useCache = TRUE, crossOrigin = TRUE)) %>%
addMiniMap(toggleDisplay = T) %>%
addScaleBar(position = 'bottomleft') %>%
setView(lng = 97.963,lat = 20.380, zoom = 6 ) %>%
addLayersControl(baseGroups = c("Esri World Imagery", "OSM"))
})
#-------- READ SHAPEFILE --------#
#-------- SAVE IN TEMP FOLDER --------#
#-------- CREATE A CSV --------#
uploadShpfile <- reactive({
if (!is.null(input$zip)) {
zipFile <- input$zip
zipPath <- substr(zipFile$datapath, 1, nchar(zipFile$datapath) - 5)
unzip(zipFile$datapath, exdir = zipPath)
pwd <- getwd()
updir <- dirname(zipFile$datapath[1])
setwd(updir)
for (i in 1:nrow(zipFile)) {
file.rename(zipFile$datapath[i], zipFile$name[i])
}
shpName <- zipFile$name[grep(zipFile$name, pattern = "*.shp")]
shpPath <- paste(updir, shpName, sep = "/")
setwd(updir)
Layers <- ogrListLayers(shpPath)
shpName <- readOGR(shpPath)
shpName <- spTransform(shpName,CRS("+proj=longlat +datum=WGS84"))
shapefile(shpName, paste(shpPath, Layers, "_WGS84.shp", sep = ""))
write.table(paste(shpPath, Layers, "_WGS84.shp", sep = ""),
file = "info_shp.csv",
row.names = FALSE,
col.names = FALSE,
quote = FALSE)
shpName
}
})
#-------- ADD SHAPEFILE --------#
observeEvent(input$zip, {
data = uploadShpfile()
map = leafletProxy("map")
if (!is.null(uploadShpfile())){
if(inherits(data, "SpatialPolygons")){
shinyalert("Successful upload !", type = "info", timer = 2000)
cent <- gCentroid(spgeom = uploadShpfile(), byid = FALSE)
leafletProxy("map")%>%
addPolygons(data = uploadShpfile(),
stroke = TRUE,
# color = "#00FFEC",
# fillColor = "white",
fillOpacity = 0.5)
}
if(inherits(data, "SpatialPoints")){
shinyalert("Successful upload !", type = "info")
cent <- gCentroid(spgeom = uploadShpfile(), byid = FALSE)
leafletProxy("map") %>%
addCircleMarkers(data = uploadShpfile(),
stroke = TRUE,
# color = "white",
# fillColor = "#00FFEC",
radius = 6,
fillOpacity = 0.9)
}
}
})
})
# ui.R
#--------- ADD PACKAGES --------#
library(shiny)
library(shinydashboard)
library(leaflet)
library(rgdal)
library(rgeos)
library(shinyjs)
library(sp)
library(V8)
library(shinyalert)
library(leaflet.extras)
library(raster)
#--------- USER INTERFACE --------#
shinyUI(
dashboardPage(
dashboardHeader(title ="Sen2extract"),
#--------- SIDEBAR CONFIGURATION --------#
sidebar <- dashboardSidebar(
sidebarMenu(
menuItem("Map", tabName= "carte", icon = icon("globe")),
),
#--------- ELEMENTS OF THE BODY --------#
dashboardBody(
#--------- CONFIGURE THE HEIGHT --------#
tags$head(tags$script('
// Set input$box_height when the connection is established
$(document).on("shiny:connected", function(event) {
var window_height = $(window).height();
var header_height = $(".main-header").height();
var boxHeight = window_height - header_height - 30;
Shiny.onInputChange("box_height", boxHeight);
});
// Refresh the box height on every window resize event
$(window).on("resize", function(){
var window_height = $(this).height();
var header_height = $(".main-header").height();
var boxHeight = window_height - header_height - 30;
Shiny.onInputChange("box_height", boxHeight);
});
')),
# Boxes need to be put in a row (or column)
tabItems(
#--------- ELEMENTS TAB "carte" --------#
tabItem(tabName ="carte",
fluidRow(
box(
width = 3,
title = "Settings",
status = "primary",
solidHeader = TRUE,
collapsible = TRUE,
useShinyalert(),br(),
fileInput(inputId = "zip", label = "Upload your file (.zip) :", multiple = FALSE, accept = c('.zip')),
checkboxGroupInput(inputId ="indice", label ="Choose a spectral index (multiple choice possible) :", choices = c("NDVI", "NDWIGAO", "NDWIMCF", "MNDWI")),br(),
dateRangeInput(inputId ="dates", label = "Select the date range :", start = "", end = ""), br(),
textInput(inputId = "mail", label = "Enter your email address :"), br(),br(),
shinyjs::useShinyjs(),
shinyjs::extendShinyjs(text = "shinyjs.reset = function() {window.location.reload(true)}"),
div(style = "display:inline-block", actionButton("reset_button", "Refresh", icon("refresh", lib ="glyphicon"))),
div(style = "display:inline-block", actionButton("send", "Send now !", icon("send", lib = "glyphicon"), style = "background-color : #000000 ; color : #fff ; border-color : #717878"))
),
uiOutput("ui", width = "100%")
)
)
)
)
)
On the first image, I imported a shapefile. If I change the size of the window (2nd image), the shapefile is no longer displayed (but we see it in the inputfile) and my map has returned to its original SetView.