From b80a7d89b62806604645eb66a82ff5cf24d52b2c Mon Sep 17 00:00:00 2001 From: nfrerebeau Date: Fri, 15 Dec 2023 18:44:28 +0100 Subject: [PATCH] Allow to save and restore session --- R/janus-internal.R | 29 +++++++++---- R/module_footer.R | 6 +-- R/module_home.R | 90 +++++++++++++++++++++++------------------ inst/coda/global.R | 2 +- inst/coda/server.R | 12 +++++- inst/config.yml | 10 ++++- inst/seriation/global.R | 2 +- inst/ternary/global.R | 2 +- 8 files changed, 97 insertions(+), 56 deletions(-) diff --git a/R/janus-internal.R b/R/janus-internal.R index 52e25ba..466f0a3 100644 --- a/R/janus-internal.R +++ b/R/janus-internal.R @@ -8,6 +8,10 @@ is_set <- function(x) { !is.null(x) && x != "" } +assert_csv <- function(x) { + validate(need(x, message = "Import a CSV file first.")) +} + url_tesselle <- function(package = NULL, campaign = TRUE) { mtm <- if (campaign) "?mtm_campaign=shiny" else "" if (is.null(package)) { @@ -17,22 +21,33 @@ url_tesselle <- function(package = NULL, campaign = TRUE) { } } -assert_csv <- function(x) { - validate(need(x, message = "Import a CSV file first.")) -} - -cite_markdown <- function(x = NULL) { +cite_package <- function(x = NULL) { x <- c("janus", x) lapply( X = x, FUN = function(x) { bib <- format(utils::citation(x), style = "text") - markdown(bib) + txt <- paste0(vapply(X = bib, FUN = markdown, FUN.VALUE = character(1))) + HTML(txt) } ) } -info_markdown <- function() { +cite_article <- function(author, year, doi, text = FALSE) { + url <- sprintf("https://doi.org/%s", doi) + link <- tags$a(year, href = url, target = "_blank", .noWS = "outside") + + if (text) { + tags$span(author, "(", link, ")") + } else { + tags$span( + paste0("(", author, ", "), link, ")", + .noWS = c("after-begin", "before-end") + ) + } +} + +info_session <- function() { info <- paste0(utils::capture.output(utils::sessionInfo()), collapse = "\n") markdown(sprintf("```\n%s\n```", info)) } diff --git a/R/module_footer.R b/R/module_footer.R index b62e2cb..a90068a 100644 --- a/R/module_footer.R +++ b/R/module_footer.R @@ -17,10 +17,10 @@ module_footer_ui <- function(id) { actionLink(inputId = ns("session"), label = "Session info"), HTML(" · "), tags$a(href = "https://github.com/tesselle/janus", - rel = "external", title = "Code", "Source code"), + target = "_blank", rel = "external", "Source code"), HTML(" · "), tags$a(href = "https://github.com/tesselle/janus/issues", - rel = "external", title = "Issue", "Report a bug or request") + target = "_blank", rel = "external", "Report a bug or request") ) ) } @@ -41,7 +41,7 @@ module_footer_server <- function(id) { showModal( modalDialog( title = "Session Info", - info_markdown(), + info_session(), size = "xl", easyClose = TRUE, footer = modalButton("Close") diff --git a/R/module_home.R b/R/module_home.R index 1d9e4b7..77a0c89 100644 --- a/R/module_home.R +++ b/R/module_home.R @@ -29,7 +29,7 @@ module_home_ui <- function(id) { "This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY." ), - h3("Citation"), + h3("How to cite"), tags$p( "If you use this application in your research, you must report and cite it properly to ensure transparency of your results. @@ -38,7 +38,7 @@ module_home_ui <- function(id) { by the research community." ), tags$p("To cite in your publications, please use:"), - cite_markdown(), + cite_package(), tags$p( class = "logo", tags$a(href = "https://www.archeosciences-bordeaux.fr", rel = "external", @@ -49,8 +49,9 @@ module_home_ui <- function(id) { ), tabPanel( title = "About", - h3("What is", tags$i("tesselle"), "?"), - tags$img(src="static/tesselle.png", alt="Smiley face", style="float:right;width:150px;margin:0 10px;"), + h3("What is", tags$i("tesselle", .noWS = "after"), "?"), + tags$img(src="static/tesselle.png", alt="tesselle logo", + style="float:right;width:150px;margin:0 10px;"), tags$p( "This app is a part of the", tags$strong("tesselle"), "project,", "a collection of packages for research and teaching in archaeology. @@ -61,13 +62,15 @@ module_home_ui <- function(id) { ), tags$p( "For more information and relevant links see:", - tags$a(href = url_tesselle(), rel = "external", "tesselle.org.") + tags$a("tesselle.org", href = url_tesselle(), + target = "_blank", rel = "external", .noWS = "after"), "." ), # h3("Who is", tags$i("tesselle"), "for?"), h3("License"), tags$p( "This app is distributed as a free and open source", - tags$a(href = url_tesselle("janus"), rel = "external", "R package.") + tags$a("R package", href = url_tesselle("janus"), + target = "_blank", rel = "external", .noWS = "after"), "." ), tags$p( "You can redistribute it and/or modify it under the terms of the @@ -75,6 +78,24 @@ module_home_ui <- function(id) { Foundation, either version 3 of the License, or (at your option) any later version." ) + ), + tabPanel( + title = "Save and restore", + fileInput( + inputId = ns("session_restore"), + label = "Restore session", + multiple = FALSE, + accept = ".rds" + ), + textInput( + inputId = ns("session_name"), + label = "Please enter a session name (optional):" + ), + actionButton( + inputId = ns("session_save"), + label = "Save session", + icon = icon("download") + ) ) ) ) # mainPanel @@ -91,40 +112,29 @@ module_home_ui <- function(id) { #' @family server modules #' @keywords internal #' @export -module_home_server <- function(id) { +module_home_server <- function(id, bk) { moduleServer(id, function(input, output, session) { - ## Render ------------------------------------------------------------------ - output$session <- renderPrint({ utils::sessionInfo() }) - - ## Bookmark ---------------------------------------------------------------- - # onBookmark(function(state) { - # saved_time <- Sys.time() - # - # msg <- sprintf("Last saved at %s.", saved_time) - # showNotification( - # ui = msg, - # duration = 5, - # closeButton = TRUE, - # type = "message", - # session = session - # ) - # cat(msg, "\n") - # - # # state is a mutable reference object, - # # we can add arbitrary values to it. - # state$values$time <- saved_time - # }) - ## Bookmark ---------------------------------------------------------------- - # onRestore(function(state) { - # msg <- sprintf("Restoring from state bookmarked at %s.", state$values$time) - # showNotification( - # ui = msg, - # duration = 5, - # closeButton = TRUE, - # type = "message", - # session = session - # ) - # cat(msg, sep = "\n") - # }) + ## Download ----- + output$session_save <- downloadHandler( + filename = function() { + session$doBookmark() + if (input$session_name != "") { + tmp_session_name <- sub("\\.rds$", "", input$session_name) + tmp_session_name <- sub("[[:punct:]]", "", tmp_session_name) + tmp_session_name <- paste0(tmp_session_name, ".rds") + } else { + paste(req(bk()), "rds", sep = ".") + } + }, + content = function(file) { + file.copy(from = file.path( + ".", + "shiny_bookmarks", + req(bk()), + "input.rds" + ), + to = file) + } + ) }) } diff --git a/inst/coda/global.R b/inst/coda/global.R index da84d76..26749f9 100644 --- a/inst/coda/global.R +++ b/inst/coda/global.R @@ -9,4 +9,4 @@ rm(list = ls()) ## Set Shiny settings ========================================================== options(shiny.maxRequestSize = 30*1024^2) -enableBookmarking(store = "server") +enableBookmarking(store = janus::get_option("bookmark")) diff --git a/inst/coda/server.R b/inst/coda/server.R index 03cb79e..d9dd748 100644 --- a/inst/coda/server.R +++ b/inst/coda/server.R @@ -7,6 +7,16 @@ #' @keywords internal #' @noRd shiny_server <- function(input, output, session) { + ## Bookmark + bookmark_url <- reactiveVal() + onBookmarked(fun = function(url) { + bookmark_url(parseQueryString(url)) + }) + onRestored(function(state) { + showNotification(paste("Restored session:", basename(state$dir)), + duration = 10, type = "message") + }) + ## Data clean <- janus::module_import_server("import") |> janus::module_prepare_server("prepare", x = _) |> @@ -37,7 +47,7 @@ shiny_server <- function(input, output, session) { pca_results <- janus::module_pca_server("pca", x = ratio) janus::module_multivar_server("pca", pca_results) - janus::module_home_server("home") + janus::module_home_server("home", bk = bookmark_url) janus::module_header_server("header") janus::module_footer_server("footer") session$onSessionEnded(stopApp) diff --git a/inst/config.yml b/inst/config.yml index 9b8566a..5157303 100644 --- a/inst/config.yml +++ b/inst/config.yml @@ -1,7 +1,13 @@ default: + production: TRUE + verbose: FALSE + bookmark: disable + +test: production: FALSE - verbose: TRUE + verbose: disable -production: +online: production: TRUE verbose: FALSE + bookmark: server diff --git a/inst/seriation/global.R b/inst/seriation/global.R index 5ce0ae8..b0b1650 100644 --- a/inst/seriation/global.R +++ b/inst/seriation/global.R @@ -9,4 +9,4 @@ rm(list = ls()) ## Set Shiny settings ========================================================== options(shiny.maxRequestSize = 30*1024^2) -enableBookmarking(store = "server") +enableBookmarking(store = janus::get_option("bookmark")) diff --git a/inst/ternary/global.R b/inst/ternary/global.R index 270f929..587dc5a 100644 --- a/inst/ternary/global.R +++ b/inst/ternary/global.R @@ -9,4 +9,4 @@ rm(list = ls()) ## Set Shiny settings ========================================================== options(shiny.maxRequestSize = 30*1024^2) -enableBookmarking(store = "server") +enableBookmarking(store = janus::get_option("bookmark"))