如果输入之前已经写入RDS文件,那么在闪亮的应用程序中本地恢复会话是可能的吗? [英] It is possible to restore a session, locally, in a Shiny app if the inputs have been previously written in a RDS file?

查看:9
本文介绍了如果输入之前已经写入RDS文件,那么在闪亮的应用程序中本地恢复会话是可能的吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个闪亮的应用程序,供本地使用。我正在尝试开发一个系统,使用户能够还原以前的会话。

为此,我从这个入口获取了代码:Saving state of Shiny app to be restored later,它确实起作用了,但是我希望能够还原不同会话中的输入,所以我向代码添加了fileInput(还原会话)和downloadButton(保存会话),但不幸的是我无法使其起作用。

我的代码如下:

library(shiny)  

ui <- fluidPage(
  textInput("control_label",
            "This controls some of the labels:",
            "LABEL TEXT"),
  numericInput("inNumber", "Number input:", min = 1, max = 20, value = 5, step = 0.5),
  radioButtons("inRadio", "Radio buttons:",
               c("label 1" = "option1",
                 "label 2" = "option2",
                 "label 3" = "option3")),
  fileInput("load_inputs", "Restore Session", multiple = FALSE),
  downloadButton("save_inputs", 'Save Session')
)

server <-  function(input, output,session) { 

  # SAVE SESSION
  output$save_inputs <- downloadHandler(
    filename = function() {
      paste("session", ".RDS", sep = "")
    },
    content = function(file) {
      saveRDS( reactiveValuesToList(input), file)
    })

  # LOAD SESSION
  load_sesion <- reactive({
    req(input$load_inputs)
    load_session <- readRDS( input$load_inputs$datapath )
  })

  observeEvent(input$load_inputs,{       
    if(is.null(input$load_inputs)) {return(NULL)}

    savedInputs <- load_sesion()
    inputIDs      <- names(savedInputs) 
    inputvalues   <- unlist(savedInputs) 

    for (i in 1:length(inputvalues)) { 
      session$sendInputMessage(inputIDs[i], list(value=inputvalues[[i]]) )
    }
  })}

shinyApp(ui, server)

使用此代码,我可以保存会话的输入,并且可以在下一个会话中读取它们,但是我无法将存储在RDS上的那些值用作另一个会话中的输入。

非常感谢,

瑞秋

推荐答案

正如我在上面的评论中所建议的那样,以下应用程序使用SHINY的内置功能来创建书签,而不是使用自定义函数来保存输入的当前状态。

单击"下载"按钮后,书签将存储在服务器端,重命名并复制到downloadHandler。

如果用户上载书签文件,则会根据文件名创建所需的路径,并将用户重定向到较早的会话。(另请参阅注释掉的替代方案,它要求用户主动切换会话)。

当然,您可以实现一个模式,让用户输入会话名称,以避免将相当隐晦的书签散列用作文件名。

编辑: 实现了允许用户提供自定义会话名称(限于字母数字字符)的模式

library(shiny)
library(shinyjs)
library(utils)
library(tools)
library(stringi)

ui <- function(request) {
    fluidPage(
        useShinyjs(),
        textInput("control_label", "This controls some of the labels:", "LABEL TEXT"),
        numericInput("inNumber", "Number input:", min = 1, max = 20, value = 5, step = 0.5 ),
        radioButtons("inRadio", "Radio buttons:", c("label 1" = "option1", "label 2" = "option2", "label 3" = "option3")),
        fileInput("restore_bookmark", "Restore Session", multiple = FALSE, accept = ".rds"),
        actionButton("save_inputs", 'Save Session', icon = icon("download"))
    )
}

server <-  function(input, output, session) {
    latestBookmarkURL <- reactiveVal()
    
    onBookmarked(
        fun = function(url) {
            latestBookmarkURL(parseQueryString(url))
        }
    )
    
    onRestored(function(state) {
        showNotification(paste("Restored session:", basename(state$dir)), duration = 10, type = "message")
    })
    
    observeEvent(input$save_inputs, {
        showModal(modalDialog(
            title = "Session Name",
            textInput("session_name", "Please enter a session name (optional):"),
            footer = tagList(
                modalButton("Cancel"),
                downloadButton("download_inputs", "OK")
            )
        ))
    }, ignoreInit = TRUE)
    
    # SAVE SESSION
    output$download_inputs <- downloadHandler(
        filename = function() {
            removeModal()
            session$doBookmark()
            if (input$session_name != "") {
                
                tmp_session_name <- sub("\.rds$", "", input$session_name)
                
                # "Error: Invalid state id" when using special characters - removing them:
                tmp_session_name <- stri_replace_all(tmp_session_name, "", regex = "[^[:alnum:]]")
                # TODO: check if a valid filename is provided (e.g. via library(shinyvalidate)) for better user feedback
                
                tmp_session_name <- paste0(tmp_session_name, ".rds")
                
            } else {
                paste(req(latestBookmarkURL()), "rds", sep = ".")
            }
        },
        content = function(file) {
            file.copy(from = file.path(
                ".",
                "shiny_bookmarks",
                req(latestBookmarkURL()),
                "input.rds"
            ),
            to = file)
        }
    )
    
    # LOAD SESSION
    observeEvent(input$restore_bookmark, {
        
        sessionName <- file_path_sans_ext(input$restore_bookmark$name)
        targetPath <- file.path(".", "shiny_bookmarks", sessionName, "input.rds")
        
        if (!dir.exists(dirname(targetPath))) {
            dir.create(dirname(targetPath), recursive = TRUE)
        }
        
        file.copy(
            from = input$restore_bookmark$datapath,
            to = targetPath,
            overwrite = TRUE
        )
        
        restoreURL <- paste0(session$clientData$url_protocol, "//", session$clientData$url_hostname, ":", session$clientData$url_port, session$clientData$url_pathname, "?_state_id_=", sessionName)
        
        # redirect user to restoreURL
        runjs(sprintf("window.location = '%s';", restoreURL))
        
        # showModal instead of redirecting the user
        # showModal(modalDialog(
        #     title = "Restore Session",
        #     "The session data was uploaded to the server. Please visit:",
        #     tags$a(restoreURL),
        #     "to restore the session"
        # ))
    })
    
}

shinyApp(ui, server, enableBookmarking = "server")

这篇关于如果输入之前已经写入RDS文件,那么在闪亮的应用程序中本地恢复会话是可能的吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆