Related
I have a shiny app below that shows a file content from a server-side sqlite file
I want to overwrite the sqlite every week on my shiny server from a csv upload and filter it through the App
When I update the sqlite file from within the shiny ran in RStudio I get new content OK and am able to work with it and upload multiple new content as expected
When I run the same app on the shiny server in my browser, I get disconnected from the server as soon as I click on the 'Upload' button after uploading the new csv with 'Browse' (which succeeds).
Can someone please explain this behaviour
I suspect something off in :
observeEvent(input$Upload, {
if(is.null(input$Browse))
{
return(NULL)
}
else
{
file <- input$Browse
createDB(file$datapath, basename(file$name), dbfile)
shinyalert(paste(basename(file$name), "database uploaded, please refresh the session", sep=" "), type = "success", timer=2000)
}
})
REM: it is not the shinyalert though
my full App code :
# accounts.shinyapp
# R/shiny tool to filter the weekly accounts_filtered.csv
library("shiny")
library("shinyBS")
library("shinyalert")
library("RSQLite")
library("DT")
# you may un-comment the next line to allow 10MB input files
options(shiny.maxRequestSize=10*1024^2)
# the following test checks if we are running on shinnyapps.io to limit file size dynamically
# ref: https://stackoverflow.com/questions/31423144/how-to-know-if-the-app-is-running-at-local-or-on-server-r-shiny/31425801#31425801
#if ( Sys.getenv('SHINY_PORT') == "" ) { options(shiny.maxRequestSize=1000*1024^2) }
# App defaults
app.name <- "accounts"
script.version <- "1.0b"
version <- "NA"
names <- c("Last","First","Email","Phone","Level","DeptNum","Code","Short","Logon","Location")
# database functions
createDB <- function(filepath, filename, dbfile){
data <- read_csv(filepath,
locale = locale(encoding = "ISO-8859-2",
asciify = TRUE))
# give proper english names to columns
colnames(data) <- names
data$Email <- tolower(data$Email)
version <- data.frame(version=filename)
# create sqlite and save
mydb <- dbConnect(RSQLite::SQLite(), dbfile)
dbWriteTable(mydb, "data", data, overwrite=TRUE)
dbWriteTable(mydb, "version", version, overwrite=TRUE)
dbDisconnect(mydb)
}
loadDB <- function(dbfile){
mydb <- dbConnect(RSQLite::SQLite(), dbfile)
data <- dbReadTable(mydb, "data")
version <- dbReadTable(mydb, "version")
dbDisconnect(mydb)
# return resulting data.frame
return(list(data = as.data.frame(data), version = as.data.frame(version)))
}
# initial DB creation
# infile <- "Data/ori_accounts_filtered.csv"
# createDB(infile, basename(infile), dbfile)
#############################
# Define UI for application #
#############################
ui <- fluidPage(
useShinyalert(),
HTML('<style type="text/css">
.row-fluid { width: 25%; }
.well { background-color: #99CCFF; }
.shiny-html-output { font-size: 14px; line-height: 15px; }
</style>'),
# Application header
headerPanel("Filter the weekly accounts list"),
# Application title
titlePanel(
windowTitle = "accounts",
tags$a(href="https://http://someIP:8787/accounts", target="_blank",
img(src='logo.png', align = "right",
width="150", height="58.5", alt="myApp"))
),
sidebarLayout(
# show file import weekly update csv data
sidebarPanel(
tags$h5(paste(app.name, " version: ", script.version, sep="")),
tipify(fileInput("Browse",
"Choose new Weekly update:",
accept = ".csv"),
"a accounts_filtered.csv file"),
tipify(actionButton("Upload", "Upload new table"),
"This will replace the current database content!"),
hr(),
checkboxGroupInput("show_vars",
"Check columns to be shown:",
names,
selected = names[c(1:4,6)]),
hr(),
tipify(actionButton("Refresh", "Refresh Session"),
"This will reload the database content!")
),
mainPanel(
htmlOutput("version_tag"),
hr(),
dataTableOutput('dataTable')
)
)
)
#######################
# Define server logic #
#######################
server <- function(input, output, session) {
# initialize content at startup
dbfile <- "Data/data.sqlite"
# load both data and version
mydat <- loadDB(dbfile)
version <- mydat$version[1,1]
accounts <- mydat$data
names <- colnames(accounts)
output$version_tag <- renderText({
paste("<b>Data file: ", version, "</b>")
})
observeEvent(input$Refresh, {
session$reload()
})
observeEvent(input$Upload, {
if(is.null(input$Browse))
{
return(NULL)
}
else
{
file <- input$Browse
createDB(file$datapath, basename(file$name), dbfile)
shinyalert(paste(basename(file$name), "database uploaded, please refresh the session", sep=" "), type = "success", timer=2000)
}
})
output$dataTable <- renderDT(
accounts[,input$show_vars], # data
class = "display nowrap compact", # style
filter = "top", # location of column filters
options = list(pageLength = 20, autoWidth = TRUE),
rownames= FALSE
)
}
# Run the application
shinyApp(ui = ui, server = server)
This is missing.
library("readr")
Ciao,
I have some trouble in changing font color in my flextable.
The R version is 3.5.2
I am working on this object since I have to add the table on a pptx presentation and to do this I will of course use officer package. Let me show you a dummy code and the output:
library(officer)
library(flextable)
ppt <- read_pptx()
ppt <- add_slide( ppt, layout = "Title and Content", master = "Office Theme")
ppt <- ph_with_text(ppt, "Title whatever", type = "title")
df = head(mtcars)
ft = flextable(df)
ft <- bg(ft, i = 1, bg = "#FF0000", part = "body")
ft <- bg(ft, i = 1, bg = "#FF0000", part = "header")
ft <- fontsize(ft, i = 1, size = 15, part = "body")
ft <- fontsize(ft, i = 1, size = 20, part = "header")
ft <- color(ft, i = 1, color = "#FFFFFF", part = "body")
ft <- color(ft, i = 1, color = "white", part = "header")
ft <- font(ft, i = 1, fontname = "Consolas", part = "header")
ft <- autofit(ft)
ppt <- ph_with_flextable(ppt, ft)
if(file.exists("prova.pptx"))
file.remove("prova.pptx")
print(x = ppt, target = "prova.pptx")
As you can see I apply to the table a lot of formatting functions but I've noticed that the only one that fails is the "color" function.
The header and the first line of the table should be white. Notice that I've tried to assign to the "color" parameter both values "white" and "#FFFFFF" but in both case it does not work.
It is even more wierd considering that all other settings have been successfully applied.
What I am missing about color function from flextable package? Have you noticed the same issue (bug) ?
Thanks,
Ciao
AM
I have a data table that contains some very wide columns and I want to add a scrolling-bar to make it more presentable. So far I have found examples using a scrolling-bar for the entire table - but ideally I would like to have a scrolling-bar for EACH column in the table if that is possible. Below there is an illustrating example. In this code I want a scrolling-bar for both "This_is_a_very_long_name_1", "This_is_a_very_long_name_2" etc.
library("shinydashboard")
library("shiny")
body <- dashboardBody(
fluidPage(
column(width = 4,
box(
title = "Box title", width = NULL, status = "primary",
div(style = 'overflow-x: scroll', tableOutput('table'))
)
)
)
)
ui <- dashboardPage(
dashboardHeader(title = "Column layout"),
dashboardSidebar(),
body
)
server <- function(input, output) {
test.table <- data.frame(lapply(1:8, function(x) {1:10}))
names(test.table) <- paste0('This_is_a_very_long_name_', 1:8)
output$table <- renderTable({
test.table
})
}
# Preview the UI in the console
shinyApp(ui = ui, server = server)
I thought about splitting the table into 8 tables, making a scrolling table for each of them and then putting them next to each other, but space was added betweeen them and it did not look that nice. I think it would be preferable to keeping it as one table (but suggestions are very welcome!).
Does anyone whether this is possible - and how to solve it?
Thanks in advance!
I would not recommend scrolling column header, i think it would not be very clear to read it or so. Here is the code which You can use to get the header in 2 lines so the columns are not too wide:
library("shinydashboard")
library("shiny")
library(DT)
test.table <- data.frame(lapply(1:8, function(x) {1:10}))
names(test.table) <- paste0('This_is_a_very_long_name_', 1:8)
body <- dashboardBody(
fluidPage(
column(width = 8,
box(
title = "Box title", width = NULL, status = "primary",
div(style = 'overflow-x: scroll', dataTableOutput('table'))
)
)
)
)
ui <- dashboardPage(
dashboardHeader(title = "Column layout"),
dashboardSidebar(),
body
)
server <- function(input, output) {
output$table <- renderDataTable({
names(test.table) <- gsub("_"," ",names(test.table))
datatable(test.table, options = list(columnDefs = list(list(width = '100px', targets = c(1:8)))))
})
}
# Preview the UI in the console
shinyApp(ui = ui, server = server)
[UPDATE] --> Column text rendering
Here is a one solution which can be usefull for You. There is no scrolling, however Your row text displays only first three characters (the number of characters displayed can be changed) and ..., with mouse over the row You get the pop up with whole variable name in this row:
library("shinydashboard")
library("shiny")
library(DT)
x <- c("aaaaaaaaaaaaaa", "bbbbbbbbbbbb", "ccccccccccc")
y <- c("aaaaaaaaaaaaaa", "bbbbbbbbbbbb", "ccccccccccc")
z <- c(1:3)
data <- data.frame(x,y,z)
body <- dashboardBody(
fluidPage(
column(width = 4,
box(
title = "Box title", width = NULL, status = "primary",
div(style = 'overflow-x: scroll', dataTableOutput('table'))
)
)
)
)
ui <- dashboardPage(
dashboardHeader(title = "Column layout"),
dashboardSidebar(),
body
)
server <- function(input, output) {
output$table <- renderDataTable({
datatable(data, options = list(columnDefs = list(list(
targets = c(1:3),
render = JS(
"function(data, type, row, meta) {",
"return type === 'display' && data.length > 3 ?",
"'<span title=\"' + data + '\">' + data.substr(0, 3) + '...</span>' : data;",
"}")),list(width = '100px', targets = c(1:3)))))
})
}
# Preview the UI in the console
shinyApp(ui = ui, server = server)
I am building a shiny application that renders large number of images in the form of tiles. I want to integrate Lightbox jScript into my application, something similar to the four image set example given. How do i do that.
The data file here.
The styles.css here.
The minimal working codes:
UI:
shinyUI(dashboardPage(skin = "green",
dashboardHeader(title = "MYAPP"),
dashboardSidebar(
useShinyjs(),
includeCSS("www/styles.css"),
includeCSS("www/lightbox.css"),
includeCSS("www/lightbox.min.css"),
includeScript("www/lightbox.js"),
includeScript("www/lightbox.min.js"),
sidebarMenu(id = "tabs",
menuItem("PICTURES & IMAGES", tabName = "imag", icon = shiny::icon("angle-double-right"))
)
),
dashboardBody(
tabItems(
tabItem(
tabName = "imag", h3("PICTURES & IMAGES"),
fluidRow(
uiOutput("picss")
)
)
))
))
The server code:
shinyServer(function(input, output) {
output$picss <- renderUI({
fluidRow(
column(12, id="columns",
lapply(df1$recipe.link, function(i) {
box(width=NULL,
title = HTML(paste0("<div class='image-wrap'>
<img src='./images/",
df1$img[df1$recipe.link == i],"'class=fixed-height'",
df1$img[df1$recipe.link == i],
"'></div>"
))
)}
)))
})
})
The global.R
library(shiny)
library(shinydashboard)
library(shinyjs)
library(base64enc)
df1 <- readRDS("df1.RDS")
filepath <- "www/images/"
dir.create(file.path(filepath), showWarnings = FALSE)
for (i in 1:nrow(df1)){
if(df1[i,"image_path"] == "NULL"){
next
}
testObj <- strsplit(df1[i,"image_path"],",")[[1]][2]
inconn <- testObj
outconn <- file(paste0(filepath,"image_id",df1[i,"id"],".jpg"),"wb")
base64decode(what=inconn, output=outconn)
close(outconn)
}
If you are trying to reproduce the Four image set (in your case three images) this is how I was able to do it.
In the ui.R i have use tagList to include all the necessary components. Note the by Lightbox instructions. Point 3 of getting started lightbox.js should be included at the bottom of the body.
Just be sure to put the correct paths back for inlcudeCSS and includeJS since I have changed them.
ui.R
library(shiny)
shinyUI(tagList(
tags$head(
useShinyjs(),
includeCSS("www/css/styles.css"),
includeCSS("www/css/lightbox.css")
),
dashboardPage(skin = "green",
dashboardHeader(title = "MYAPP"),
dashboardSidebar(
sidebarMenu(id = "tabs",
menuItem("PICTURES & IMAGES", tabName = "imag", icon = shiny::icon("angle-double-right"))
)
),
dashboardBody(
tabItems(
tabItem(
tabName = "imag", h3("PICTURES & IMAGES"),
fluidRow(
uiOutput("picss")
)
)
))
),
includeScript("www/js/lightbox.js")
))
server.R
library(shiny)
shinyServer(function(input, output) {
output$picss <- renderUI({
fluidRow(
column(12, id="columns",
lapply(df1$recipe.link, function(i) {
box(width=NULL,
title = HTML(paste0('<div class="image-wrap"><a href="images/',
df1[df1$recipe.link == i, 6],
'" data-lightbox="image-1" data-title="My caption"><img border="0" alt="" class="fixed-height" src="images/'
,df1[df1$recipe.link == i, 6],'"></a></div>'))
)}
)
))
})
})
global.R is unchanged.
Let me know if this helps.
I have created a progress bar to keep tabs on the execution of some R scripts. And I want to insert a custom icon in the bar instead of the default 'Tk' one. I am able to do this on Windows using a .ico file and the following command
tcl('wm', 'iconbitmap', .win, 'Icon.ico')
But I am a loss about how to do the same in Mac OSX and Linux. Obviously, the .ico format doesn't work but neither does .png, .jpg, .bmp, .xbm or .xpm. Any suggestion on how I could proceed? Sample image and progress bar code attached below:-
Sample image http://tinypic.com/r/jt8efn/6 - http://tinypic.com/r/jt8efn/6
tkProgressBar2 <- function (title = 'Test progress bar', label = '', min = 0, max = 100, initial = 0, width = 300, userfn='helvetica', backg='white') {
useText <- FALSE
have_ttk <- as.character(tcl('info', 'tclversion')) >= '8.5'
if (!have_ttk && as.character(tclRequire('PBar')) == 'FALSE') useText <- TRUE
.win <<- tktoplevel(background=backg)
tkfocus()
tcl('wm', 'geometry', .win, '500x100+450+350')
tcl('wm', 'iconbitmap', .win, '#Icon.xbm')
.val <- initial
.killed <- FALSE
tkwm.geometry(.win, sprintf('%dx80', width + 40))
tkwm.title(.win, title)
fn <- tkfont.create(family = userfn, size = 12)
if (useText) {
.lab <- tklabel(.win, text = label, font = fn, padx = 0, background=backg)
tkpack(.lab, side = 'left')
fn2 <- tkfont.create(family = userfn, size = 16)
.vlab <- tklabel(.win, text = '0%', font = fn2, padx = 20, background=backg)
tkpack(.vlab, side = 'right')
up <- function(value) {
if (!is.finite(value) || value < min || value > max) return()
.val <<- value
tkconfigure(.vlab, text = sprintf('%d%%', round(100 * (value - min)/(max - min))))
}
} else {
.lab <- tklabel(.win, text = label, font = fn, pady = 0, background=backg)
.tkval <- tclVar(0)
tkpack(.lab, side = 'top')
tkpack(tklabel(.win, text = '', font = fn, background=backg), side = 'bottom')
pBar <- if (have_ttk)
ttkprogressbar(.win, length = width, variable = .tkval) else
tkwidget(.win, 'ProgressBar', width = width, variable = .tkval)
tkpack(pBar, side = 'bottom')
up <- function(value) {
if (!is.finite(value) || value < min || value > max) return()
.val <<- value
tclvalue(.tkval) <<- 100 * (value - min)/(max - min)
}
}
getVal <- function() .val
kill <- function() if (!.killed) {
tkdestroy(.win)
.killed <<- TRUE
}
title <- function(title) tkwm.title(.win, title)
lab <- function(label) tkconfigure(.lab, text = label)
tkbind(.win, '<Destroy>', function() stop())
up(initial)
structure(list(getVal = getVal, up = up, title = title, label = lab, kill = kill), class = 'tkProgressBar')
}
pb <- tkProgressBar2(title='Performing k-Means clustering', label='Some information in %', min=0, max=100, initial=0, width=400, userfn='verdana', backg='white')
On Linux you set the icon with wm iconphoto; wm iconbitmap does something else entirely. To do that, you'll need to create a photo image with the image data in it.
I'm guessing that you write this in R as:
tcl('wm', 'iconphoto', .win, tcl('image', 'create', 'photo', '-file', 'Icon.gif'))
I'm not quite sure which image formats are supported by the version of Tk you're using, including any image format support packages it has available. The minimal set is GIF and PPM unless you're (bravely) using 8.6, when PNG is also available by default.
(You can also create the content of a photo image programatically, but that's slow for various reasons.)
OSX doesn't have window icons in the same sense; it's normal for each minimized window to just show a snapshot of itself when it is minimized to the dock.