From 0e2fedb4281942258418bb0ba09deeadb007087f Mon Sep 17 00:00:00 2001 From: Elie Ker Arno Date: Wed, 15 Jul 2020 14:44:41 +0200 Subject: [PATCH] Refactoring #4 --- .RData | Bin 108517 -> 2876 bytes NAMESPACE | 1 - R/aboutUI-module.R | 6 +- R/documentation-module.R | 4 +- R/eal_0.R | 431 ------ R/eal_0_functions.R | 317 ----- R/eal_1_SelectDP.R | 814 ++++++----- R/eal_2_DataFiles.R | 550 ++++---- R/eal_3_Attributes.R | 1187 ++++++++--------- R/eal_3_attributeInput.R | 2 +- R/eal_4_CatVars.R | 425 +++--- R/eal_5_GeoCovInput.R | 21 +- R/eal_5_geographicCoverage.R | 85 +- R/eal_6_taxonomicCoverage.R | 540 ++++---- R/eal_7_personnel.R | 407 +++--- R/eal_8_misc.R | 388 +++--- R/eal_8_miscellaneous.R | 17 +- R/eal_9_annotations.R | 22 +- R/eal_9_makeeml.R | 313 +++-- R/fill-module.R | 272 +++- R/fill_pages.R | 341 +++++ R/headerScript.R | 28 +- R/orcid_connect.R | 8 +- ...e_functions.R => savevariable_functions.R} | 67 +- R/server.R | 29 +- R/settings.R | 64 +- R/ui.R | 10 +- R/upload-module.R | 469 +++---- R/upload-module_functions.R | 18 +- R/utils-URL_Input.R | 46 +- R/utils-collapsible.R | 44 +- R/utils-listReactiveValues.R | 4 +- R/utils-markdownInput.R | 33 +- R/utils-observersSet.R | 14 - R/utils-readPlaintext.R | 19 + R/utils-setSavevar.R | 31 - R/utils-writeText.R | 6 +- R/{golem_utils_ui.R => utils_withRedStar.R} | 0 inst/media/hex-MetaShARK.hex | Bin 0 -> 17311 bytes inst/media/hex-MetaShARK.png | Bin 0 -> 117572 bytes man/AttributesUI.Rd | 21 - man/CatVars.Rd | 11 - man/CatVarsUI.Rd | 11 - man/DataFiles.Rd | 11 - man/DataFilesUI.Rd | 11 - man/EMLAL.Rd | 12 - man/EMLALUI.Rd | 12 - man/GeoCov.Rd | 11 - man/GeoCovInputUI.Rd | 20 - man/GeoCovUI.Rd | 11 - man/MakeEMLUI.Rd | 21 - man/MiscUI.Rd | 19 - man/Miscellaneous.Rd | 11 - man/MiscellaneousUI.Rd | 11 - man/Personnel.Rd | 11 - man/PersonnelModUI.Rd | 30 - man/PersonnelUI.Rd | 11 - man/SelectDP.Rd | 12 - man/SelectDPUI.Rd | 20 - man/TaxCov.Rd | 11 - man/TaxCovUI.Rd | 11 - man/URL_Input_UI.Rd | 10 +- man/about.Rd | 11 - man/aboutUI.Rd | 11 - man/checkTruth.Rd | 4 +- man/collapsibleUI.Rd | 10 +- man/describeWorkflowUI.Rd | 21 - man/docUI.Rd | 11 - man/documentation.Rd | 11 - man/dot-app_server.Rd | 11 - man/dot-app_ui.Rd | 11 - man/dot-globalScript.Rd | 11 - man/dot-headerScript.Rd | 11 - man/extractCoordinates.Rd | 11 - man/fillUI.Rd | 19 - man/followPath.Rd | 15 +- man/initReactive.Rd | 27 - man/insertGeoCovInput.Rd | 12 - man/insertPersonnelInput.Rd | 13 - man/listReactiveValues.Rd | 6 +- man/markdownInputUI.Rd | 14 +- man/navSidebar.Rd | 42 - man/navSidebarUI.Rd | 50 - man/readPlainText.Rd | 2 +- man/settings.Rd | 2 +- man/uploadUI.Rd | 2 +- man/withRedStar.Rd | 2 +- 87 files changed, 3426 insertions(+), 4256 deletions(-) delete mode 100644 R/eal_0.R delete mode 100644 R/eal_0_functions.R create mode 100644 R/fill_pages.R rename R/{fill-module_functions.R => savevariable_functions.R} (83%) delete mode 100644 R/utils-observersSet.R create mode 100644 R/utils-readPlaintext.R delete mode 100644 R/utils-setSavevar.R rename R/{golem_utils_ui.R => utils_withRedStar.R} (100%) create mode 100644 inst/media/hex-MetaShARK.hex create mode 100644 inst/media/hex-MetaShARK.png delete mode 100644 man/AttributesUI.Rd delete mode 100644 man/CatVars.Rd delete mode 100644 man/CatVarsUI.Rd delete mode 100644 man/DataFiles.Rd delete mode 100644 man/DataFilesUI.Rd delete mode 100644 man/EMLAL.Rd delete mode 100644 man/EMLALUI.Rd delete mode 100644 man/GeoCov.Rd delete mode 100644 man/GeoCovInputUI.Rd delete mode 100644 man/GeoCovUI.Rd delete mode 100644 man/MakeEMLUI.Rd delete mode 100644 man/MiscUI.Rd delete mode 100644 man/Miscellaneous.Rd delete mode 100644 man/MiscellaneousUI.Rd delete mode 100644 man/Personnel.Rd delete mode 100644 man/PersonnelModUI.Rd delete mode 100644 man/PersonnelUI.Rd delete mode 100644 man/SelectDP.Rd delete mode 100644 man/SelectDPUI.Rd delete mode 100644 man/TaxCov.Rd delete mode 100644 man/TaxCovUI.Rd delete mode 100644 man/about.Rd delete mode 100644 man/aboutUI.Rd delete mode 100644 man/describeWorkflowUI.Rd delete mode 100644 man/docUI.Rd delete mode 100644 man/documentation.Rd delete mode 100644 man/dot-app_server.Rd delete mode 100644 man/dot-app_ui.Rd delete mode 100644 man/dot-globalScript.Rd delete mode 100644 man/dot-headerScript.Rd delete mode 100644 man/extractCoordinates.Rd delete mode 100644 man/fillUI.Rd delete mode 100644 man/initReactive.Rd delete mode 100644 man/insertGeoCovInput.Rd delete mode 100644 man/insertPersonnelInput.Rd delete mode 100644 man/navSidebar.Rd delete mode 100644 man/navSidebarUI.Rd diff --git a/.RData b/.RData index f721097d15a917a2a191deb721d6de613c7da39b..339a67021dc804db47f54ed44eee539c028f0a41 100644 GIT binary patch literal 2876 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 RzRF*-4ghQbn%h)&{s*!MOH%*< diff --git a/NAMESPACE b/NAMESPACE index 5685e6f..b4cfbaa 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -57,7 +57,6 @@ importFrom(shinyAce,updateAceEditor) importFrom(shinyBS,bsCollapse) importFrom(shinyBS,bsCollapsePanel) importFrom(shinyBS,bsTooltip) -importFrom(shinyBS,tipify) importFrom(shinyBS,updateCollapse) importFrom(shinyFiles,getVolumes) importFrom(shinyFiles,parseDirPath) diff --git a/R/aboutUI-module.R b/R/aboutUI-module.R index cb400a5..c39e6d4 100644 --- a/R/aboutUI-module.R +++ b/R/aboutUI-module.R @@ -25,16 +25,16 @@ aboutUI <- function(id) { tags$p("The following people and parties have worked upstream of MetaShARK dev team to provide the fundamentals united in the present tool."), - uiOutput(ns("actors")), + uiOutput(NS(id, "actors")), # Informatics tags$h2("Computer material"), tags$p("The following references will lead the user to the source of tools and methods reused in MetaShARK."), - uiOutput(ns("informatics")), + uiOutput(NS(id, "informatics")), # Sci litt tags$h2("Literature"), tags$p("MetaShARK is based on the following papers and articles concerning mainly ecological metadata."), - uiOutput(ns("ecology")) + uiOutput(NS(id, "ecology")) ) } diff --git a/R/documentation-module.R b/R/documentation-module.R index 4d53e7b..a6f1bb1 100644 --- a/R/documentation-module.R +++ b/R/documentation-module.R @@ -21,7 +21,7 @@ docUI <- function(id) { 5, wellPanel( shinyTree::shinyTree( - outputId = ns("tree"), + outputId = NS(id, "tree"), search = TRUE, theme = "proton" ) @@ -32,7 +32,7 @@ docUI <- function(id) { 7, div( id = "docPanel", - uiOutput(ns("doc")) + uiOutput(NS(id, "doc")) ) ) ) diff --git a/R/eal_0.R b/R/eal_0.R deleted file mode 100644 index 3639af4..0000000 --- a/R/eal_0.R +++ /dev/null @@ -1,431 +0,0 @@ -#' @import shiny -#' @importFrom shinydashboard box -#' @importFrom shinycssloaders withSpinner -#' -#' @noRd -EMLALUI <- function(id, dev = FALSE) { - ns <- NS(id) - - fluidPage( - style = "padding-top:2.5%;", - shinydashboard::box( - title = span( - div("EML Assembly Line", style = "padding-right: 15px"), - uiOutput(ns("chain")), - style = "display: inline-flex" - ), - width = 12, - fluidRow( - uiOutput(ns("currentUI")) %>% - shinycssloaders::withSpinner(color = "#599cd4") - ) - ) # end variable UI - ) # end fluidPage -} - -#' @import shiny -#' @importFrom shinyBS tipify -#' -#' @noRd -EMLAL <- function(input, output, session, - save.variable, main.env) { - ns <- session$ns - .EAL <- main.env$EAL # local copy - - # NSB ----------------------------------------------------- - # names of EMLAL steps - steps <- c("SelectDP", "Data Files", "Attributes", "Categorical Variables", "Geographic Coverage", "Taxonomic Coverage", "Personnel", "Miscellaneous", "Make EML") - - NSB <- navSidebar("nav", main.env, save.variable) - assign("NSB", NSB, envir = main.env) - - # Output ----------------------------------------------------- - observeEvent(.EAL$navigate, { - # On loading DP, correct step - if(.EAL$navigate == -1) - .EAL$navigate <- match(utils::tail(save.variable$emlal$history,1), steps) - - if (.EAL$current[1] == "Data Files") { - unlink(main.env$PATHS$eal.tmp) - } - .EAL$current[1] <- steps[.EAL$navigate] - if (.EAL$current[1] == "Data Files" && - !dir.exists(main.env$PATHS$eal.tmp)) { - dir.create(main.env$PATHS$eal.tmp) - } - - if (isFALSE(.EAL$current[2])) { - .EAL$current[2] <- TRUE - } # trigger - .EAL$current[2] <- FALSE - NSB$tag.list <- tagList() - - # Edition changed path -> remove excedent history - if (!.EAL$current[1] %in% .EAL$history) { - .EAL$history <- c(.EAL$history, .EAL$current[1]) - } - - # Savevar modification - save.variable$emlal$step <- .EAL$navigate - save.variable$emlal$history <- .EAL$history - - # * Chain ----------------------------------------------------- - output$chain <- renderUI({ - validate( - need(.EAL$navigate > 1, "") - ) - - return( - tags$span( - tagList( - lapply(seq(.EAL$history)[-1], function(ind) { - .step.name <- .EAL$history[ind] - - if (.step.name != "Taxonomic Coverage") { - .style <- "color: dodgerblue;" - .description <- paste(.step.name, "(mandatory)") - } else { - .style <- "color: lightseagreen;" - .description <- paste(.step.name, "(facultative)") - } - - return( - actionLink( - ns(paste0("chain_", .step.name)), - "", - if (.step.name == .EAL$current[1]) { - icon("map-marker") - } else { - icon("circle") - }, - style = .style - ) %>% shinyBS::tipify( - title = .description - # , placement = "bottom" - # , trigger = "hover" - ) - ) # end of return - }), - paste0( - "Step ", .EAL$navigate, - "/", length(steps), - ": ", .EAL$current[1] - ) - ), - style = "position: right" - ) - ) - }) - - observe({ - validate( - need( - exists("main.env") && isTruthy(names(input)), - "Not initialized" - ), - need( - isTruthy(.EAL$history), - "No history available" - ), - need( - any(sapply( - .EAL$history, - grepl, - x = names(input) - ) %>% unlist()) && - length(.EAL$history) > 1, - "No history available" - ) - ) - - sapply(seq(.EAL$history)[-1], function(.ind) { - id <- paste0("chain_", .EAL$history[.ind]) - - observeEvent(input[[id]], { - req(input[[id]] && - .ind != .EAL$navigate) - .EAL$navigate <- .ind - NSB$NEXT <- NSB$NEXT + 1 - }) - }) - }) - - # * UI ----------------------------------------------------- - namespace <- .EAL$current[1] - - output$currentUI <- renderUI({ - .ui <- switch(.EAL$navigate, - SelectDPUI( - id = ns(namespace), - dev = main.env$DEV - ), - DataFilesUI( - id = ns(namespace), - dev = main.env$DEV - ), - AttributesUI( - id = ns(namespace), - dev = main.env$DEV - ), - CatVarsUI( - id = ns(namespace), - dev = main.env$DEV - ), - GeoCovUI( - id = ns(namespace), - dev = main.env$DEV - ), - TaxCovUI( - id = ns(namespace), - dev = main.env$DEV - ), - PersonnelUI( - id = ns(namespace), - dev = main.env$DEV - ), - MiscUI( - id = ns(namespace), - dev = main.env$DEV, - save.variable = isolate({savevar}) - ), - MakeEMLUI( - id = ns(namespace), - dev = main.env$DEV - ), - tags$h2("WIP") - ) - - return( - if (.EAL$navigate > 1) { - # NSB modifications - .nsb <- if (.EAL$current[1] == "Data Files") { - navSidebarUI(ns("nav"), .prev = FALSE) - } else if (.EAL$current[1] == "Make EML") { - navSidebarUI(ns("nav"), .next = FALSE) - } else { - navSidebarUI(ns("nav")) - } - - tagList( - column(10, .ui), - column(2, .nsb) - ) - } else { - tagList( - column(12, .ui) - ) - } - ) - }) - - # * Server ----------------------------------------------------- - save.variable <- switch(.EAL$navigate, - callModule( - SelectDP, namespace, - save.variable, main.env - ), - callModule( - DataFiles, namespace, - save.variable, main.env, - NSB = NSB - ), - callModule( - Attributes, namespace, - save.variable, main.env, - NSB = NSB - ), - callModule( - CatVars, namespace, - save.variable, main.env, - NSB = NSB - ), - callModule( - GeoCov, namespace, - save.variable, main.env, - NSB = NSB - ), - callModule( - TaxCov, namespace, - save.variable, main.env, - NSB = NSB - ), - callModule( - Personnel, namespace, - save.variable, main.env, - NSB = NSB - ), - callModule( - Misc, namespace, - save.variable, main.env, - NSB = NSB - ), - # TODO Add annotations here? - callModule( - MakeEML, namespace, - save.variable, main.env - ) - ) - # * Module helper ----------------------------------------------------- - NSB$help <- modalDialog( - title = paste0(.EAL$current[1], " - Help"), - switch(.EAL$navigate, - # SelectDP - tagList( - tags$p("This module allows you to manage your", tags$strong("data packages"), ". - A data package (aka DP) is a collection of a dataset and its associated metadata - and resources (scripts, literature, ...). You can:"), - tags$ul( - tags$li("Load an existing data package among local ones (left). You - will resume its edition at the last saved encountered step."), - tags$li( - "Create a new data package. You must fill in", tags$strong("three fields"), - tags$i("Data package name"), "will be used for identifying the DP,", - tags$i("Data package title"), "will be displayed when consulting the DP - page once formatted (explained in last step),", - tags$i("Data package license"), "is the license assigned to this production for - intellectual rights properties" - ) - ), - tags$p("Also, notice the", tags$strong("quick"), "check box above DP name. - Checking this box enables \"quick mode\" which will pre-fill most of the - fields in further steps. You still will be able to edit them at your - convenience.") - ), - # Data Files - tagList( - tags$p("This module allows you to load data files from the dataset you want to - describe. Once uploaded, you can set:"), - tags$ul( - tags$li(tags$i("Content name:"), "A name for the data contained in the file (e.g. table name)."), - tags$li(tags$i("URL:"), "If the file is accessible remotely, here is a way to reference it."), - tags$li(tags$i("Description:"), "A short text provided to describe the file, its content, - relevant information about the data in the entity.") - ), - tags$p("To edit your selection, select files among the list with the check boxes on - their left, then click the \"Remove\" button."), - tags$p("Recommended size per file is around 1 Gb. Such files and heavier ones might slow down the - app.") - ), - # Attributes - tagList( - tags$p("This module allows you to describe precisely each attribute of each file. Some of these metadata - are guessed from the data files. Such fields are annoted with a star (*). - For each attribute, you can set:"), - tags$ul( - tags$li(tags$i("Attribute Name*:"), "the name of the attribute."), - tags$li(tags$i("Attribute Description:"), "a "), - tags$li(tags$i("Attribute Class*:"), "the type of content in the attributes among - \"numeric\", \"character\", \"categorical\" and \"Date\". Categorical means a - character string with encoded values (e.g. Male/Female)."), - tags$li(tags$i("Date format (only for Date class): how the dates of the attributes are - written (e.g. DD-MM-YYYY).")), - tags$li(tags$i("Unit (only for Numeric class):"), "which is the unit used for the - numeric data of the attributes. The list is huge and refers to", tags$a("STMML Scientific - units", href = "http://www.ch.ic.ac.uk/rzepa/codata2/"), ". You can also define you own unit - (see Custom Units thereafter)."), - tags$li(tags$i("Missing Value Code:"), "a one-word code used instead of a missing value among - the data of the attribute currently described."), - tags$li(tags$i("Missing Value Code Explanation:"), "a short definition of the meaning(s) given - for the missing value code.") - ), - tags$h3("Custom units creation"), - tags$p("EML allows the user to define its own units, but this require to fulfill some more - fields. However, the custom units you will have defined will be saved into the Custom Units - table at the bottom of this page. You will find the written custom units in the units selection - once they are written. To define a custom unit, chose the unit to be \"custom\". A custom - unit is defined with:"), - tags$ul( - tags$li(tags$i("Unit id:"), "the id of the unit (e.g. gramsPerOneThirdMeter). The unit id - must validate the STMML schema."), - tags$li(tags$i("Unit type:"), "the physical property measured by the custom unit (e.g. mass)."), - tags$li(tags$i("Parent unit in SI:"), "from which unit among the most common one is the custom - unit derived (e.g. gram)."), - tags$li(tags$i("Multiplier to SI:"), "by how many has the custom unit to be multiplied to be - equal to its parent unit."), - tags$li(tags$i("Unit description:"), "some additional notes about the unit, how to compute it.") - ) - ), - # Catvars - tagList( - tags$p("This module allows you to detail the categorical variables (class \"categorical\" in Attributes). - For each variable, you will be able to detail each of its value by a short description.") - ), - # Geocov - tagList( - tags$p("This module allows you to define the geographic area in which the data have been produced. - You have the choice between two methods to define geographic coverage:"), - tags$ul( - tags$li( - tags$h4("Columns description (recommended)"), - tags$p("This method asks you to choose columns in one of your files. For latitude and longitude, - you can select either one or two columns. If a single column contains a pair of numbers, they - will be detected. Chosing single coordinates will be considered as single sites. Chosing pairs of - coordinates will be considered as sub-areas. For each coordinate, you can select a column - containing description for each one.") - ), - tags$li( - tags$h4("Custom description"), - tags$p("With this, you will be able to define by hand each one of the sites covered by your data.") - ) - ) - ), - # Taxcov - tagList( - tags$p("This module allows you to define the taxonomical coverage of the study. You will be asked to - select columns among your files containing the species name. Also, let the app know if the taxonomic - coverage shall be written with scientific, common or both names. At last, select at least one taxonomic - authority among the ones suggested."), - ), - # Personnel - tagList( - tags$p("This module allows you to get a full list of the people who contributed to the creation of - this dataset. The recommended best practice is to", tags$b("use the ORCID"), "of a person. With - this and the help of {rorcid}, the app will be able to fetch all available and interesting data. - You will be able to correct this afterwards. Also, note that you must fill in the fields - for two roles: creator and contact."), - tags$p("Suggested roles are the following:"), - tags$ul( - tags$li("Creator: person who contributed to produce the data."), - tags$li("Contact: persone to contact for any question about the data."), - tags$li("Principal investigator: person who led the creation of the dataset. Selecting this will allow - you to fill in additional information about the project and its funding."), - tags$li("Custom: as the list of roles is not exhaustive, feel free to add any role you consider important.") - ) - ), - # Misc - tagList( - tags$p("This module allows you to define the last details of your data package. Note that you can write - some of these metadata using the markdown syntax. Here are brief descriptions of the fields:"), - tags$ul( - tags$li("Abstract: the abstract of the publication linked to those data."), - tags$li("Methods: the methods used in the production of this dataset."), - tags$li( - "Keywords: you can type a list of keywords for your dataset. For each keyword, you can add a - keyword thesaurus, like", tags$a("the LTER controlled vocabulary ", href = "http://vocab.lternet.edu/vocab/vocab/index.php"), - ", which are controlled vocabulary your exact keyword originates from. Keywords thesaurus are not - required." - ), - tags$li("Temporal coverage: this lets you define the duration of the study during which the data have been produced."), - tags$li("Additional information: if any information has been omitted, you can provide it here (e.g. collection metadata - from GBIF-EML).") - ) - ), - # Make EML - tagList( - tags$p("Here we are (well done) ! This is the final step to write EML. Just click the button and let the magic happen. If an - error occurs, this will be displayed to the screen. In this case, do not hesitate to get in touch with the dev team."), - tags$p("You can also use the {emldown} package to get a human-readable version of the generated EML. The button below it will - let you download the result of this step.") - ) - ), - footer = modalButton("Close"), - easyClose = TRUE, fade = TRUE - ) - # * end ==== - }, - label = "EAL0 update" - ) - - # Save variable - return(save.variable) -} diff --git a/R/eal_0_functions.R b/R/eal_0_functions.R deleted file mode 100644 index 7ac9bb9..0000000 --- a/R/eal_0_functions.R +++ /dev/null @@ -1,317 +0,0 @@ -#' @title navSidebarUI -#' -#' @description UI part for shiny navigation sidebar module -#' -#' @param id shiny id -#' @param class css class style. Default is set to "navSidebar": -#' .navSidebar { -#' width: 100%; -#' text-align: center; -#' padding: 0; -#' } -#' @param .prev logical. Do you want a "Previous" actionButton? (prevTabButton) -#' @param .next logical. Do you want a "Next" actionButton? (nextTabButton) -#' @param ... UI tags set at the bottom of the navigation side bar -#' -#' @import shiny -navSidebarUI <- function(id, class = "navSidebar", - .prev = TRUE, .next = TRUE) { - ns <- NS(id) - - tags$div( - id = "navsidebar", - verticalLayout( - tags$h4("Navigation", class = "text-title"), - quitButton(id), - saveButton(id), - if (isTRUE(.prev)) prevTabButton(id) else NULL, - if (isTRUE(.next)) nextTabButton(id) else NULL, - uiOutput(ns("NSB_custom_ui")), - tags$hr(), - actionButton(ns("EAL_help"), "Help") - ), - class = class - ) -} - -#' @describeIn navSidebarUI -#' -#' @import shiny -quitButton <- function(id) { - ns <- NS(id) - - actionButton( - ns("quit"), - "Quit", - icon = icon("sign-out-alt"), - width = "100%" - ) -} - -#' @describeIn navSidebarUI -#' -#' @import shiny -saveButton <- function(id) { - ns <- NS(id) - - actionButton( - ns("save"), - "Save", - icon = icon("save", class = "regular"), - width = "100%" - ) -} - -#' @describeIn navSidebarUI -#' -#' @import shiny -nextTabButton <- function(id) { - ns <- NS(id) - - actionButton( - ns("nextTab"), - "Next", - icon = icon("arrow-right"), - width = "100%" - ) -} - -#' @describeIn navSidebarUI -#' -#' @import shiny -prevTabButton <- function(id) { - ns <- NS(id) - - actionButton( - ns("prevTab"), - "Previous", - icon = icon("arrow-left"), - width = "100%" - ) -} - -## Associated server functions ----------------------------------------------------- - -#' @title navSidebar -#' -#' @description server part for shiny navigation sidebar module (see [navSidebar()]). -#' The functions are very specific and thus are not exported. -#' -#' @param id shiny server id -#' @param main.env MetaShARK main.env variable -#' @param save.variable MetaShARK savevar variable -#' -#' @import shiny -navSidebar <- function(id, main.env, save.variable) { - NSB <- reactiveValues( - SAVE = 0, - NEXT = 0, - PREV = 0, - tag.list = tagList(), - help = modalDialog() - ) - - NSB <- callModule(onQuit, id, main.env, save.variable, NSB) - NSB <- callModule(onSave, id, save.variable, NSB) - NSB <- callModule(prevTab, id, main.env, NSB) - NSB <- callModule(nextTab, id, main.env, save.variable, NSB) - - # Custom on-the-fly server - callModule( - function(input, output, session, x = NSB) { - output$NSB_custom_ui <- renderUI({ - x$tag.list - }) - - observeEvent(input$EAL_help, { - showModal(x$help) - }) - }, - id - ) - - return(NSB) -} - -#' @describeIn navSidebar -#' -#' @import shiny -#' @importFrom shinyjs onclick disable enable -onQuit <- function(input, output, session, - main.env, save.variable, NSB) { - ns <- session$ns - - # modal dialog for quitting data description - quitModal <- modalDialog( - title = "You are leaving data description", - "Are you sure to leave? Some of your metadata have maybe not been saved.", - easyClose = FALSE, - footer = tagList( - actionButton(ns("cancel"), "Cancel"), - actionButton(ns("save_quit_button"), "Save & Quit"), - actionButton( - ns("quit_button"), - "Quit", - icon("times-circle"), - class = "redButton" - ) - ) - ) - - # show modal on 'quit' button clicked - observeEvent(input$quit, - { - endisableNSB(input, disable) - req(input$quit) - showModal(quitModal) - }, - label = "NSB quit" - ) - - # quits simply - observeEvent(input$cancel, - { - req(input$quit) - req(input$cancel) - endisableNSB(input, enable) - removeModal() - }, - label = "NSB cancel" - ) - - # calls saveRDS method and quits - observeEvent(input$save_quit_button, - { - req(input$quit) - req(input$save_quit_button) - endisableNSB(input, enable) - removeModal() - - NSB$tagList <- tagList() - NSB$SAVE <- NSB$SAVE + 1 - saveReactive(save.variable) - main.env$EAL$history <- "SelectDP" - main.env$EAL$navigate <- 1 - - file.remove( - list.files( - save.variable$emlal$SelectDP$dp.data.path, - pattern = "preview_" - ) - ) - }, - label = "NSB save+quit" - ) - - # quits simply - observeEvent(input$quit_button, - { - req(input$quit) - req(input$quit_button) - endisableNSB(input, enable) - removeModal() - - NSB$tag.list <- tagList() - main.env$EAL$history <- "SelectDP" - main.env$EAL$navigate <- 1 - - file.remove( - list.files( - save.variable$emlal$SelectDP$dp.data.path, - pattern = "preview___" - ) - ) - }, - label = "NSB +quit" - ) - - return(NSB) -} - -#' @describeIn navSidebar -#' -#' @import shiny -#' @importFrom shinyjs onclick disable enable -onSave <- function(input, output, session, save.variable, NSB) { - observeEvent(input$save, - { - req(input$save) - NSB$SAVE <- NSB$SAVE + 1 - }, - label = "NSB save" - ) - - return(NSB) -} - -#' @describeIn navSidebar -#' -#' @import shiny -#' @importFrom shinyjs onclick enable disable -nextTab <- function(input, output, session, - main.env, save.variable, NSB) { - - observe( - { - if (isFALSE(main.env$EAL$current[2])) { - disable("nextTab") - } else if (isTRUE(main.env$EAL$current[2])) { - enable("nextTab") - } - }, - label = "NSB cplt" - ) - - observeEvent(input$nextTab, - { - if(!isTRUE(main.env$EAL$current[2])) - showNotification( - "Check input information: some are not valid.", - type = "warning" - ) - req(isTRUE(main.env$EAL$current[2])) - endisableNSB(input, disable) - if (!main.env$EAL$current[1] %in% c("Geographic Coverage", "Taxonomic Coverage")) { - main.env$EAL$navigate <- main.env$EAL$navigate + 1 - NSB$tag.list <- tagList() - - # Savevar modification - save.variable$emlal$step <- main.env$EAL$navigate - } - NSB$NEXT <- NSB$NEXT + 1 - endisableNSB(input, enable) - }, - label = "NSB next" - ) - - return(NSB) -} -#' @describeIn navSidebar -#' -#' @import shiny -#' @importFrom shinyjs onclick enable disable -prevTab <- function(input, output, session, main.env, NSB) { - observeEvent(input$prevTab, - { - endisableNSB(input, disable) - main.env$EAL$navigate <- main.env$EAL$navigate - 1 - NSB$tag.list <- tagList() - NSB$PREV <- NSB$PREV + 1 - endisableNSB(input, enable) - }, - label = "NSB prev" - ) - - return(NSB) -} - -#' @importFrom shinyjs enable disable -#' -#' @noRd -endisableNSB <- function(input, todo) { - .n <- names(input) - .n <- .n[which(.n %in% c("save", "quit", "nextTab", "prevTab"))] - sapply(.n, function(ui, action = todo) { - action(ui) - }) -} \ No newline at end of file diff --git a/R/eal_1_SelectDP.R b/R/eal_1_SelectDP.R index 2b667c9..73ec954 100644 --- a/R/eal_1_SelectDP.R +++ b/R/eal_1_SelectDP.R @@ -2,16 +2,16 @@ #' @importFrom shinyFiles shinyDirButton #' #' @noRd -SelectDPUI <- function(id, width = 12, dev = FALSE) { +SelectDPUI <- function(id, main.env) { ns <- NS(id) - + # UI output return( fluidPage( title = "Organize data packages", fluidRow( collapsibleUI( - ns("usage"), + NS(id, "usage"), "TUTORIAL: EML Assembly Line workflow", ... = tagList( tags$p(tags$b("Welcome in the EML Assembly line."), "This tool is @@ -34,15 +34,15 @@ SelectDPUI <- function(id, width = 12, dev = FALSE) { filling. It will bring you to the next step."), tags$li(tags$b("Previous:"), "click this to come back to one of the previous steps. You can also use the steps", tags$span( - icon("circle"), - style = "color: dodgerblue;" - ), " markers to get + icon("circle"), + style = "color: dodgerblue;" + ), " markers to get to the desired step.") ) ) ) ), - # Data package location ----------------------------------------------------- + # Data package location ---- # if (!isTRUE(server)) { # tagList( # fluidRow( @@ -51,7 +51,7 @@ SelectDPUI <- function(id, width = 12, dev = FALSE) { # tags$b("Data Package will be saved in:") # } else { # shinyDirButton( - # ns("dp_location"), + # NS(id, "dp_location"), # "Choose directory", # "DP save location", # icon = icon("folder-open") @@ -59,7 +59,7 @@ SelectDPUI <- function(id, width = 12, dev = FALSE) { # } # ), # column(8, - # textOutput(ns("dp_location")), + # textOutput(NS(id, "dp_location")), # style = "text-align: left;" # ), # class = "inputBox" @@ -74,22 +74,20 @@ SelectDPUI <- function(id, width = 12, dev = FALSE) { hr(), # }, fluidRow( - # Load existing DP ----------------------------------------------------- - column( - ceiling(width / 2), + # Load existing DP ---- + column(6, tags$h4("Edit existing data package", style = "text-align:center" ), - uiOutput(ns("dp_list")) + uiOutput(NS(id, "dp_list")) ), - # Create DP ----------------------------------------------------- - column( - floor(width / 2), + # Create DP ---- + column(6, tags$h4("Create new data package", style = "text-align:center" ), checkboxInput( - ns("quick"), + NS(id, "quick"), tagList( tags$b("Quick mode"), "Most fields will be automatically filled" @@ -98,19 +96,19 @@ SelectDPUI <- function(id, width = 12, dev = FALSE) { ), # Data package title textInput( - ns("dp_name"), + NS(id, "dp_name"), "Data package name", placeholder = paste0(Sys.Date(), "_project") ), textInput( - ns("dp_title"), + NS(id, "dp_title"), "Dataset title", placeholder = "Any title is a title" ), tags$div( id = "license-help", selectInput( - ns("license"), + NS(id, "license"), "Select an Intellectual Rights License:", c("CCBY", "CC0"), multiple = FALSE @@ -121,7 +119,7 @@ SelectDPUI <- function(id, width = 12, dev = FALSE) { CC-BY-4.0: open source with authorship.
For more details, visit Creative Commons."), # DP creation - uiOutput(ns("dp_create")) + uiOutput(NS(id, "dp_create")) ) # end column2 ) # end fluidRow ) # end fluidPage @@ -135,51 +133,43 @@ SelectDPUI <- function(id, width = 12, dev = FALSE) { #' @importFrom jsonlite read_json unserializeJSON #' #' @noRd -SelectDP <- function(input, output, session, save.variable, main.env) { - ns <- session$ns - - if (main.env$dev) { - shinyjs::onclick("dev", +SelectDP <- function(id, main.env){ + moduleServer(id, function(input, output, session) { + save.variable <- main.env$save.variable + ns <- session$ns + + collapsible("usage") + + # variable initialization ---- + rv <- reactiveValues( + dp.location = main.env$PATHS$eal.dp, + dp.name = character(), + dp.title = character(), + dp.list = NULL, + dp.license = NULL + ) + + # DP location ---- + observeEvent(input$dp_location, { - req(main.env$EAL$navigate == 1) - browser() + req(input$dp_location) + rv$dp.location <- input$dp_location }, - asis = TRUE + label = "EAL1: input dp location" ) - } - - callModule(collapsible, "usage") - - # variable initialization ---- - rv <- reactiveValues( - dp.location = main.env$PATHS$eal.dp, - dp.name = character(), - dp.title = character(), - dp.list = NULL, - dp.license = NULL - ) - - # DP location ---- - observeEvent(input$dp_location, - { - req(input$dp_location) - rv$dp.location <- input$dp_location - }, - label = "EAL1: input dp location" - ) - - # Render selected DP location - output$dp_location <- renderText({ - rv$dp.location - }) - - # DP load ----------------------------------------------------- - # reset input if user comes back on this screen - # fetch list of DP at selected location - observeEvent({ - rv$dp.location - main.env$SETTINGS$logged - }, { + + # Render selected DP location + output$dp_location <- renderText({ + rv$dp.location + }) + + # DP load ---- + # reset input if user comes back on this screen + # fetch list of DP at selected location + observeEvent({ + rv$dp.location + main.env$SETTINGS$logged + }, { # Build full DP list .dp.path <- gsub( "/+", @@ -235,377 +225,371 @@ SelectDP <- function(input, output, session, save.variable, main.env) { else rv$dp.list <- NULL }, - label = "EAL1: build dp list" - ) - - # Render list of DP at selected location - output$dp_list <- renderUI({ - validate( - need( - isTruthy(rv$dp.list), - "No data package has been written." - ) + label = "EAL1: build dp list" ) - tagList( - radioButtons( - ns("dp_list"), - NULL, - choiceNames = c("None selected", rv$dp.list), - choiceValues = c("", rv$dp.list) - ), - actionButton( - ns("dp_load"), - "Load", - icon = icon("folder-open") - ), - actionButton( - ns("dp_delete"), - "Delete", - icon = icon("minus-circle"), - class = "redButton" - ), - downloadButton( - ns("dp_download"), - label = "Download .zip", - icon = icon("file-download") + + # Render list of DP at selected location + output$dp_list <- renderUI({ + validate( + need( + isTruthy(rv$dp.list), + "No data package has been written." + ) ) - ) - }) - - # Save updated index ---- - observeEvent(main.env$DP.LIST, { - data.table::fwrite( - main.env$DP.LIST, - isolate(main.env$PATHS$eal.dp.index), - sep = "\t" - ) - }) - - # Manage DP download ---- - output$dp_download <- downloadHandler( - filename = function() { - paste0(input$dp_list, "_emldp.zip") - }, - content = function(file) { - .path <- getwd() - setwd(main.env$PATHS$eal.dp) - utils::zip( - zipfile = file, - files = dir( - gsub( - "/+", - "/", - dir( - ".", - full.names = TRUE, - pattern = input$dp_list - ) - ), - recursive = TRUE, - full.names = TRUE + tagList( + radioButtons( + NS(id, "dp_list"), + NULL, + choiceNames = c("None selected", rv$dp.list), + choiceValues = c("", rv$dp.list) + ), + actionButton( + NS(id, "dp_load"), + "Load", + icon = icon("folder-open") + ), + actionButton( + NS(id, "dp_delete"), + "Delete", + icon = icon("minus-circle"), + class = "redButton" + ), + downloadButton( + NS(id, "dp_download"), + label = "Download .zip", + icon = icon("file-download") ) ) - setwd(.path) - }, - contentType = "application/zip" - ) - - # toggle Load and Delete buttons - observeEvent(input$dp_list, - { - if (input$dp_list != "") { - shinyjs::enable("dp_load") - shinyjs::enable("dp_delete") - shinyjs::enable("dp_download") - } - else { - shinyjs::disable("dp_load") - shinyjs::disable("dp_delete") - shinyjs::disable("dp_download") - } - }, - label = "EAL1: UX hs" - ) - - # DP create ----------------------------------------------------- - # check name input - rv$valid.name <- FALSE - output$dp_create <- renderUI({ - rv$valid.name <- FALSE - validate( - need( - nchar(input$dp_name) > 3, - "Please type a name with at least 3 characters." - ), - need( - grepl("^[[:alnum:]_-]+$", input$dp_name) - && nzchar(input$dp_name), - "Only authorized characters are alphanumeric, '_' (underscore) and '-' (hyphen)." - ), - need( - input$dp_name != "" - && !(input$dp_name %in% rv$dp.list), - "This name is already used: change either save directory or data package name." - ), - need( - input$dp_title != "" - && grepl("^[[:alnum:]\\ \\.,:_-]+$", input$dp_title), - "This title has invalid character: use alphanumerics, or one of: - ' ' '.' ',' ':' '_' '-' " - # \" \", \".\", \",\", \":\", \"_\" or \"-\"." + }) + + # Save updated index ---- + observeEvent(main.env$DP.LIST, { + data.table::fwrite( + main.env$DP.LIST, + isolate(main.env$PATHS$eal.dp.index), + sep = "\t" ) - ) - rv$valid.name <- TRUE - return(actionButton(ns("dp_create"), "Create")) - }) - - observeEvent(input$quick, - { - req(input$dp_name %in% c("", paste0(Sys.Date(), "_project"))) # Do not change a yet changed name - if (input$quick) { - updateTextInput(session, "dp_name", value = paste0(Sys.Date(), "_project")) - } else { - updateTextInput(session, "dp_name", placeholder = paste0(Sys.Date(), "_project")) - } - }, - label = "EAL1: quick" - ) - - observeEvent(input$dp_name, - { - rv$dp.name <- input$dp_name - }, - label = "EAL1: save dp name" - ) - - observeEvent(input$dp_title, - { - rv$dp.title <- input$dp_title - }, - label = "EAL1: save dp title" - ) - - # license choice - observeEvent(input$license, - { - rv$dp.license <- input$license - }, - label = "EAL1: save dp license" - ) - - # DP management - on clicks ----------------------------------------------------- - # * Create DP ----------------------------------------------------- - onclick("dp_create", { - req(input$dp_create) - req(input$dp_name) - req(rv$valid.name) - - # variable operation - legibility purpose - dp <- input$dp_name - path <- paste0(rv$dp.location, dp, "_emldp") - title <- input$dp_title - license <- rv$dp.license - - # verbose - withProgress( - { - # save in empty dedicated variable - save.variable$emlal <- initReactive("emlal", savevar, main.env$EAL) - save.variable$emlal$SelectDP$dp.name <- dp - save.variable$emlal$SelectDP$dp.path <- path - save.variable$emlal$SelectDP$dp.metadata.path <- paste(path, dp, "metadata_templates", sep = "/") - save.variable$emlal$SelectDP$dp.data.path <- paste(path, dp, "data_objects", sep = "/") - save.variable$emlal$SelectDP$dp.eml.path <- paste(path, dp, "eml", sep = "/") - save.variable$emlal$SelectDP$dp.title <- title - save.variable$emlal$quick <- input$quick - incProgress(0.2) - - dir.create(path, recursive = TRUE) - # add DP to index - main.env$DP.LIST <- rbind( - main.env$DP.LIST, - data.frame( - creator.orcid = main.env$SETTINGS$user, - name = dp, - title = title, - path = path, - stringsAsFactors = FALSE - ) - ) - incProgress(0.2) - - # EAL template import - try( - EMLassemblyline::template_directories( - save.variable$emlal$SelectDP$dp.path, - save.variable$emlal$SelectDP$dp.name + }) + + # Manage DP download ---- + output$dp_download <- downloadHandler( + filename = function() { + paste0(input$dp_list, "_emldp.zip") + }, + content = function(file) { + .path <- getwd() + setwd(main.env$PATHS$eal.dp) + utils::zip( + zipfile = file, + files = dir( + gsub( + "/+", + "/", + dir( + ".", + full.names = TRUE, + pattern = input$dp_list + ) + ), + recursive = TRUE, + full.names = TRUE ) ) - incProgress(0.2) - x <- try( - EMLassemblyline::template_core_metadata( - save.variable$emlal$SelectDP$dp.metadata.path, - license - ) + setwd(.path) + }, + contentType = "application/zip" + ) + + # toggle Load and Delete buttons + observeEvent(input$dp_list, + { + if (input$dp_list != "") { + shinyjs::enable("dp_load") + shinyjs::enable("dp_delete") + shinyjs::enable("dp_download") + } + else { + shinyjs::disable("dp_load") + shinyjs::disable("dp_delete") + shinyjs::disable("dp_download") + } + }, + label = "EAL1: UX hs" + ) + + # DP create ---- + # check name input + rv$valid.name <- FALSE + output$dp_create <- renderUI({ + rv$valid.name <- FALSE + validate( + need( + nchar(input$dp_name) > 3, + "Please type a name with at least 3 characters." + ), + need( + grepl("^[[:alnum:]_-]+$", input$dp_name) + && nzchar(input$dp_name), + "Only authorized characters are alphanumeric, '_' (underscore) and '-' (hyphen)." + ), + need( + input$dp_name != "" + && !(input$dp_name %in% rv$dp.list), + "This name is already used: change either save directory or data package name." + ), + need( + input$dp_title != "" + && grepl("^[[:alnum:]\\ \\.,:_-]+$", input$dp_title), + "This title has invalid character: use alphanumerics, or one of: + ' ' '.' ',' ':' '_' '-' " + # \" \", \".\", \",\", \":\", \"_\" or \"-\"." ) - incProgress(0.2) - - if (class(x) != "try-error") { - rv$dp.list <- c(rv$dp.list, dp) - main.env$EAL$navigate <- main.env$EAL$navigate + 1 - saveReactive(save.variable) - incProgress(0.2) + ) + rv$valid.name <- TRUE + return(actionButton(NS(id, "dp_create"), "Create")) + }) + + observeEvent(input$quick, + { + req(input$dp_name %in% c("", paste0(Sys.Date(), "_project"))) # Do not change a yet changed name + if (input$quick) { + updateTextInput(session, "dp_name", value = paste0(Sys.Date(), "_project")) } else { - unlink(path, recursive = TRUE) - save.variable <- initReactive(main.env = main.env$EAL) - incProgress(0.2) - showNotification(x, type = "error") + updateTextInput(session, "dp_name", placeholder = paste0(Sys.Date(), "_project")) } }, - message = paste("Creating:", path, "\n", sep = "") + label = "EAL1: quick" ) - }) - - # * Load DP ----------------------------------------------------- - shinyjs::onclick("dp_load", { - req(input$dp_list) - shinyjs::disable("dp_load") - # variable operation - legibility purpose - dp <- input$dp_list - path <- paste0(rv$dp.location, dp, "_emldp") - - # verbose - showNotification( - paste("Loading:", path, "\n", sep = ""), - type = "message" + + observeEvent(input$dp_name, + { + rv$dp.name <- input$dp_name + }, + label = "EAL1: save dp name" ) - - # actions - save.variable$emlal <- initReactive("emlal", savevar, main.env$EAL) - - .save.variable <- jsonlite::read_json(paste0(path, "/", dp, ".json"))[[1]] %>% - jsonlite::unserializeJSON() - save.variable$emlal <- setSavevar(.savevar$emlal, savevar$emlal) - - # Update paths from another file system - # * selectDP - sapply( - names(save.variable$emlal$SelectDP), - function(.dp.item){ - save.variable$emlal$SelectDP[[.dp.item]] <- gsub( - pattern=".*/dataPackagesOutput/emlAssemblyLine/", - replacement = rv$dp.location, - save.variable$emlal$SelectDP[[.dp.item]] - ) - } + + observeEvent(input$dp_title, + { + rv$dp.title <- input$dp_title + }, + label = "EAL1: save dp title" ) - # * datafiles - if(isTruthy(save.variable$emlal$DataFiles)){ - sapply(names(save.variable$emlal$DataFiles), function(col){ - save.variable$emlal$DataFiles[,col] <- gsub( - pattern=".*/dataPackagesOutput/emlAssemblyLine/", - replacement = rv$dp.location, - save.variable$emlal$DataFiles[,col] - ) - if(col == "size") - save.variable$emlal$DataFiles[,col] <- as.integer( - save.variable$emlal$DataFiles[,col] + + # license choice + observeEvent(input$license, + { + rv$dp.license <- input$license + }, + label = "EAL1: save dp license" + ) + + # DP management - on clicks ---- + # * Create DP ---- + onclick("dp_create", { + req(input$dp_create) + req(input$dp_name) + req(rv$valid.name) + + # variable operation - legibility purpose + dp <- input$dp_name + path <- paste0(rv$dp.location, dp, "_emldp") + title <- input$dp_title + license <- rv$dp.license + + # verbose + withProgress( + { + # save in empty dedicated variable + save.variable$emlal <- initReactive("emlal", savevar, main.env$EAL) + save.variable$emlal$SelectDP$dp.name <- dp + save.variable$emlal$SelectDP$dp.path <- path + save.variable$emlal$SelectDP$dp.metadata.path <- paste(path, dp, "metadata_templates", sep = "/") + save.variable$emlal$SelectDP$dp.data.path <- paste(path, dp, "data_objects", sep = "/") + save.variable$emlal$SelectDP$dp.eml.path <- paste(path, dp, "eml", sep = "/") + save.variable$emlal$SelectDP$dp.title <- title + save.variable$emlal$quick <- input$quick + incProgress(0.2) + + dir.create(path, recursive = TRUE) + # add DP to index + main.env$DP.LIST <- rbind( + main.env$DP.LIST, + data.frame( + creator.orcid = main.env$SETTINGS$user, + name = dp, + title = title, + path = path, + stringsAsFactors = FALSE + ) + ) + incProgress(0.2) + + # EAL template import + try( + EMLassemblyline::template_directories( + save.variable$emlal$SelectDP$dp.path, + save.variable$emlal$SelectDP$dp.name + ) ) - }) - } - # * misc - if(isTruthy(save.variable$emlal$Misc$abstract)){ - save.variable$emlal$Misc$abstract <- gsub( - ".*/dataPackagesOutput/emlAssemblyLine/", - rv$dp.location, - save.variable$emlal$Misc$abstract + incProgress(0.2) + x <- try( + EMLassemblyline::template_core_metadata( + save.variable$emlal$SelectDP$dp.metadata.path, + license + ) + ) + incProgress(0.2) + + if (class(x) != "try-error") { + rv$dp.list <- c(rv$dp.list, dp) + main.env$EAL$page <- main.env$EAL$page + 1 + saveReactive(save.variable) + incProgress(0.2) + } else { + unlink(path, recursive = TRUE) + save.variable <- initReactive(main.env = main.env$EAL) + incProgress(0.2) + showNotification(x, type = "error") + } + }, + message = paste("Creating:", path, "\n", sep = "") ) - save.variable$emlal$Misc$methods <- gsub( - ".*/dataPackagesOutput/emlAssemblyLine/", - rv$dp.location, - save.variable$emlal$Misc$methods + }) + + # * Load DP ---- + shinyjs::onclick("dp_load", { + req(input$dp_list) + shinyjs::disable("dp_load") + # variable operation - legibility purpose + dp <- input$dp_list + path <- paste0(rv$dp.location, dp, "_emldp") + + # verbose + showNotification( + paste("Loading:", path, "\n", sep = ""), + type = "message" ) - save.variable$emlal$Misc$additional.information <- gsub( - ".*/dataPackagesOutput/emlAssemblyLine/", - rv$dp.location, - save.variable$emlal$Misc$additional.information + + # actions + save.variable$emlal <- initReactive("emlal", savevar, main.env$EAL) + + .save.variable <- jsonlite::read_json(paste0(path, "/", dp, ".json"))[[1]] %>% + jsonlite::unserializeJSON() + save.variable$emlal <- setSavevar(.savevar$emlal, savevar$emlal) + + # Update paths from another file system + # * selectDP + sapply( + names(save.variable$emlal$SelectDP), + function(.dp.item){ + save.variable$emlal$SelectDP[[.dp.item]] <- gsub( + pattern=".*/dataPackagesOutput/emlAssemblyLine/", + replacement = rv$dp.location, + save.variable$emlal$SelectDP[[.dp.item]] + ) + } ) - } + # * datafiles + if(isTruthy(save.variable$emlal$DataFiles)){ + sapply(names(save.variable$emlal$DataFiles), function(col){ + save.variable$emlal$DataFiles[,col] <- gsub( + pattern=".*/dataPackagesOutput/emlAssemblyLine/", + replacement = rv$dp.location, + save.variable$emlal$DataFiles[,col] + ) + if(col == "size") + save.variable$emlal$DataFiles[,col] <- as.integer( + save.variable$emlal$DataFiles[,col] + ) + }) + } + # * misc + if(isTruthy(save.variable$emlal$Misc$abstract)){ + save.variable$emlal$Misc$abstract <- gsub( + ".*/dataPackagesOutput/emlAssemblyLine/", + rv$dp.location, + save.variable$emlal$Misc$abstract + ) + save.variable$emlal$Misc$methods <- gsub( + ".*/dataPackagesOutput/emlAssemblyLine/", + rv$dp.location, + save.variable$emlal$Misc$methods + ) + save.variable$emlal$Misc$additional.information <- gsub( + ".*/dataPackagesOutput/emlAssemblyLine/", + rv$dp.location, + save.variable$emlal$Misc$additional.information + ) + } + + # TODO remove this later : update history + save.variable$emlal$history <- sapply(savevar$emlal$history, function(h) { + switch(h, + create = "Select Data Package", + DataFiles = "Data Files", + attributes = "Attributes", + CustomUnits = NULL, + CatVars = "Categorical Variables", + GeoCov = "Geographic Coverage", + TaxCov = "Taxonomic Coverage", + h + ) + }) %>% unname() + save.variable$emlal$quick <- isTRUE(savevar$emlal$quick) + + # resume where max reached + main.env$EAL$page <- if(save.variable$emlal$step > 1) + -1 + else + main.env$EAL$page + 1 + main.env$EAL$history <- save.variable$emlal$history + shinyjs::enable("dp_load") + }) - # TODO remove this later : update history - save.variable$emlal$history <- sapply(savevar$emlal$history, function(h) { - switch(h, - create = "Select Data Package", - DataFiles = "Data Files", - attributes = "Attributes", - CustomUnits = NULL, - CatVars = "Categorical Variables", - GeoCov = "Geographic Coverage", - TaxCov = "Taxonomic Coverage", - h - ) - }) %>% unname() - save.variable$emlal$quick <- isTRUE(savevar$emlal$quick) + # * Delete DP ---- + shinyjs::onclick("dp_delete", { + req(input$dp_list) + + # variable operation - legibility purpose + dp <- input$dp_list + + # actions + showModal( + modalDialog( + title = "Delete data package?", + paste("Are you sure to delete", dp, "?"), + footer = tagList( + modalButton("No"), + actionButton( + NS(id, "delete_confirm"), "Yes", + class = "redButton" + ) + ) # end footer + ) # end modalDialog + ) # end showModal + }) - # resume where max reached - main.env$EAL$navigate <- if(save.variable$emlal$step > 1) - -1 - else - main.env$EAL$navigate + 1 - main.env$EAL$HISTORY <- save.variable$emlal$history - shinyjs::enable("dp_load") - }) - - # * Delete DP ----------------------------------------------------- - shinyjs::onclick("dp_delete", { - req(input$dp_list) - - # variable operation - legibility purpose - dp <- input$dp_list - - # actions - showModal( - modalDialog( - title = "Delete data package?", - paste("Are you sure to delete", dp, "?"), - footer = tagList( - modalButton("No"), - actionButton( - ns("delete_confirm"), "Yes", - class = "redButton" - ) - ) # end footer - ) # end modalDialog - ) # end showModal - }) - - # If deletion is confirmed - shinyjs::onclick("delete_confirm", { - # variable operation - legibility purpose - dp <- input$dp_list - if(grepl("\\(public\\)", dp)) - dp <- gsub(" \\(public\\)", "", dp) - path <- paste0(rv$dp.location, dp, "_emldp") - - # verbose - showNotification( - paste("Deleting:", path, "\n", sep = "") - ) # to replace by deleting DP - - # actions - unlink(path, recursive = TRUE) - rv$dp.list <- rv$dp.list[rv$dp.list != dp] - main.env$DP.LIST <- main.env$DP.LIST[main.env$DP.LIST$name != dp] - removeModal() + # If deletion is confirmed + shinyjs::onclick("delete_confirm", { + # variable operation - legibility purpose + dp <- input$dp_list + if(grepl("\\(public\\)", dp)) + dp <- gsub(" \\(public\\)", "", dp) + path <- paste0(rv$dp.location, dp, "_emldp") + + # verbose + showNotification( + paste("Deleting:", path, "\n", sep = "") + ) # to replace by deleting DP + + # actions + unlink(path, recursive = TRUE) + rv$dp.list <- rv$dp.list[rv$dp.list != dp] + main.env$DP.LIST <- main.env$DP.LIST[main.env$DP.LIST$name != dp] + removeModal() + }) + + # Output ---- + return(save.variable) }) - - # Output ----------------------------------------------------- - return(save.variable) } - -# @importFrom EML read_eml -# -# @noRd -# loadFromDP <- function(save.variable, file) { -# loaded.eml <- read_eml(file) -# } diff --git a/R/eal_2_DataFiles.R b/R/eal_2_DataFiles.R index 0bc6ead..d359c90 100644 --- a/R/eal_2_DataFiles.R +++ b/R/eal_2_DataFiles.R @@ -2,9 +2,9 @@ #' @importFrom shinyFiles shinyFilesButton #' #' @noRd -DataFilesUI <- function(id, dev = FALSE) { +DataFilesUI <- function(id, main.env) { ns <- NS(id) - + return( fluidPage( tags$b("Disclaimers:"), @@ -16,7 +16,7 @@ DataFilesUI <- function(id, dev = FALSE) { tags$div( tagList( fileInput( - ns("add_data_files"), + NS(id, "add_data_files"), "Select data file(s) from your dataset", buttonLabel = span("Load files", icon("plus-circle")), multiple = TRUE @@ -24,8 +24,8 @@ DataFilesUI <- function(id, dev = FALSE) { ), style = "display: inline-block; vertical-align: top;" ), - uiOutput(ns("data_files")), - actionButton(ns("remove_data_files"), "Remove", + uiOutput(NS(id, "data_files")), + actionButton(NS(id, "remove_data_files"), "Remove", icon = icon("minus-circle"), class = "redButton" ) @@ -39,292 +39,290 @@ DataFilesUI <- function(id, dev = FALSE) { #' @importFrom EMLassemblyline template_table_attributes #' #' @noRd -DataFiles <- function(input, output, session, save.variable, main.env, NSB) { - ns <- session$ns - if (main.env$DEV) { - shinyjs::onclick("dev", +DataFiles <- function(id, main.env) { + moduleServer(id, function(input, output, session){ + save.variable <- main.env$save.variable + ns <- session$ns + + # Variable initialization ---- + rv <- reactiveValues( + data.files = data.frame(stringsAsFactors = FALSE) + ) + + if (checkTruth(save.variable$emlal$DataFiles)) { # from create button in SelectDP + .ind <- which(file.exists(save.variable$emlal$DataFiles$datapath)) + .col <- which(names(save.variable$emlal$DataFiles) != "metadatapath") + rv$data.files <- save.variable$emlal$DataFiles[.ind, .col] + } + + # Data file upload ---- + # * Add data files ---- + observeEvent(input$add_data_files, { - req(main.env$EAL$navigate == 2) - browser() + # validity checks + req(input$add_data_files) + + # retrieve data files info + loaded.files <- input$add_data_files + + req(checkTruth(loaded.files)) + + # remove spaces + loaded.files$name <- gsub(" ", "_", loaded.files$name) + + # add URL, description and table name columns + loaded.files$url <- rep("", dim(loaded.files)[1]) + loaded.files$description <- rep("", dim(loaded.files)[1]) + loaded.files$table.name <- rep("", dim(loaded.files)[1]) + + # bind into input + if (isFALSE(checkTruth(rv$data.files) && all(dim(rv$data.files) > 0))) { + rv$data.files <- loaded.files + } else { + sapply(loaded.files$name, function(filename){ + if (fs::is_dir(filename)) { + showNotification( + paste(filename, "is a folder."), + type = "warning" + ) + } else + if (!filename %in% rv$data.files$name) { + rv$data.files <- unique(rbind( + rv$data.files, + loaded.files[loaded.files$name == filename, ] + )) + } + }) + } + + # copies on the server + withProgress( + { + file.copy( + rv$data.files$datapath, + paste0(main.env$PATHS$eal.tmp, rv$data.files$name) + ) + incProgress(0.8) + + rv$data.files$datapath <- paste0(main.env$PATHS$eal.tmp, rv$data.files$name) + incProgress(0.2) + }, + message = "Downloading data files" + ) }, - asis = TRUE + ignoreInit = TRUE, + label = "EAL2: add files" ) - } - - # Variable initialization ----------------------------------------------------- - rv <- reactiveValues( - data.files = data.frame(stringsAsFactors = FALSE) - ) - - if (checkTruth(save.variable$emlal$DataFiles)) { # from create button in SelectDP - .ind <- which(file.exists(save.variable$emlal$DataFiles$datapath)) - .col <- which(names(save.variable$emlal$DataFiles) != "metadatapath") - rv$data.files <- save.variable$emlal$DataFiles[.ind, .col] - } - - # Data file upload ----------------------------------------------------- - # * Add data files ----------------------------------------------------- - observeEvent(input$add_data_files, - { - # validity checks - req(input$add_data_files) - - # retrieve data files info - loaded.files <- input$add_data_files - - req(checkTruth(loaded.files)) - - # remove spaces - loaded.files$name <- gsub(" ", "_", loaded.files$name) - - # add URL, description and table name columns - loaded.files$url <- rep("", dim(loaded.files)[1]) - loaded.files$description <- rep("", dim(loaded.files)[1]) - loaded.files$table.name <- rep("", dim(loaded.files)[1]) - - # bind into input - if (isFALSE(checkTruth(rv$data.files) && all(dim(rv$data.files) > 0))) { - rv$data.files <- loaded.files - } else { - sapply(loaded.files$name, function(filename){ - if (fs::is_dir(filename)) { - showNotification( - paste(filename, "is a folder."), - type = "warning" - ) - } else - if (!filename %in% rv$data.files$name) { - rv$data.files <- unique(rbind( - rv$data.files, - loaded.files[loaded.files$name == filename, ] - )) - } - }) - } - - # copies on the server - withProgress( - { - file.copy( - rv$data.files$datapath, - paste0(main.env$PATHS$eal.tmp, rv$data.files$name) + + # * Remove data files ---- + observeEvent(input$remove_data_files, + { + # validity check + req(input$select_data_files) + + # actions + rv$data.files <- rv$data.files[ + !(rv$data.files$name %in% input$select_data_files), + ] + }, + label = "EAL2: remove files" + ) + + # Display data files ---- + # * UI ---- + observeEvent(rv$data.files, { + df <- isolate(rv$data.files) + + output$data_files <- renderUI({ + validate( + need( + !any(dim(df) == 0) && !is.null(df), + "Select files to describe." ) - incProgress(0.8) - - rv$data.files$datapath <- paste0(main.env$PATHS$eal.tmp, rv$data.files$name) - incProgress(0.2) - }, - message = "Downloading data files" - ) - }, - ignoreInit = TRUE, - label = "EAL2: add files" - ) - - # * Remove data files ----------------------------------------------------- - observeEvent(input$remove_data_files, - { - # validity check - req(input$select_data_files) - - # actions - rv$data.files <- rv$data.files[ - !(rv$data.files$name %in% input$select_data_files), - ] - }, - label = "EAL2: remove files" - ) - - # Display data files ----------------------------------------------------- - # * UI ---- - observeEvent(rv$data.files, { - df <- isolate(rv$data.files) - - output$data_files <- renderUI({ - validate( - need( - !any(dim(df) == 0) && !is.null(df), - "Select files to describe." ) - ) - - checkboxGroupInput(ns("select_data_files"), - "Select files to delete (all files here will be kept otherwise)", - choiceNames = lapply( - df$name, - function(label) { - # Variable initialization - id <- match(label, df$name) - xls.warning <- if (grepl("xlsx?$", label)) { - tags$div( - "Only the first sheet of Excel files will be read.", - style = "color: red" - ) - } else { - NULL - } - - # Output - collapsibleUI( - id = ns(id), - label = label, - hidden = FALSE, - class = "inputBox", - tagList( - fluidRow( - column( - 6, - textInput( - ns(paste0(id, "-dataName")), - "Data table name", - value = label - ) - ), - column( - 6, - URL_Input_UI( - ns(paste0(id, "-dataURL")), - label = "Data remote location" - ) + + checkboxGroupInput(NS(id, "select_data_files"), + "Select files to delete (all files here will be kept otherwise)", + choiceNames = lapply( + df$name, + function(label) { + # Variable initialization + id <- match(label, df$name) + xls.warning <- if (grepl("xlsx?$", label)) { + tags$div( + "Only the first sheet of Excel files will be read.", + style = "color: red" + ) + } else { + NULL + } + + # Output + collapsibleUI( + id = ns(id), + label = label, + hidden = FALSE, + class = "inputBox", + tagList( + fluidRow( + column( + 6, + textInput( + ns(paste0(id, "-dataName")), + "Data table name", + value = label + ) + ), + column( + 6, + URL_Input_UI( + ns(paste0(id, "-dataURL")), + label = "Data remote location" + ) + ), ), - ), - xls.warning, - fluidRow( - column( - 12, - textAreaInput( - ns(paste0(id, "-dataDesc")), - "Data Table Description", - value = paste("Content of", label), - width = "100%" + xls.warning, + fluidRow( + column( + 12, + textAreaInput( + ns(paste0(id, "-dataDesc")), + "Data Table Description", + value = paste("Content of", label), + width = "100%" + ) ) ) ) ) + } + ), + choiceValues = df$name + ) + }) + }) + + # * Server ---- + observeEvent(names(input), { + req( + any(grepl("dataName", names(input))) || + any(grepl("dataURL", names(input))) || + any(grepl("dataDesc", names(input))) + ) + sapply(rv$data.files$name, function(id) { + collapsible(id) + ind <- match(id, rv$data.files$name) + + # Data name + observeEvent(input[[paste0(ind, "-dataName")]], + { + isolate( + rv$data.files[ind, "table.name"] <- input[[paste0(ind, "-dataName")]] ) - } - ), - choiceValues = df$name + }, + ignoreInit = FALSE + ) + # Data URL + observeEvent(input[[paste0(ind, "-dataURL")]], + { + isolate( + rv$data.files[ind, "url"] <- URL_Input(paste0(ind, "-dataURL")) + ) + }, + ignoreInit = FALSE + ) + # Description + observeEvent(input[[paste0(ind, "-dataDesc")]], + { + isolate( + rv$data.files[ind, "description"] <- input[[paste0(ind, "-dataDesc")]] + ) + }, + ignoreInit = FALSE + ) + }) + }) + + # Warnings: data size + observeEvent(rv$data.files, { + req(checkTruth(rv$data.files)) + files.size <- if (checkTruth(rv$data.files$size)) { + sum(rv$data.files$size) + } else { + 0 + } + files.size.max <- main.env$VALUES$thresholds$files.size.max + + style <- if (files.size < 0.9 * files.size.max) { + "color: green;" + } else if (files.size >= 0.9 * files.size.max && files.size < files.size.max) { + "color: gold;" + } else { + "color: red" + } + + EAL$tag.list <- tagList( + "Files size:", + tags$p( + utils::object.size(files.size), + if (files.size >= files.size.max) { + paste("Max. recommended:", utils::object.size(files.size.max)) + } else { + NULL + }, + style = style + ) ) }) - }) - - # * Server ---- - observeEvent(names(input), { - req( - any(grepl("dataName", names(input))) || - any(grepl("dataURL", names(input))) || - any(grepl("dataDesc", names(input))) + + # Saves ---- + observe({ + main.env$EAL$completed <- checkTruth(rv$data.files) && + all(dim(rv$data.files) > 0) + }) + + # observeEvent(NSB$SAVE, + shinyjs::onclick( + "fill-wizard-save", + asis = TRUE, + add = TRUE, + { + req(main.env$EAL$current == "Data Files") + req(isTruthy(rv$data.files$name)) + + save.variable <- saveReactive( + save.variable = savevar, + rv = list(DataFiles = rv) + ) + }, + label = "Save_DataFiles", + ignoreInit = TRUE ) - sapply(rv$data.files$name, function(id) { - callModule(collapsible, id) - ind <- match(id, rv$data.files$name) - - # Data name - observeEvent(input[[paste0(ind, "-dataName")]], - { - isolate( - rv$data.files[ind, "table.name"] <- input[[paste0(ind, "-dataName")]] - ) - }, - ignoreInit = FALSE - ) - # Data URL - observeEvent(input[[paste0(ind, "-dataURL")]], - { - isolate( - rv$data.files[ind, "url"] <- callModule(URL_Input, paste0(ind, "-dataURL")) - ) - }, - ignoreInit = FALSE - ) - # Description - observeEvent(input[[paste0(ind, "-dataDesc")]], - { - isolate( - rv$data.files[ind, "description"] <- input[[paste0(ind, "-dataDesc")]] + + # Process files ---- + observeEvent(EAL$.next, + { + req(main.env$EAL$current == "Data Files") + # Save + save.variable <- saveReactive( + save.variable, + rv = list(DataFiles = rv) + ) + + # EMLAL templating function + try( + EMLassemblyline::template_table_attributes( + path = save.variable$emlal$SelectDP$dp.metadata.path, + data.path = save.variable$emlal$SelectDP$dp.data.path, + data.table = save.variable$emlal$DataFiles$name ) - }, - ignoreInit = FALSE - ) - }) - }) - - # Warnings: data size - observeEvent(rv$data.files, { - req(checkTruth(rv$data.files)) - files.size <- if (checkTruth(rv$data.files$size)) { - sum(rv$data.files$size) - } else { - 0 - } - files.size.max <- main.env$VALUES$thresholds$files.size.max - - style <- if (files.size < 0.9 * files.size.max) { - "color: green;" - } else if (files.size >= 0.9 * files.size.max && files.size < files.size.max) { - "color: gold;" - } else { - "color: red" - } - - NSB$tagList <- tagList( - "Files size:", - tags$p( - utils::object.size(files.size), - if (files.size >= files.size.max) { - paste("Max. recommended:", utils::object.size(files.size.max)) - } else { - NULL - }, - style = style - ) + ) + }, + priority = 1, + ignoreInit = TRUE ) + + # Output ---- + return(save.variable) }) - - # Saves ----------------------------------------------------- - observe({ - main.env$EAL$current[2] <- checkTruth(rv$data.files) && - all(dim(rv$data.files) > 0) - }) - - observeEvent(NSB$SAVE, - { - req(utils::tail(main.env$EAL$history, 1) == "Data Files") - req(isTruthy(rv$data.files$name)) - - save.variable <- saveReactive( - save.variable = savevar, - rv = list(DataFiles = rv) - ) - }, - label = "Save_DataFiles", - ignoreInit = TRUE - ) - - # Process files ---- - observeEvent(NSB$NEXT, - { - req(main.env$EAL$current[1] == "Data Files") - # Save - save.variable <- saveReactive( - save.variable, - rv = list(DataFiles = rv) - ) - - # EMLAL templating function - try( - EMLassemblyline::template_table_attributes( - path = save.variable$emlal$SelectDP$dp.metadata.path, - data.path = save.variable$emlal$SelectDP$dp.data.path, - data.table = save.variable$emlal$DataFiles$name - ) - ) - }, - priority = 1, - ignoreInit = TRUE - ) - - # Output ----------------------------------------------------- - return(save.variable) } diff --git a/R/eal_3_Attributes.R b/R/eal_3_Attributes.R index 6c7c675..4eed1e6 100644 --- a/R/eal_3_Attributes.R +++ b/R/eal_3_Attributes.R @@ -5,7 +5,7 @@ #' @import shiny #' #' @noRd -AttributesUI <- function(id, title, dev) { +AttributesUI <- function(id, main.env) { ns <- NS(id) return( @@ -21,21 +21,21 @@ AttributesUI <- function(id, title, dev) { column( 1, actionButton( - ns("file_prev"), + NS(id, "file_prev"), "", icon("chevron-left") ) ), column( 10, - uiOutput(ns("current_file"), + uiOutput(NS(id, "current_file"), inline = TRUE ) ), column( 1, actionButton( - ns("file_next"), + NS(id, "file_next"), "", icon("chevron-right") ) @@ -44,666 +44,659 @@ AttributesUI <- function(id, title, dev) { fluidRow( column( 12, - uiOutput(ns("edit_attributes")) %>% + uiOutput(NS(id, "edit_attributes")) %>% shinycssloaders::withSpinner(color = "#599cd4") ) ), # Custom Units tags$h4("Custom Units"), fluidRow( - tableOutput(ns("CUUI")) + tableOutput(NS(id, "CUUI")) ) ) # end fluidPage ) # end return } -#' @describeIn AttributesUI -#' -#' @description server part of the Attributes module. -#' #' @importFrom data.table fwrite #' @import shiny #' @importFrom shinyjs hide show enable disable onclick #' @importFrom EMLassemblyline template_categorical_variables template_geographic_coverage #' @importFrom shinyBS bsCollapse bsCollapsePanel updateCollapse -Attributes <- function(input, output, session, - save.variable, main.env, NSB){ - ns <- session$ns - - if (main.env$DEV) { -shinyjs::onclick("dev", - { - req(main.env$EAL$navigate == 3) - browser() - }, - asis = TRUE - ) - } - - if (main.env$DEV || isTRUE(save.variable$emlal$quick)) { - .fill <- function(rv = rv) { - lapply(seq(rv$tables), function(ind) { - .table <- rv$tables[[ind]] - sapply(colnames(.table), function(col) { - # Set values - if (col == "attributeDefinition") { - rv$tables[[ind]][[col]] <- paste("Description for", rv$tables[[ind]][["attributeName"]]) - } - if (col %in% c("missingValueCodeExplanation", "missingValueCode")) { - rv$tables[[ind]][[col]] <- rep("LoremIpsum", dim(.table)[1]) - } - if (col == "dateTimeFormatString") { - .dat.row <- which(rv$tables[[ind]]$class == "Date") - rv$tables[[ind]][[col]] <- rep("", dim(.table)[1]) - if(isTruthy(.dat.row)) - rv$tables[[ind]][.dat.row, col] <- rep(main.env$FORMATS$dates[3], length(.dat.row)) - } - if (col == "unit") { - .uni.row <- which(rv$tables[[ind]]$class == "numeric") - rv$tables[[ind]][[col]] <- rep("", dim(.table)[1]) - if(isTruthy(.uni.row)) - rv$tables[[ind]][.uni.row, col] <- rep(main.env$FORMATS$dates[2], length(.uni.row)) - } +#' +#' @noRd +Attributes <- function(id, main.env) { + moduleServer(id, function(input, output, session){ + save.variable <- main.env$save.variable + ns <- session$ns + + if (main.env$DEV || isTRUE(save.variable$emlal$quick)) { + .fill <- function(rv = rv) { + lapply(seq(rv$tables), function(ind) { + .table <- rv$tables[[ind]] + sapply(colnames(.table), function(col) { + # Set values + if (col == "attributeDefinition") { + rv$tables[[ind]][[col]] <- paste("Description for", rv$tables[[ind]][["attributeName"]]) + } + if (col %in% c("missingValueCodeExplanation", "missingValueCode")) { + rv$tables[[ind]][[col]] <- rep("LoremIpsum", dim(.table)[1]) + } + if (col == "dateTimeFormatString") { + .dat.row <- which(rv$tables[[ind]]$class == "Date") + rv$tables[[ind]][[col]] <- rep("", dim(.table)[1]) + if(isTruthy(.dat.row)) + rv$tables[[ind]][.dat.row, col] <- rep(main.env$FORMATS$dates[3], length(.dat.row)) + } + if (col == "unit") { + .uni.row <- which(rv$tables[[ind]]$class == "numeric") + rv$tables[[ind]][[col]] <- rep("", dim(.table)[1]) + if(isTruthy(.uni.row)) + rv$tables[[ind]][.uni.row, col] <- rep(main.env$FORMATS$dates[2], length(.uni.row)) + } + + # Update values + if (ind == rv$current.file) { + sapply(1:dim(rv$tables[[ind]])[1], function(item) { + inputId <- paste(ind, item, col, sep = "-") + if (inputId %in% names(input)) { + if (col %in% c("unit", "dateTimeFormatString")) { + updateSelectInput(session, inputId, selected = rv$tables[[ind]][item, col]) + } + if (col %in% c("attributeDefinition", "missingValueCode", "missingValueCodeExplanation")) { + updateTextAreaInput(session, inputId, value = rv$tables[[ind]][item, col]) + } + } + }) + } + }) # end of sapply - # Update values + # Update current table if (ind == rv$current.file) { - sapply(1:dim(rv$tables[[ind]])[1], function(item) { - inputId <- paste(ind, item, col, sep = "-") - if (inputId %in% names(input)) { - if (col %in% c("unit", "dateTimeFormatString")) { - updateSelectInput(session, inputId, selected = rv$tables[[ind]][item, col]) - } - if (col %in% c("attributeDefinition", "missingValueCode", "missingValueCodeExplanation")) { - updateTextAreaInput(session, inputId, value = rv$tables[[ind]][item, col]) - } - } - }) + rv$current.table <- rv$tables[[ind]] } - }) # end of sapply - - # Update current table - if (ind == rv$current.file) { - rv$current.table <- rv$tables[[ind]] - } - }) # end of lapply - return(rv) - } # end of .fill - } - - # variable initialization ----------------------------------------------------- - rv <- reactiveValues( - data.filepath = save.variable$emlal$DataFiles$datapath, - filepath = save.variable$emlal$DataFiles$metadatapath, - filenames = basename(save.variable$emlal$DataFiles$metadatapath), - current.file = 1, - tables = NULL, - current.table = NULL, - current.preview = NULL, - cu.table = data.frame(stringsAsFactors = FALSE), - cu.values = rep(NA, 5), - modal.on = FALSE, - unit.id = character(), - units.list = character(), - annotations = reactiveValues( - values = data.frame(stringsAsFactors = FALSE), - count = 0 + }) # end of lapply + return(rv) + } # end of .fill + } + + # variable initialization ---- + rv <- reactiveValues( + data.filepath = save.variable$emlal$DataFiles$datapath, + filepath = save.variable$emlal$DataFiles$metadatapath, + filenames = basename(save.variable$emlal$DataFiles$metadatapath), + current.file = 1, + tables = NULL, + current.table = NULL, + current.preview = NULL, + cu.table = data.frame(stringsAsFactors = FALSE), + cu.values = rep(NA, 5), + modal.on = FALSE, + unit.id = character(), + units.list = character(), + annotations = reactiveValues( + values = data.frame(stringsAsFactors = FALSE), + count = 0 + ) ) - ) - rv$tables <- lapply( - rv$filepath, readDataTable, - data.table = FALSE, stringsAsFactors = FALSE - ) - rv$current.table <- rv$tables[[rv$current.file]] - rv$cu.table <- readDataTable( - dir( - save.variable$emlal$SelectDP$dp.metadata.path, - pattern = "ustom", - full.names = TRUE - ), - stringsAsFactors = FALSE, - ) - rv$units.list <- main.env$FORMATS$units - if (checkTruth(save.variable$emlal$Attributes$annotations)) { - rv$annotations$values <- save.variable$emlal$Attributes$annotations - rv$annotations$count <- nrow(rv$annotations$values) - } - else { - rv$annotations$values <- data.frame( - id = character(), - element = character(), - context = character(), - subject = character(), - predicate_label = character(), - predicate_uri = character(), - object_label = character(), - object_uri = character(), - stringsAsFactors = FALSE + rv$tables <- lapply( + rv$filepath, readDataTable, + data.table = FALSE, stringsAsFactors = FALSE ) - } - - if (isTRUE(save.variable$emlal$quick)) { - rv <- .fill(rv) - } - - observe( - { - . <- rv$current.table # trigger - - .tmp <- unique(c( - unlist(lapply(seq_along(rv$tables), function(t) { - .tab <- if (t == rv$current.file) { - rv$current.table - } else { - rv$tables[[t]] - } - .tab$unit - })), - main.env$FORMATS$units - )) - rv$units.list <- .tmp[.tmp != ""] - }, - label = "EAL3: unit list" - ) - - # Reactive triggers - curt <- makeReactiveTrigger() - - # List of observers - obs <- reactiveValues() - - # Navigation buttons ----------------------------------------------------- - onclick("file_prev", { - req(rv$current.file > 1) - # Save - if (!is.null(rv$current.table)) { - rv$tables[[rv$current.file]] <- rv$current.table - } - # Change file - rv$current.file <- rv$current.file - 1 - }) - - onclick("file_next", { - req(rv$current.file < length(rv$filenames)) - # Save - if (!is.null(rv$current.table)) { - rv$tables[[rv$current.file]] <- rv$current.table + rv$current.table <- rv$tables[[rv$current.file]] + rv$cu.table <- readDataTable( + dir( + save.variable$emlal$SelectDP$dp.metadata.path, + pattern = "ustom", + full.names = TRUE + ), + stringsAsFactors = FALSE, + ) + rv$units.list <- main.env$FORMATS$units + if (checkTruth(save.variable$emlal$Attributes$annotations)) { + rv$annotations$values <- save.variable$emlal$Attributes$annotations + rv$annotations$count <- nrow(rv$annotations$values) } - # Change file - rv$current.file <- rv$current.file + 1 - }) - - # update table - observeEvent(rv$current.file, - { - req(rv$current.file > 0) - rv$current.table <- rv$tables[[rv$current.file]] - rv$current.table[is.na(rv$current.table)] <- "" - rv$current.preview <- readDataTable( - rv$data.filepath[rv$current.file], - stringsAsFactors = FALSE, - nrows = 5 + else { + rv$annotations$values <- data.frame( + id = character(), + element = character(), + context = character(), + subject = character(), + predicate_label = character(), + predicate_uri = character(), + object_label = character(), + object_uri = character(), + stringsAsFactors = FALSE ) - }, - priority = 1 - ) - - # display - output$current_file <- renderUI( - tags$div( - rv$filenames[rv$current.file], - class = "ellipsis", - style = paste0( - "display: inline-block; + } + + if (isTRUE(save.variable$emlal$quick)) { + rv <- .fill(rv) + } + + observe( + { + . <- rv$current.table # trigger + + .tmp <- unique(c( + unlist(lapply(seq_along(rv$tables), function(t) { + .tab <- if (t == rv$current.file) { + rv$current.table + } else { + rv$tables[[t]] + } + .tab$unit + })), + main.env$FORMATS$units + )) + rv$units.list <- .tmp[.tmp != ""] + }, + label = "EAL3: unit list" + ) + + # Reactive triggers + curt <- makeReactiveTrigger() + + # List of observers + obs <- reactiveValues() + + # Navigation buttons ---- + onclick("file_prev", { + req(rv$current.file > 1) + # Save + if (!is.null(rv$current.table)) { + rv$tables[[rv$current.file]] <- rv$current.table + } + # Change file + rv$current.file <- rv$current.file - 1 + }) + + onclick("file_next", { + req(rv$current.file < length(rv$filenames)) + # Save + if (!is.null(rv$current.table)) { + rv$tables[[rv$current.file]] <- rv$current.table + } + # Change file + rv$current.file <- rv$current.file + 1 + }) + + # update table + observeEvent(rv$current.file, + { + req(rv$current.file > 0) + rv$current.table <- rv$tables[[rv$current.file]] + rv$current.table[is.na(rv$current.table)] <- "" + rv$current.preview <- readDataTable( + rv$data.filepath[rv$current.file], + stringsAsFactors = FALSE, + nrows = 5 + ) + }, + priority = 1 + ) + + # display + output$current_file <- renderUI( + tags$div( + rv$filenames[rv$current.file], + class = "ellipsis", + style = paste0( + "display: inline-block; font-size:14pt; text-align:center; width:100%; background: linear-gradient(90deg, #3c8dbc ", - round(100 * rv$current.file / length(rv$filenames)), - "%, white ", - round(100 * rv$current.file / length(rv$filenames)), - "%);" + round(100 * rv$current.file / length(rv$filenames)), + "%, white ", + round(100 * rv$current.file / length(rv$filenames)), + "%);" + ) ) ) - ) - - # * UI ----------------------------------------------------- - observeEvent(rv$current.file, { - req(checkTruth(rv$current.table)) - .current.table <- isolate(rv$current.table) - output$edit_attributes <- renderUI({ - # validity check - validate( - need( - !identical(.current.table, data.frame()) && - isTruthy(.current.table), - "No valid attributes table." - ) - ) + # * UI ---- + observeEvent(rv$current.file, { + req(checkTruth(rv$current.table)) + .current.table <- isolate(rv$current.table) - ui <- do.call( - bsCollapse, - args = c( - lapply( - seq(dim(.current.table)[1]), # rows - fields = colnames(.current.table), - function(row.index, fields) { - # prepare variables - attribute.row <- .current.table[row.index, ] - - return( - bsCollapsePanel( - title = attribute.row[fields[1]], - tagList( - column( - 9, - # Input ==== - lapply(fields[-1], function(colname) { - # prepare var - saved.value <- .current.table[row.index, colname] - inputId <- paste( - isolate(rv$current.file), - row.index, - sep = "-" - ) - - # GUI - attributeInputUI( - ns(inputId), - colname, - saved.value, - main.env$FORMATS, - rv - ) - }) # end of lapply colname - ), - column( - 3, - # Preview ==== - h4("Preview:"), - tableOutput( - ns(paste0( - "preview-", - colnames(rv$current.preview)[row.index] - )) - ), - tags$hr(), - # Annotate ==== - # tags$div( - # annotateUI( - # ns(paste( - # "annotate", - # isolate(rv$current.file), - # row.index, - # sep = "-" - # )) - # ), - # class = "inputbox wip" - # ) - ) # end of column - ) - ) # end of bsCollapsePanel - ) # end of return - } - ), # end of lapply : row.index - id = ns("collapse") + output$edit_attributes <- renderUI({ + # validity check + validate( + need( + !identical(.current.table, data.frame()) && + isTruthy(.current.table), + "No valid attributes table." + ) ) - ) - return(ui) - }) - }) # end of observeEvent - - # * Server ----------------------------------------------------- - observeEvent(rv$current.file, { - req(checkTruth(rv$current.table)) - - sapply( - seq(dim(rv$current.table)[1]), - fields = colnames(rv$current.table)[-1], # not Attribute Name - function(row.index, fields) { - # TODO Update style: to correct - # updateCollapse( - # session = session, - # ns("collapse"), - # style = filled - # ) - - # Preview ==== - preview.column <- colnames(rv$current.preview)[row.index] - output[[paste0("preview-", preview.column)]] <- renderTable(rv$current.preview[[preview.column]]) - - # Annotate ==== - # annotateId <- paste( - # "annotate", - # isolate(rv$current.file), - # row.index, - # sep = "-" - # ) - # - # .tmp <- callModule( - # annotate, annotateId, - # save.variable, main.env, rv, row.index - # ) - - # Input ==== - lapply(fields, function(colname) { - inputId <- paste( - isolate(rv$current.file), - row.index, - sep = "-" - ) - - obs <- callModule( - attributeInput, - inputId, - rv, - row.index, - colname, - obs, - curt + ui <- do.call( + bsCollapse, + args = c( + lapply( + seq(dim(.current.table)[1]), # rows + fields = colnames(.current.table), + function(row.index, fields) { + # prepare variables + attribute.row <- .current.table[row.index, ] + + return( + bsCollapsePanel( + title = attribute.row[fields[1]], + tagList( + column( + 9, + # Input ==== + lapply(fields[-1], function(colname) { + # prepare var + saved.value <- .current.table[row.index, colname] + inputId <- paste( + isolate(rv$current.file), + row.index, + sep = "-" + ) + + # GUI + attributeInputUI( + ns(inputId), + colname, + saved.value, + main.env$FORMATS, + rv + ) + }) # end of lapply colname + ), + column( + 3, + # Preview ==== + h4("Preview:"), + tableOutput( + ns(paste0( + "preview-", + colnames(rv$current.preview)[row.index] + )) + ), + tags$hr(), + # Annotate ==== + # tags$div( + # annotateUI( + # ns(paste( + # "annotate", + # isolate(rv$current.file), + # row.index, + # sep = "-" + # )) + # ), + # class = "inputbox wip" + # ) + ) # end of column + ) + ) # end of bsCollapsePanel + ) # end of return + } + ), # end of lapply : row.index + id = NS(id, "collapse") ) - }) # end of lapply colname - } # end of *in situ* function - ) # end of sapply : row.index - }) # end of observeEvent - - # Custom units ---- - observe({ - curt$depend() - .current.table <- isolate(rv$current.table) - modal.on <- isolate(rv$modal.on) - req(any(.current.table$unit == "custom")) - - rv$unit.id <- c( - rv$current.file, - which(.current.table$unit == "custom"), - "unit" - ) - - row <- rv$unit.id[2] - class <- .current.table[row, "class"] + ) + return(ui) + }) + }) # end of observeEvent - if (class == "numeric" && - modal.on == FALSE) { - rv$cu.values <- rv$cu.table %>% - dplyr::filter(grepl(class, id)) - if (any(dim(rv$cu.values) == 0)) { - rv$cu.values <- rep(NA, 5) - } + # * Server ---- + observeEvent(rv$current.file, { + req(checkTruth(rv$current.table)) - showModal(CU_Modal(rv$cu.values, cu.table = rv$cu.table)) - - rv$modal.on <- TRUE - - isolate({ - rv$current.table[row, "unit"] <- "" - }) - } - }) - - CU_Modal <- function(values = rep(NA, 5), cu.table = NULL) { - modalDialog( - title = "Custom Unit", - tagList( - # id - fluidRow( - column(6, - offset = 3, - textInput( - ns("modal_id"), - label = withRedStar("Unit identifier"), - placeholder = "e.g. milligramsPerGram", - value = if (!is.na(values[1])) values[1] else NULL - ), - # unitType - textInput( - ns("modal_unitType"), - label = withRedStar("Physical property types the unit belongs to"), - placeholder = "e.g. mass", - value = if (!is.na(values[2])) values[2] else NULL - ), - # ParentSI - selectInput( - ns("modal_parentSI"), - label = withRedStar("Parent unit in SI"), - choices = main.env$FORMATS$units[-1], - selected = if (!is.na(values[3])) values[3] else NULL - ), - # MultiplierToSI - numericInput( - ns("modal_multiplier"), - label = withRedStar("Numeric multiplier computed from Parent unit in SI"), - value = 1, - ), - # Description - textAreaInput( - ns("modal_description"), - label = withRedStar("Unit description"), - placeholder = "e.g. milligrams per gram", - value = if (!is.na(values[5])) values[5] else NULL + sapply( + seq(dim(rv$current.table)[1]), + fields = colnames(rv$current.table)[-1], # not Attribute Name + function(row.index, fields) { + + # TODO Update style: to correct + # updateCollapse( + # session = session, + # NS(id, "collapse"), + # style = filled + # ) + + # Preview ==== + preview.column <- colnames(rv$current.preview)[row.index] + output[[paste0("preview-", preview.column)]] <- renderTable(rv$current.preview[[preview.column]]) + + # Annotate ==== + # annotateId <- paste( + # "annotate", + # isolate(rv$current.file), + # row.index, + # sep = "-" + # ) + # + # .tmp <- callModule( + # annotate, annotateId, + # save.variable, main.env, rv, row.index + # ) + + # Input ==== + lapply(fields, function(colname) { + inputId <- paste( + isolate(rv$current.file), + row.index, + sep = "-" ) - ) - ) # end of fluidRow - ), - easyClose = FALSE, - footer = tagList( - actionButton(ns("modal_cancel"), "Cancel"), - actionButton(ns("modal_submit"), "Submit") - ) - ) - } - - # * CU server ---- - # Cancel - onclick("modal_cancel", { - req(isTRUE(rv$modal.on)) - - # Close modal - rv$modal.on <- FALSE - removeModal() + + obs <- attributeInput( + inputId, + rv, + row.index, + colname, + obs, + curt + ) + }) # end of lapply colname + } # end of *in situ* function + ) # end of sapply : row.index + }) # end of observeEvent - isolate({ - updateSelectInput( - session, - paste(rv$unit.id, collapse = "-"), - selected = main.env$FORMATS$units[2] + # Custom units ---- + observe({ + curt$depend() + .current.table <- isolate(rv$current.table) + modal.on <- isolate(rv$modal.on) + req(any(.current.table$unit == "custom")) + + rv$unit.id <- c( + rv$current.file, + which(.current.table$unit == "custom"), + "unit" ) + + row <- rv$unit.id[2] + class <- .current.table[row, "class"] + + if (class == "numeric" && + modal.on == FALSE) { + rv$cu.values <- rv$cu.table %>% + dplyr::filter(grepl(class, id)) + if (any(dim(rv$cu.values) == 0)) { + rv$cu.values <- rep(NA, 5) + } + + showModal(CU_Modal(rv$cu.values, cu.table = rv$cu.table)) + + rv$modal.on <- TRUE + + isolate({ + rv$current.table[row, "unit"] <- "" + }) + } }) - rv$unit.id <- character() # reset to default - }) - - # Submit button en/disable - observe({ - req(isTRUE(rv$modal.on)) - # type a new one - if (!input$modal_id %in% rv$cu.table$id && - input$modal_id != "custom" && - isTruthy(input$modal_id) && - isTruthy(input$modal_unitType) && - isTruthy(input$modal_parentSI) && - isTruthy(input$modal_multiplier) && - isTruthy(input$modal_description)) { - shinyjs::enable("modal_submit") - } else { - shinyjs::disable("modal_submit") + CU_Modal <- function(values = rep(NA, 5), cu.table = NULL) { + modalDialog( + title = "Custom Unit", + tagList( + # id + fluidRow( + column(6, + offset = 3, + textInput( + NS(id, "modal_id"), + label = withRedStar("Unit identifier"), + placeholder = "e.g. milligramsPerGram", + value = if (!is.na(values[1])) values[1] else NULL + ), + # unitType + textInput( + NS(id, "modal_unitType"), + label = withRedStar("Physical property types the unit belongs to"), + placeholder = "e.g. mass", + value = if (!is.na(values[2])) values[2] else NULL + ), + # ParentSI + selectInput( + NS(id, "modal_parentSI"), + label = withRedStar("Parent unit in SI"), + choices = main.env$FORMATS$units[-1], + selected = if (!is.na(values[3])) values[3] else NULL + ), + # MultiplierToSI + numericInput( + NS(id, "modal_multiplier"), + label = withRedStar("Numeric multiplier computed from Parent unit in SI"), + value = 1, + ), + # Description + textAreaInput( + NS(id, "modal_description"), + label = withRedStar("Unit description"), + placeholder = "e.g. milligrams per gram", + value = if (!is.na(values[5])) values[5] else NULL + ) + ) + ) # end of fluidRow + ), + easyClose = FALSE, + footer = tagList( + actionButton(NS(id, "modal_cancel"), "Cancel"), + actionButton(NS(id, "modal_submit"), "Submit") + ) + ) } - }) - - # Submit - observeEvent(input$modal_submit, - { + + # * CU server ---- + # Cancel + onclick("modal_cancel", { req(isTRUE(rv$modal.on)) # Close modal - removeModal() rv$modal.on <- FALSE + removeModal() - isolate({ - rv$cu.values <- c( - input$modal_id, - input$modal_unitType, - input$modal_parentSI, - input$modal_multiplier, - input$modal_description - ) - }) - - # Update CU values - if (rv$cu.values[1] %in% rv$cu.table$id) { - rv$cu.table <- rv$cu.table %>% - dplyr::filter(id = rv$cu.values[1]) %>% - base::replace(values = rv$cu.values) - } # Add CU values - else { - names(rv$cu.values) <- colnames(rv$cu.table) - rv$cu.table[dim(rv$cu.table)[1] + 1,] <- rv$cu.values - } - # update input UI - rv$units.list <- unique(c( - rv$cu.values["id"], - rv$units.list - )) isolate({ updateSelectInput( session, paste(rv$unit.id, collapse = "-"), - choices = rv$units.list, - selected = rv$cu.values["id"] + selected = main.env$FORMATS$units[2] ) }) + rv$unit.id <- character() # reset to default + }) + + # Submit button en/disable + observe({ + req(isTRUE(rv$modal.on)) - row <- rv$unit.id[2] - rv$current.table[row, "unit"] <- rv$cu.values["id"] - }, - priority = 1 - ) - - output$CUUI <- renderTable({ - validate( - need(isTruthy(unlist(rv$cu.table)), "No custom units registered") + # type a new one + if (!input$modal_id %in% rv$cu.table$id && + input$modal_id != "custom" && + isTruthy(input$modal_id) && + isTruthy(input$modal_unitType) && + isTruthy(input$modal_parentSI) && + isTruthy(input$modal_multiplier) && + isTruthy(input$modal_description)) { + shinyjs::enable("modal_submit") + } else { + shinyjs::disable("modal_submit") + } + }) + + # Submit + observeEvent(input$modal_submit, + { + req(isTRUE(rv$modal.on)) + + # Close modal + removeModal() + rv$modal.on <- FALSE + + isolate({ + rv$cu.values <- c( + input$modal_id, + input$modal_unitType, + input$modal_parentSI, + input$modal_multiplier, + input$modal_description + ) + }) + + # Update CU values + if (rv$cu.values[1] %in% rv$cu.table$id) { + rv$cu.table <- rv$cu.table %>% + dplyr::filter(id = rv$cu.values[1]) %>% + base::replace(values = rv$cu.values) + } # Add CU values + else { + names(rv$cu.values) <- colnames(rv$cu.table) + rv$cu.table[dim(rv$cu.table)[1] + 1,] <- rv$cu.values + } + # update input UI + rv$units.list <- unique(c( + rv$cu.values["id"], + rv$units.list + )) + isolate({ + updateSelectInput( + session, + paste(rv$unit.id, collapse = "-"), + choices = rv$units.list, + selected = rv$cu.values["id"] + ) + }) + + row <- rv$unit.id[2] + rv$current.table[row, "unit"] <- rv$cu.values["id"] + }, + priority = 1 ) - return(rv$cu.table) - }) - - # Saves ----------------------------------------------------- - # observeEvent(rv$tables, { - observe( - { - main.env$EAL$current[2] <- FALSE - req( - length(rv$tables) != 0 && - !any(sapply(rv$tables, identical, y = data.frame())) - ) - - main.env$EAL$current[2] <- all( - unlist( - lapply( - rv$tables, - function(table) { - isTruthy(table) && - all(sapply(table$attributeName, isTruthy)) && - all(sapply(table$attributeDefinition, isTruthy)) && - all(sapply(table$class, isTruthy)) && - !any(grepl("!Add.*here!", table$unit)) && - !any(grepl("!Add.*here!", table$dateTimeFormatString)) - } - ) # lapply - ) # unlist - ) # all - }, - priority = -1 - ) - - observeEvent(NSB$SAVE, - { - req(utils::tail(main.env$EAL$history, 1) == "Attributes") - - save.variable <- saveReactive( - save.variable = savevar, - rv = list(Attributes = rv) + + output$CUUI <- renderTable({ + validate( + need(isTruthy(unlist(rv$cu.table)), "No custom units registered") ) - }, - label = "Save_Attributes", - ignoreInit = TRUE - ) - - # en/disable buttons - observeEvent(rv$current.file, { - req( - isTruthy(names(input)) && - isTruthy(names(rv$current.file)) + return(rv$cu.table) + }) + + # Saves ---- + # observeEvent(rv$tables, { + observe( + { + main.env$EAL$completed <- FALSE + req( + length(rv$tables) != 0 && + !any(sapply(rv$tables, identical, y = data.frame())) + ) + + main.env$EAL$completed <- all( + unlist( + lapply( + rv$tables, + function(table) { + isTruthy(table) && + all(sapply(table$attributeName, isTruthy)) && + all(sapply(table$attributeDefinition, isTruthy)) && + all(sapply(table$class, isTruthy)) && + !any(grepl("!Add.*here!", table$unit)) && + !any(grepl("!Add.*here!", table$dateTimeFormatString)) + } + ) # lapply + ) # unlist + ) # all + }, + priority = -1 ) - if (rv$current.file == 1) { - shinyjs::disable("file_prev") - } else { - shinyjs::enable("file_prev") - } - if (rv$current.file == length(rv$filenames)) { - shinyjs::disable("file_next") - } else { - shinyjs::enable("file_next") - } - }) - - # Process data ----------------------------------------------------- - observeEvent(NSB$NEXT, - { - req(main.env$EAL$current[1] == "Attributes") - - withProgress({ - setProgress(0.5, "Saving metadata") + # observeEvent(NSB$SAVE, + shinyjs::onclick( + "fill-wizard-save", + asis = TRUE, + add = TRUE, + { + req(utils::tail(main.env$EAL$history, 1) == "Attributes") save.variable <- saveReactive( save.variable = savevar, rv = list(Attributes = rv) ) + }, + label = "Save_Attributes", + ignoreInit = TRUE + ) + + # en/disable buttons + observeEvent(rv$current.file, { + req( + isTruthy(names(input)) && + isTruthy(names(rv$current.file)) + ) + + if (rv$current.file == 1) { + shinyjs::disable("file_prev") + } else { + shinyjs::enable("file_prev") + } + if (rv$current.file == length(rv$filenames)) { + shinyjs::disable("file_next") + } else { + shinyjs::enable("file_next") + } + }) + + # Process data ---- + observeEvent(EAL$.next, + { + req(main.env$EAL$current == "Attributes") - # for each attribute data frame - setProgress(0.8, "Resolving catvar templates") - .do.template.catvars <- sapply( - seq_along(rv$filenames), - function(cur_ind) { - - # check for direction: CustomUnits or CatVars - return(isTRUE("categorical" %in% rv$tables[[cur_ind]][, "class"])) + withProgress({ + setProgress(0.5, "Saving metadata") + + save.variable <- saveReactive( + save.variable = savevar, + rv = list(Attributes = rv) + ) + + # for each attribute data frame + setProgress(0.8, "Resolving catvar templates") + .do.template.catvars <- sapply( + seq_along(rv$filenames), + function(cur_ind) { + + # check for direction: CustomUnits or CatVars + return(isTRUE("categorical" %in% rv$tables[[cur_ind]][, "class"])) + } + ) %>% + unlist() %>% + any() + + # EMLAL: template new fields if needed + if (isTRUE(.do.template.catvars)) { + try( + EMLassemblyline::template_categorical_variables( + path = save.variable$emlal$SelectDP$dp.metadata.path, + data.path = save.variable$emlal$SelectDP$dp.data.path + ) + ) } - ) %>% - unlist() %>% - any() - - # EMLAL: template new fields if needed - if (isTRUE(.do.template.catvars)) { + + setProgress(0.9, "Templating geographic coverage") try( - EMLassemblyline::template_categorical_variables( + EMLassemblyline::template_geographic_coverage( path = save.variable$emlal$SelectDP$dp.metadata.path, - data.path = save.variable$emlal$SelectDP$dp.data.path + data.path = save.variable$emlal$SelectDP$dp.data.path, + empty = TRUE, + write.file = TRUE ) ) - } - - setProgress(0.9, "Templating geographic coverage") - try( - EMLassemblyline::template_geographic_coverage( - path = save.variable$emlal$SelectDP$dp.metadata.path, - data.path = save.variable$emlal$SelectDP$dp.data.path, - empty = TRUE, - write.file = TRUE - ) - ) - - if (isFALSE(.do.template.catvars)) { - isolate(main.env$EAL$navigate <- main.env$EAL$navigate + 1) - } - incProgress(0.1) - }) - }, - priority = 1, - ignoreInit = TRUE - ) - - # Output ----------------------------------------------------- - return(save.variable) + + if (isFALSE(.do.template.catvars)) { + isolate(main.env$EAL$page <- main.env$EAL$page + 1) + } + incProgress(0.1) + }) + }, + priority = 1, + ignoreInit = TRUE + ) + + # Output ---- + return(save.variable) + }) } diff --git a/R/eal_3_attributeInput.R b/R/eal_3_attributeInput.R index f1afe50..0c155d4 100644 --- a/R/eal_3_attributeInput.R +++ b/R/eal_3_attributeInput.R @@ -101,7 +101,7 @@ attributeInput <- function(input, output, session, value = .val ) showNotification( - id = session$ns("mvc_update"), + id = session$NS(id, "mvc_update"), ui = HTML("missingValueCode fields are limited to a single word."), duration = 3, diff --git a/R/eal_4_CatVars.R b/R/eal_4_CatVars.R index 87b5658..0417133 100644 --- a/R/eal_4_CatVars.R +++ b/R/eal_4_CatVars.R @@ -1,7 +1,7 @@ #' @import shiny -CatVarsUI <- function(id, title, dev) { +CatVarsUI <- function(id, main.env) { ns <- NS(id) - + return( fluidPage( fluidRow( @@ -10,7 +10,7 @@ CatVarsUI <- function(id, title, dev) { column( 1, actionButton( - ns("file_prev"), + NS(id, "file_prev"), "", icon("chevron-left") ) @@ -18,14 +18,14 @@ CatVarsUI <- function(id, title, dev) { column( 10, uiOutput( - ns("current_file"), + NS(id, "current_file"), inline = TRUE ) ), column( 1, actionButton( - ns("file_next"), + NS(id, "file_next"), "", icon("chevron-right") ) @@ -33,7 +33,7 @@ CatVarsUI <- function(id, title, dev) { style = "padding: 5px;" ), # content form - uiOutput(ns("edit_catvar")) + uiOutput(NS(id, "edit_catvar")) ) ) # end of fluidPage ) # end of return @@ -45,231 +45,228 @@ CatVarsUI <- function(id, title, dev) { #' @importFrom shinyjs onclick #' #' @noRd -CatVars <- function(input, output, session, - save.variable, main.env, NSB) { - ns <- session$ns - - if (main.env$DEV) { -shinyjs::onclick("dev", +CatVars <- function(id, main.env) { + moduleServer(id, function(input, output, session){ + save.variable <- main.env$save.variable + ns <- session$ns + + # variables initialization ---- + rv <- reactiveValues( + catvar.files = list.files( + save.variable$emlal$SelectDP$dp.metadata.path, + pattern = "catvar", + full.names = TRUE + ), + current.index = 1 + ) + + # update current file + observeEvent(rv$current.index, { - req(main.env$EAL$navigate == 4) - browser() + rv$current.file <- basename(rv$catvar.files[rv$current.index]) }, - asis = TRUE + priority = 1, + ignoreInit = FALSE ) - } - - # variables initialization ----------------------------------------------------- - rv <- reactiveValues( - catvar.files = list.files( - save.variable$emlal$SelectDP$dp.metadata.path, - pattern = "catvar", - full.names = TRUE - ), - current.index = 1 - ) - - # update current file - observeEvent(rv$current.index, - { - rv$current.file <- basename(rv$catvar.files[rv$current.index]) - }, - priority = 1, - ignoreInit = FALSE - ) - - # Set each reactivevalues per file - sapply(rv$catvar.files, function(file.path) { - file.name <- basename(file.path) - rv[[file.name]] <- reactiveValues() - - # * Init data frame ==== - rv[[file.name]]$CatVars <- fread( - file.path, - data.table = FALSE, stringsAsFactors = FALSE, - na.strings = "NA" - ) %>% - dplyr::mutate( - definition = if (definition == "NA" || is.na(definition)) { - paste("Value:", code, "for attribute:", attributeName) - } else { - definition + + # Set each reactivevalues per file + sapply(rv$catvar.files, function(file.path) { + file.name <- basename(file.path) + rv[[file.name]] <- reactiveValues() + + # * Init data frame ==== + rv[[file.name]]$CatVars <- fread( + file.path, + data.table = FALSE, stringsAsFactors = FALSE, + na.strings = "NA" + ) %>% + dplyr::mutate( + definition = if (definition == "NA" || is.na(definition)) { + paste("Value:", code, "for attribute:", attributeName) + } else { + definition + } + ) + + # * Write UI ==== + .content <- lapply( + unique(rv[[file.name]]$CatVars$attributeName), + function(attribute) { + # get codes aka values for `attribute` in catvar_*.txt + codes <- rv[[file.name]]$CatVars %>% + dplyr::filter(attributeName == attribute) %>% + dplyr::select(code) + + bsCollapsePanel( + title = attribute, + # value = attribute, + ... = tagList( + lapply(unlist(codes), function(cod) { + if(is.na(cod)) + cod <- "NA" + + input.id <- paste( + attribute, + cod %>% + gsub("[ [:punct:]]", "", .), + sep = "-" + ) + + textAreaInput( + ns(input.id), + cod, + value = rv[[file.name]]$CatVars %>% + dplyr::filter(attributeName == attribute, code == cod) %>% + dplyr::select(definition) %>% + unique + ) + }) + ) # end of "tagapply" -- text areas + ) # end of bsCollapsePanel } + ) # end of "tagapply" -- collapse boxes + + rv[[file.name]]$UI <- do.call( + bsCollapse, + c( + .content, + id = file.name, + multiple = FALSE + ) ) - - # * Write UI ==== - .content <- lapply( - unique(rv[[file.name]]$CatVars$attributeName), - function(attribute) { - # get codes aka values for `attribute` in catvar_*.txt - codes <- rv[[file.name]]$CatVars %>% - dplyr::filter(attributeName == attribute) %>% - dplyr::select(code) - - bsCollapsePanel( - title = attribute, - # value = attribute, - ... = tagList( - lapply(unlist(codes), function(cod) { - if(is.na(cod)) - cod <- "NA" - - input.id <- paste( - attribute, - cod %>% - gsub("[ [:punct:]]", "", .), - sep = "-" - ) - - textAreaInput( - ns(input.id), - cod, - value = rv[[file.name]]$CatVars %>% - dplyr::filter(attributeName == attribute, code == cod) %>% - dplyr::select(definition) %>% - unique - ) - }) - ) # end of "tagapply" -- text areas - ) # end of bsCollapsePanel + + # * Write server ==== + rv[[file.name]]$obs <- sapply( + seq(dim(rv[[file.name]]$CatVars)[1]), + function(row) { + input.id <- paste( + rv[[file.name]]$CatVars$attributeName[row], + rv[[file.name]]$CatVars$code[row] %>% + gsub("[ [:punct:]]", "", .), + sep = "-" + ) + + return( + observeEvent(input[[input.id]], + { + req(input[[input.id]]) + rv[[file.name]]$CatVars[row, "definition"] <- input[[input.id]] + }, + suspended = TRUE + ) + ) + } + ) + }) + + # Navigation buttons ---- + # Previous file + observeEvent(input$file_prev, { + req(rv$current.index, rv$catvar.files) + save.variable$emlal$CatVars[[rv$current.file]] <- rv[[rv$current.file]]$CatVars + if (rv$current.index > 1) { + rv$current.index <- rv$current.index - 1 } - ) # end of "tagapply" -- collapse boxes + }) - rv[[file.name]]$UI <- do.call( - bsCollapse, - c( - .content, - id = file.name, - multiple = FALSE - ) - ) - - # * Write server ==== - rv[[file.name]]$obs <- sapply( - seq(dim(rv[[file.name]]$CatVars)[1]), - function(row) { - input.id <- paste( - rv[[file.name]]$CatVars$attributeName[row], - rv[[file.name]]$CatVars$code[row] %>% - gsub("[ [:punct:]]", "", .), - sep = "-" - ) - - return( - observeEvent(input[[input.id]], - { - req(input[[input.id]]) - rv[[file.name]]$CatVars[row, "definition"] <- input[[input.id]] - }, - suspended = TRUE - ) - ) + # Next file + observeEvent(input$file_next, { + req(rv$current.index, rv$catvar.files) + save.variable$emlal$CatVars[[rv$current.file]] <- rv[[rv$current.file]]$CatVars + if (rv$current.index < length(rv$catvar.files)) { + rv$current.index <- rv$current.index + 1 } - ) - }) - - # Navigation buttons ----------------------------------------------------- - # Previous file - observeEvent(input$file_prev, { - req(rv$current.index, rv$catvar.files) - save.variable$emlal$CatVars[[rv$current.file]] <- rv[[rv$current.file]]$CatVars - if (rv$current.index > 1) { - rv$current.index <- rv$current.index - 1 - } - }) - - # Next file - observeEvent(input$file_next, { - req(rv$current.index, rv$catvar.files) - save.variable$emlal$CatVars[[rv$current.file]] <- rv[[rv$current.file]]$CatVars - if (rv$current.index < length(rv$catvar.files)) { - rv$current.index <- rv$current.index + 1 - } - }) - - # Current file - output$current_file <- renderUI({ - tags$div( - rv$current.file, - class = "ellipsis", - style = paste0( - "display: inline-block; + }) + + # Current file + output$current_file <- renderUI({ + tags$div( + rv$current.file, + class = "ellipsis", + style = paste0( + "display: inline-block; font-size:14pt; text-align:center; width:100%; background: linear-gradient(90deg, #3c8dbc ", - round(100 * rv$current.index / length(rv$catvar.files)), - "%, white ", - round(100 * rv$current.index / length(rv$catvar.files)), - "%);" + round(100 * rv$current.index / length(rv$catvar.files)), + "%, white ", + round(100 * rv$current.index / length(rv$catvar.files)), + "%);" + ) ) + }) + + # Set UI ---- + output$edit_catvar <- renderUI({ + validate( + need(rv[[rv$current.file]]$UI, "No UI set.") + ) + rv[[rv$current.file]]$UI + }) # end of renderUI + + # Set Server ---- + + # Suspend observers + observeEvent(rv$current.index, + { + req(rv$current.file) + sapply(rv[[rv$current.file]]$obs, function(obs) { + obs$suspend() + }) + }, + priority = 2 ) - }) - - # Set UI ----------------------------------------------------- - output$edit_catvar <- renderUI({ - validate( - need(rv[[rv$current.file]]$UI, "No UI set.") - ) - rv[[rv$current.file]]$UI - }) # end of renderUI - - # Set Server ----------------------------------------------------- - - # Suspend observers - observeEvent(rv$current.index, - { - req(rv$current.file) - sapply(rv[[rv$current.file]]$obs, function(obs) { - obs$suspend() - }) - }, - priority = 2 - ) - - # Run observers - observeEvent(rv$current.file, - { - req(rv$current.file) - sapply(rv[[rv$current.file]]$obs, function(obs) { - obs$resume() - }) - }, - priority = 0 - ) - - # Saves ----------------------------------------------------- - observe({ - main.env$EAL$current[2] <- all( - sapply(basename(rv$catvar.files), function(file.name) { - all(sapply(rv[[file.name]]$CatVars$definition, isTruthy)) - }) - ) - }) - - observeEvent(NSB$SAVE, { - req(utils::tail(main.env$EAL$history, 1) == "Categorical Variables") - - save.variable <- saveReactive( - save.variable, - rv = list(CatVars = rv) + + # Run observers + observeEvent(rv$current.file, + { + req(rv$current.file) + sapply(rv[[rv$current.file]]$obs, function(obs) { + obs$resume() + }) + }, + priority = 0 ) - }) - - # Process data ----------------------------------------------------- - observeEvent(NSB$NEXT, - { - req(main.env$EAL$current[2] == "Categorical Variables") - + + # Saves ---- + observe({ + main.env$EAL$completed <- all( + sapply(basename(rv$catvar.files), function(file.name) { + all(sapply(rv[[file.name]]$CatVars$definition, isTruthy)) + }) + ) + }) + + # observeEvent(NSB$SAVE, + shinyjs::onclick( + "fill-wizard-save", + asis = TRUE, + add = TRUE, + { + req(utils::tail(main.env$EAL$history, 1) == "Categorical Variables") + save.variable <- saveReactive( save.variable, rv = list(CatVars = rv) ) - }, - priority = 1, - ignoreInit = TRUE - ) - - # Output ----------------------------------------------------- - return(save.variable) + }) + + # Process data ---- + observeEvent(EAL$.next, + { + req(main.env$EAL$current == "Categorical Variables") + + save.variable <- saveReactive( + save.variable, + rv = list(CatVars = rv) + ) + }, + priority = 1, + ignoreInit = TRUE + ) + + # Output ---- + return(save.variable) + }) } diff --git a/R/eal_5_GeoCovInput.R b/R/eal_5_GeoCovInput.R index 871e6dd..8a705c7 100644 --- a/R/eal_5_GeoCovInput.R +++ b/R/eal_5_GeoCovInput.R @@ -29,7 +29,7 @@ GeoCovInputUI <- function(id, site.id, rmv.id, default = NULL) { id = site.id, fluidRow( column(2, "Description", style = "text-align: right"), - column(9, textInput(ns("site_description"), def.site, site.id)), + column(9, textInput(NS(id, "site_description"), def.site, site.id)), column( 1, actionButton( @@ -82,7 +82,7 @@ GeoCovInputUI <- function(id, site.id, rmv.id, default = NULL) { GeoCovInput <- function(input, output, session, rv, rmv.id, site.id, ref) { - # Metadata acquisition ----------------------------------------------------- + # Metadata acquisition ---- local.rv <- reactiveValues( id = ref, geographicDescription = "", @@ -121,7 +121,7 @@ GeoCovInput <- function(input, output, session, priority = 1 ) - # Metadata save ----------------------------------------------------- + # Metadata save ---- observeEvent( { input$site_description @@ -145,7 +145,7 @@ GeoCovInput <- function(input, output, session, priority = 0 ) - # Remove UI ----------------------------------------------------- + # Remove UI ---- shinyjs::onclick(rmv.id, { # remove the UI removeUI(selector = paste0("#", site.id), immediate = TRUE) @@ -156,7 +156,7 @@ GeoCovInput <- function(input, output, session, rv$id <- rv$id[-ind] }) - # Output ----------------------------------------------------- + # Output ---- return(rv) } @@ -167,12 +167,12 @@ GeoCovInput <- function(input, output, session, insertGeoCovInput <- function(id, rv, ns, default = NULL) { # !!! warning: rv = rv$custom here !!! - # initialize IDs ----------------------------------------------------- + # initialize IDs ---- div.id <- id site.id <- paste0("site_", div.id) rmv.id <- paste0("rmv_", div.id) - # Proper module server ----------------------------------------------------- + # Proper module server ---- # create the UI new.ui <- GeoCovInputUI(ns(div.id), site.id, rmv.id, default = default) @@ -180,12 +180,9 @@ insertGeoCovInput <- function(id, rv, ns, default = NULL) { insertUI(selector = "#inserthere", ui = new.ui) # create the server - rv <- callModule( - GeoCovInput, div.id, - rv, rmv.id, site.id, id - ) + rv <- GeoCovInput(div.id, rv, rmv.id, site.id, id) - # Output ----------------------------------------------------- + # Output ---- return(rv) } diff --git a/R/eal_5_geographicCoverage.R b/R/eal_5_geographicCoverage.R index ace0562..543bf8c 100644 --- a/R/eal_5_geographicCoverage.R +++ b/R/eal_5_geographicCoverage.R @@ -2,7 +2,7 @@ #' @importFrom shinyjs hidden #' #' @noRd -GeoCovUI <- function(id, title, dev) { +GeoCovUI <- function(id, main.env) { ns <- NS(id) return( @@ -18,21 +18,21 @@ GeoCovUI <- function(id, title, dev) { and one or two others for latitude and longitude. Southern latitude and western longitude shall be noted with negative values."), bsCollapse( - id = ns("method"), + id = NS(id, "method"), bsCollapsePanel( title = "Use dataset's geographic variables", value = 1, tagList( - uiOutput(ns("site-ui")), - uiOutput(ns("latitude-ui")), + uiOutput(NS(id, "site-ui")), + uiOutput(NS(id, "latitude-ui")), div( - id = ns("latiWarn"), - textOutput(ns("latitude-warning")) + id = NS(id, "latiWarn"), + textOutput(NS(id, "latitude-warning")) ), - uiOutput(ns("longitude-ui")), + uiOutput(NS(id, "longitude-ui")), div( - id = ns("longWarn"), - textOutput(ns("longitude-warning")) + id = NS(id, "longWarn"), + textOutput(NS(id, "longitude-warning")) ) ) ), @@ -42,13 +42,13 @@ GeoCovUI <- function(id, title, dev) { fluidRow( column( 2, - actionButton(ns("addui"), "", icon("plus")), + actionButton(NS(id, "addui"), "", icon("plus")), ), column( 10, hidden( tags$div( - id = ns("slider_tips"), + id = NS(id, "slider_tips"), HTML("You can detail a more precise number by using the left/right (or down/up) arrows of your keyboard. Precision can be given at 0.01 °. Items can be removed by using the @@ -75,20 +75,12 @@ GeoCovUI <- function(id, title, dev) { #' @importFrom shinyjs onclick show #' #' @noRd -GeoCov <- function(input, output, session, save.variable, main.env, NSB) { +GeoCov <- function(id, main.env) { + moduleServer(id, function(input, output, session){ + save.variable <- main.env$save.variable ns <- session$ns - if (main.env$DEV) { - shinyjs::onclick("dev", - { - req(main.env$EAL$navigate == 5) - browser() - }, - asis = TRUE - ) - } - - # Variable initialization ----------------------------------------------------- + # Variable initialization ---- # Reactive Values rv <- reactiveValues( @@ -136,7 +128,7 @@ GeoCov <- function(input, output, session, save.variable, main.env, NSB) { } } - # Pre-fill ----------------------------------------------------- + # Pre-fill ---- # * Set choices ==== columns <- lapply( seq_along(save.variable$emlal$Attributes), @@ -230,7 +222,7 @@ GeoCov <- function(input, output, session, save.variable, main.env, NSB) { label = "EAL5 init choices" ) - # Input management ----------------------------------------------------- + # Input management ---- { # * Site description ---- output$`site-ui` <- renderUI({ @@ -248,7 +240,7 @@ GeoCov <- function(input, output, session, save.variable, main.env, NSB) { } selectInput( - ns("site"), + NS(id, "site"), "Choose a column for sites:", c("None" = "", rv$columns$choices$sites), selected = .site.name @@ -298,7 +290,7 @@ GeoCov <- function(input, output, session, save.variable, main.env, NSB) { # Update UI selectizeInput( - ns("latitude"), + NS(id, "latitude"), "Choose a column for latitude:", c("None" = "", rv$columns$choices$coords), selected = .lat.cols, @@ -334,7 +326,7 @@ GeoCov <- function(input, output, session, save.variable, main.env, NSB) { label = "EAL5 get latitude" ) - # * Longitude ----------------------------------------------------- + # * Longitude ---- output$`longitude-ui` <- renderUI({ isolate({ .lon.cols <- printReactiveValues(rv$columns$lon) @@ -355,7 +347,7 @@ GeoCov <- function(input, output, session, save.variable, main.env, NSB) { # Update UI selectizeInput( - ns("longitude"), + NS(id, "longitude"), "Choose a column for longitude:", c("None" = "", rv$columns$choices$coords), selected = .lon.cols, @@ -391,7 +383,7 @@ GeoCov <- function(input, output, session, save.variable, main.env, NSB) { ) } - # Fill custom ----------------------------------------------------- + # Fill custom ---- # * Setup ---- if (dim(rv$custom$coordinates)[1] > 0) { sapply(1:nrow(rv$custom$coordinates), function(ind) { @@ -415,7 +407,7 @@ GeoCov <- function(input, output, session, save.variable, main.env, NSB) { ) }) - # Saves ----------------------------------------------------- + # Saves ---- observeEvent( { rv$columns$site$col @@ -438,13 +430,17 @@ GeoCov <- function(input, output, session, save.variable, main.env, NSB) { ) observe({ - main.env$EAL$current[2] <- any( + main.env$EAL$completed <- any( isTRUE(rv$custom$complete), isTRUE(rv$columns$complete) ) }) - observeEvent(NSB$SAVE, + # observeEvent(NSB$SAVE, + shinyjs::onclick( + "fill-wizard-save", + asis = TRUE, + add = TRUE, { req(utils::tail(main.env$EAL$history, 1) == "Geographic Coverage") @@ -461,23 +457,23 @@ GeoCov <- function(input, output, session, save.variable, main.env, NSB) { ignoreInit = TRUE ) - # Process data ----------------------------------------------------- + # Process data ---- # * Previous ---- - observeEvent(NSB$PREV, + observeEvent(EAL$.prev, { - req(main.env$EAL$current[1] == "Geographic Coverage") + req(main.env$EAL$current == "Geographic Coverage") if (!"Categorical Variables" %in% main.env$EAL$history) { - main.env$EAL$navigate <- main.env$EAL$navigate - 1 + main.env$EAL$page <- main.env$EAL$page - 1 } }, ignoreInit = TRUE ) # * Next ---- - observeEvent(NSB$NEXT, + observeEvent(EAL$.next, { - req(main.env$EAL$current[1] == "Geographic Coverage") + req(main.env$EAL$current == "Geographic Coverage") # Create modal choices <- c( @@ -492,7 +488,7 @@ GeoCov <- function(input, output, session, save.variable, main.env, NSB) { tagList( "You are getting ready to proceed. Please select one of the following:", radioButtons( - ns("method"), + NS(id, "method"), "Method for Geographic Coverage:", choices = choices ) @@ -500,7 +496,7 @@ GeoCov <- function(input, output, session, save.variable, main.env, NSB) { easyClose = FALSE, footer = tagList( modalButton("Cancel"), - actionButton(ns("confirm"), "Proceed") + actionButton(NS(id, "confirm"), "Proceed") ) ) @@ -512,8 +508,8 @@ GeoCov <- function(input, output, session, save.variable, main.env, NSB) { observeEvent(input$confirm, { removeModal() - main.env$EAL$navigate <- 6 - NSB$tagList <- tagList() + main.env$EAL$page <- 6 + EAL$tag.list <- tagList() .method <- input$method @@ -529,6 +525,7 @@ GeoCov <- function(input, output, session, save.variable, main.env, NSB) { ) }, ignoreInit = TRUE) - # Output ----------------------------------------------------- + # Output ---- return(save.variable) +}) } diff --git a/R/eal_6_taxonomicCoverage.R b/R/eal_6_taxonomicCoverage.R index 526077f..044ddd1 100644 --- a/R/eal_6_taxonomicCoverage.R +++ b/R/eal_6_taxonomicCoverage.R @@ -2,21 +2,21 @@ #' @importFrom shinyjs hidden disabled #' #' @noRd -TaxCovUI <- function(id, title, dev) { +TaxCovUI <- function(id, main.env) { ns <- NS(id) - + return( fluidPage( fluidRow( column( 6, - uiOutput(ns("taxa.table")), - uiOutput(ns("taxa.col")) + uiOutput(NS(id, "taxa.table")), + uiOutput(NS(id, "taxa.col")) ), column( 6, - uiOutput(ns("taxa.name.type")), - uiOutput(ns("taxa.authority")) + uiOutput(NS(id, "taxa.name.type")), + uiOutput(NS(id, "taxa.authority")) ) ) ) # end of fluidPage @@ -30,291 +30,289 @@ TaxCovUI <- function(id, title, dev) { #' @importFrom shinyjs onclick #' #' @noRd -TaxCov <- function(input, output, session, - save.variable, main.env, NSB) { - ns <- session$ns - if (main.env$DEV) { - shinyjs::onclick("dev", - { - req(main.env$EAL$navigate == 6) - browser() - }, - asis = TRUE - ) - } - - # Variable Initialization ----------------------------------------------------- - rv <- reactiveValues( - taxa.table = character(), - taxa.col = character(), - taxa.name.type = character(), - taxa.authority = character(), - complete = FALSE - ) - - if (sapply(printReactiveValues(save.variable$emlal$TaxCov), checkTruth) %>% all()) { - rv$taxa.table <- save.variable$emlal$TaxCov$taxa.table - rv$taxa.col <- save.variable$emlal$TaxCov$taxa.col - rv$taxa.name.type <- save.variable$emlal$TaxCov$taxa.authority - rv$taxa.authority <- save.variable$emlal$TaxCov$taxa.authority - } - - # Set UI ==== - - # * taxa.table ==== - output$taxa.table <- renderUI({ - isolate({ - data.files <- basename(save.variable$emlal$DataFiles$datapath) - value <- rv$taxa.table - if(isFALSE(value %in% data.files)) - value <- NULL - }) +TaxCov <-function(id, main.env) { + moduleServer(id, function(input, output, session){ + save.variable <- main.env$save.variable + ns <- session$ns - selectInput( - ns("taxa.table"), - "Files containing taxonomic references", - choices = data.files, - selected = value, - multiple = FALSE + # Variable Initialization ---- + rv <- reactiveValues( + taxa.table = character(), + taxa.col = character(), + taxa.name.type = character(), + taxa.authority = character(), + complete = FALSE ) - }) - - # * taxa.col ==== - output$taxa.col <- renderUI({ - .ind <- match(rv$taxa.table, save.variable$emlal$DataFiles$name) - if(isTruthy(.ind)) { - choices <- isolate(save.variable$emlal$Attributes[[.ind]]$attributeName) - value <- isolate(rv$taxa.col) - if(isFALSE(value %in% choices)) - value <- NULL - .embed <- tagList - } - else { - choices <- NULL - value <- NULL - .embed <- shinyjs::disabled + + if (sapply(printReactiveValues(save.variable$emlal$TaxCov), checkTruth) %>% all()) { + rv$taxa.table <- save.variable$emlal$TaxCov$taxa.table + rv$taxa.col <- save.variable$emlal$TaxCov$taxa.col + rv$taxa.name.type <- save.variable$emlal$TaxCov$taxa.authority + rv$taxa.authority <- save.variable$emlal$TaxCov$taxa.authority } - .embed( + # Set UI ==== + + # * taxa.table ==== + output$taxa.table <- renderUI({ + isolate({ + data.files <- basename(save.variable$emlal$DataFiles$datapath) + value <- rv$taxa.table + if(isFALSE(value %in% data.files)) + value <- NULL + }) + selectInput( - ns("taxa.col"), - "Columns from selected files", - choices = choices, + NS(id, "taxa.table"), + "Files containing taxonomic references", + choices = data.files, + selected = value, + multiple = FALSE + ) + }) + + # * taxa.col ==== + output$taxa.col <- renderUI({ + .ind <- match(rv$taxa.table, save.variable$emlal$DataFiles$name) + if(isTruthy(.ind)) { + choices <- isolate(save.variable$emlal$Attributes[[.ind]]$attributeName) + value <- isolate(rv$taxa.col) + if(isFALSE(value %in% choices)) + value <- NULL + .embed <- tagList + } + else { + choices <- NULL + value <- NULL + .embed <- shinyjs::disabled + } + + .embed( + selectInput( + NS(id, "taxa.col"), + "Columns from selected files", + choices = choices, + selected = value + ) + ) + }) + + # * taxa.name.type ==== + output$taxa.name.type <- renderUI({ + isolate({ + value <- rv$taxa.name.type + if(isTRUE(value == "both")) + value <- c("scientific", "common") + else if(isFALSE(value %in% c("scientific", "common"))) + value <- NULL + }) + + checkboxGroupInput( + NS(id, "taxa.name.type"), + "Select one or both taxonomic name notation", + c("scientific", "common"), selected = value ) - ) - }) - - # * taxa.name.type ==== - output$taxa.name.type <- renderUI({ - isolate({ - value <- rv$taxa.name.type - if(isTRUE(value == "both")) - value <- c("scientific", "common") - else if(isFALSE(value %in% c("scientific", "common"))) - value <- NULL }) - checkboxGroupInput( - ns("taxa.name.type"), - "Select one or both taxonomic name notation", - c("scientific", "common"), - selected = value + # * taxa.authority ==== + output$taxa.authority <- renderUI({ + isolate({ + taxa.authority <- main.env$FORMATS$taxa.authorities + choices <- taxa.authority$authority + value <- if(isTruthy(rv$taxa.authority)){ + taxa.authority %>% + dplyr::filter(id == rv$taxa.authority) %>% + dplyr::select(authority) + } + }) + + selectInput( + NS(id, "taxa.authority"), + "Select taxonomic authority.ies", + choices = choices, + selected = value, + multiple = TRUE + ) + }) + + # Taxonomic coverage input ---- + + # * Taxa files ==== + observeEvent(input$taxa.table, + { + # invalid-selected/no value(s) + if (!isTruthy(input$taxa.table)) { + shinyjs::disable("taxa.col") + + updateSelectizeInput( + session, + "taxa.col", + choices = list("(None selected)" = NULL) + ) + } + # valid-selected value(s) + else { + shinyjs::enable("taxa.col") + + taxa.col.list <- lapply(input$taxa.table, function(file) { + all.files <- save.variable$emlal$DataFiles + file <- all.files[all.files$name == file, "datapath"] + df <- readDataTable(file, stringsAsFactors = FALSE) + return(colnames(df)) + }) + names(taxa.col.list) <- input$taxa.table + + .update.var <- if (isTRUE(rv$taxa.col %in% taxa.col.list)) + rv$taxa.col + else + NULL + + updateSelectizeInput( + session, + "taxa.col", + choices = taxa.col.list, + selected = .update.var + ) + } + + # save + rv$taxa.table <- list(input$taxa.table) + isolate({save.variable$emlal$TaxCov$taxa.table <- rv$taxa.table}) + }, + priority = -1 ) - }) - - # * taxa.authority ==== - output$taxa.authority <- renderUI({ - isolate({ - taxa.authority <- main.env$FORMATS$taxa.authorities - choices <- taxa.authority$authority - value <- if(isTruthy(rv$taxa.authority)){ - taxa.authority %>% - dplyr::filter(id == rv$taxa.authority) %>% - dplyr::select(authority) + + # * Taxa columns to read ==== + observeEvent(input$taxa.col, { + req(input$taxa.col) + + rv$taxa.col <- input$taxa.col + isolate({save.variable$emlal$TaxCov$taxa.col <- rv$taxa.col}) + }) + + # * Taxa type ==== + observeEvent(input$taxa.name.type, { + req(input$taxa.name.type) + + rv$taxa.name.type <- input$taxa.name.type + + if ("scientific" %in% rv$taxa.name.type && + "common" %in% rv$taxa.name.type) { + rv$taxa.name.type <- "both" } + save.variable$emlal$TaxCov$taxa.name.type <- rv$taxa.name.type + }) + + # * Taxa authority ==== + observeEvent(input$taxa.authority, { + req(input$taxa.authority) + + rv$taxa.authority <- main.env$FORMATS$taxa.authorities %>% + dplyr::filter(authority %in% input$taxa.authority) %>% + dplyr::select(id) %>% + unlist() + save.variable$emlal$TaxCov$taxa.authority <- rv$taxa.authority + }) + + # Saves ---- + main.env$EAL$completed <- TRUE + observe({ + req(main.env$EAL$current == "Taxonomic Coverage") + + rv$complete <- all( + length(rv$taxa.table) > 0 && + length(rv$taxa.col) > 0 && + length(rv$taxa.name.type) > 0 && + length(rv$taxa.authority) > 0 + ) }) - selectInput( - ns("taxa.authority"), - "Select taxonomic authority.ies", - choices = choices, - selected = value, - multiple = TRUE + + # observeEvent(NSB$SAVE, + shinyjs::onclick( + "fill-wizard-save", + asis = TRUE, + add = TRUE, + { + req(utils::tail(main.env$EAL$history, 1) == "Taxonomic Coverage") + + save.variable <- saveReactive( + save.variable = savevar, + rv = list(TaxCov = rv) + ) + }, + ignoreInit = TRUE ) - }) - - # Taxonomic coverage input ----------------------------------------------------- - - # * Taxa files ==== - observeEvent(input$taxa.table, - { - # invalid-selected/no value(s) - if (!isTruthy(input$taxa.table)) { - shinyjs::disable("taxa.col") - - updateSelectizeInput( - session, - "taxa.col", - choices = list("(None selected)" = NULL) + + # Process data ---- + observeEvent(EAL$.next, + { + req(main.env$EAL$current == "Taxonomic Coverage") + + choices <- c( + "Yes - Taxonomic coverage will be written as file" = if (rv$complete) 1 else NULL, + "No - Taxonomic coverage will be left blank" = 0 ) - } - # valid-selected value(s) - else { - shinyjs::enable("taxa.col") - taxa.col.list <- lapply(input$taxa.table, function(file) { - all.files <- save.variable$emlal$DataFiles - file <- all.files[all.files$name == file, "datapath"] - df <- readDataTable(file, stringsAsFactors = FALSE) - return(colnames(df)) - }) - names(taxa.col.list) <- input$taxa.table - - .update.var <- if (isTRUE(rv$taxa.col %in% taxa.col.list)) - rv$taxa.col - else - NULL - - updateSelectizeInput( - session, - "taxa.col", - choices = taxa.col.list, - selected = .update.var + nextTabModal <- modalDialog( + title = "Proceed Taxonomic Coverage", + tagList( + "You are getting ready to proceed.", + radioButtons( + NS(id, "filled"), + "Is Taxonomic Coverage filled?", + choices = choices + ) + ), + footer = tagList( + modalButton("Cancel"), + actionButton(NS(id, "confirm"), "Proceed") + ) ) - } - - # save - rv$taxa.table <- list(input$taxa.table) - isolate({save.variable$emlal$TaxCov$taxa.table <- rv$taxa.table}) - }, - priority = -1 - ) - - # * Taxa columns to read ==== - observeEvent(input$taxa.col, { - req(input$taxa.col) - - rv$taxa.col <- input$taxa.col - isolate({save.variable$emlal$TaxCov$taxa.col <- rv$taxa.col}) - }) - - # * Taxa type ==== - observeEvent(input$taxa.name.type, { - req(input$taxa.name.type) - - rv$taxa.name.type <- input$taxa.name.type - - if ("scientific" %in% rv$taxa.name.type && - "common" %in% rv$taxa.name.type) { - rv$taxa.name.type <- "both" - } - save.variable$emlal$TaxCov$taxa.name.type <- rv$taxa.name.type - }) - - # * Taxa authority ==== - observeEvent(input$taxa.authority, { - req(input$taxa.authority) - - rv$taxa.authority <- main.env$FORMATS$taxa.authorities %>% - dplyr::filter(authority %in% input$taxa.authority) %>% - dplyr::select(id) %>% - unlist() - save.variable$emlal$TaxCov$taxa.authority <- rv$taxa.authority - }) - - # Saves ----------------------------------------------------- - main.env$EAL$current[2] <- TRUE - observe({ - req(main.env$EAL$current[1] == "Taxonomic Coverage") - - rv$complete <- all( - length(rv$taxa.table) > 0 && - length(rv$taxa.col) > 0 && - length(rv$taxa.name.type) > 0 && - length(rv$taxa.authority) > 0 + + showModal(nextTabModal) + }, + ignoreInit = TRUE ) - }) - - observeEvent(NSB$SAVE, - { - req(utils::tail(main.env$EAL$history, 1) == "Taxonomic Coverage") - - save.variable <- saveReactive( - save.variable = savevar, - rv = list(TaxCov = rv) - ) - }, - ignoreInit = TRUE - ) - - # Process data ----------------------------------------------------- - observeEvent(NSB$NEXT, - { - req(main.env$EAL$current[1] == "Taxonomic Coverage") - - choices <- c( - "Yes - Taxonomic coverage will be written as file" = if (rv$complete) 1 else NULL, - "No - Taxonomic coverage will be left blank" = 0 - ) - - nextTabModal <- modalDialog( - title = "Proceed Taxonomic Coverage", - tagList( - "You are getting ready to proceed.", - radioButtons( - ns("filled"), - "Is Taxonomic Coverage filled?", - choices = choices + + observeEvent(input$confirm, { + removeModal() + main.env$EAL$page <- 7 + EAL$tag.list <- tagList() + + # Write files + if (input$filled == "1") { + save.variable <- saveReactive( + save.variable, + rv = list(TaxCov = rv) + ) + + # Template coverage + try( + template_taxonomic_coverage( + save.variable$emlal$SelectDP$dp.metadata.path, + save.variable$emlal$SelectDP$dp.data.path, + taxa.table = rv$taxa.table, + taxa.col = rv$taxa.col, + taxa.name.type = rv$taxa.name.type, + taxa.authority = rv$taxa.authority ) - ), - footer = tagList( - modalButton("Cancel"), - actionButton(ns("confirm"), "Proceed") ) - ) - - showModal(nextTabModal) - }, - ignoreInit = TRUE - ) - - observeEvent(input$confirm, { - removeModal() - main.env$EAL$navigate <- 7 - NSB$tagList <- tagList() - - # Write files - if (input$filled == "1") { - save.variable <- saveReactive( - save.variable, - rv = list(TaxCov = rv) - ) - - # Template coverage - try( - template_taxonomic_coverage( - save.variable$emlal$SelectDP$dp.metadata.path, - save.variable$emlal$SelectDP$dp.data.path, - taxa.table = rv$taxa.table, - taxa.col = rv$taxa.col, - taxa.name.type = rv$taxa.name.type, - taxa.authority = rv$taxa.authority + showNotification( + "Taxonomic Coverage has been written.", + type = "message" ) - ) - showNotification( - "Taxonomic Coverage has been written.", - type = "message" - ) - } - else { - showNotification( - "Taxonomic Coverage has been skipped.", - type = "message" - ) - } + } + else { + showNotification( + "Taxonomic Coverage has been skipped.", + type = "message" + ) + } + }) + + # Output ---- + return(save.variable) }) - - # Output ----------------------------------------------------- - return(save.variable) } diff --git a/R/eal_7_personnel.R b/R/eal_7_personnel.R index 67681f7..b157c84 100644 --- a/R/eal_7_personnel.R +++ b/R/eal_7_personnel.R @@ -1,14 +1,14 @@ #' @import shiny #' @noRd -PersonnelUI <- function(id, title, dev) { +PersonnelUI <- function(id, main.env) { ns <- NS(id) - + return( fluidPage( fluidRow( column( 2, - actionButton(ns("addui"), "", icon("plus")) + actionButton(NS(id, "addui"), "", icon("plus")) ), column( 10, @@ -22,7 +22,7 @@ PersonnelUI <- function(id, title, dev) { fill the remaining fields.

") ) ), - tags$div(id = ns("inserthere")) + tags$div(id = NS(id, "inserthere")) ) # end of fluidPage ) # end of return } @@ -32,180 +32,177 @@ PersonnelUI <- function(id, title, dev) { #' @importFrom data.table fwrite #' #' @noRd -Personnel <- function(input, output, session, save.variable, main.env, NSB) { - ns <- session$ns - - if (main.env$DEV) { - shinyjs::onclick("dev", - { - req(main.env$EAL$navigate == 7) - browser() - }, - asis = TRUE +Personnel <- function(id, main.env) { + moduleServer(id, function(input, output, session){ + save.variable <- main.env$save.variable + ns <- session$ns + + # Variable initialization ---- + rv <- reactiveValues( + Personnel = data.frame( + id = numeric(), + # Basic Identity + givenName = character(), + middleInitial = character(), + surName = character(), + # Contact + organizationName = character(), + electronicMailAddress = character(), + # Personnel information + userId = character(), + role = character(), + # Project information + projectTitle = character(), + fundingAgency = character(), + fundingNumber = character(), + stringsAsFactors = FALSE + ) ) - } - - # Variable initialization ----------------------------------------------------- - rv <- reactiveValues( - Personnel = data.frame( - id = numeric(), - # Basic Identity - givenName = character(), - middleInitial = character(), - surName = character(), - # Contact - organizationName = character(), - electronicMailAddress = character(), - # Personnel information - userId = character(), - role = character(), - # Project information - projectTitle = character(), - fundingAgency = character(), - fundingNumber = character(), - stringsAsFactors = FALSE + + personnel.file <- dir( + save.variable$emlal$SelectDP$dp.metadata.path, + pattern = "ersonnel", + full.names = TRUE ) - ) - - personnel.file <- dir( - save.variable$emlal$SelectDP$dp.metadata.path, - pattern = "ersonnel", - full.names = TRUE - ) - saved.table <- if (isTruthy(personnel.file)) { - data.table::fread(personnel.file, data.table = FALSE, stringsAsFactors = FALSE) - } else if (isTruthy(unlist(save.variable$emlal$Personnel))) { - isolate(save.variable$emlal$Personnel) - } else { - NULL - } - saved.table[is.na(saved.table)] <- "" - if (checkTruth(saved.table)) { - saved.table$id <- c( - saved.table$role[1:2], - seq_along(saved.table$givenName)[-(1:2)] - ) - isolate(rv$Personnel <- saved.table) - - sapply(rv$Personnel$id, function(rvid) { + saved.table <- if (isTruthy(personnel.file)) { + data.table::fread(personnel.file, data.table = FALSE, stringsAsFactors = FALSE) + } else if (isTruthy(unlist(save.variable$emlal$Personnel))) { + isolate(save.variable$emlal$Personnel) + } else { + NULL + } + saved.table[is.na(saved.table)] <- "" + if (checkTruth(saved.table)) { + saved.table$id <- c( + saved.table$role[1:2], + seq_along(saved.table$givenName)[-(1:2)] + ) + isolate(rv$Personnel <- saved.table) + + sapply(rv$Personnel$id, function(rvid) { + rv <- insertPersonnelInput( + rvid, + rv, + ns, + main.env, + role = if (rvid %in% c("creator", "contact")) rvid, + saved = saved.table + ) + return() + }) + } else { # New rv <- insertPersonnelInput( - rvid, + "creator", rv, ns, main.env, - role = if (rvid %in% c("creator", "contact")) rvid, + role = "creator", + saved = saved.table + ) + + rv <- insertPersonnelInput( + "contact", + rv, + ns, + main.env, + role = "contact", saved = saved.table ) - return() - }) - } else { # New - rv <- insertPersonnelInput( - "creator", - rv, - ns, - main.env, - role = "creator", - saved = saved.table - ) - - rv <- insertPersonnelInput( - "contact", - rv, - ns, - main.env, - role = "contact", - saved = saved.table - ) - } - - # Fill Personnel ----------------------------------------------------- - observeEvent(input$addui, { - id <- dim(rv$Personnel[-c(1:2), ])[1] + 1 - while (as.character(id) %in% rv$Personnel$id) { - id <- id + 1 } - rv <- insertPersonnelInput( - as.character(id), - rv, - ns, - main.env + + # Fill Personnel ---- + observeEvent(input$addui, { + id <- dim(rv$Personnel[-c(1:2), ])[1] + 1 + while (as.character(id) %in% rv$Personnel$id) { + id <- id + 1 + } + rv <- insertPersonnelInput( + as.character(id), + rv, + ns, + main.env + ) + }) + + # Saves ---- + observe({ + main.env$EAL$completed <- all( + # Personnel + isTruthy(rv$Personnel$givenName) && + isTruthy(rv$Personnel$surName) && + isTruthy(rv$Personnel$organizationName) && + isTruthy(rv$Personnel$electronicMailAddress) && + all(c("creator", "contact") %in% rv$Personnel$role) + ) + }) + + # observeEvent(NSB$SAVE, + shinyjs::onclick( + "fill-wizard-save", + asis = TRUE, + add = TRUE, + { + req(main.env$EAL$current == "Personnel") + + # save + save.variable <- saveReactive( + save.variable = savevar, + rv = list(Personnel = rv) + ) + }, + ignoreInit = TRUE ) - }) - - # Saves ----------------------------------------------------- - observe({ - main.env$EAL$current[2] <- all( - # Personnel - isTruthy(rv$Personnel$givenName) && - isTruthy(rv$Personnel$surName) && - isTruthy(rv$Personnel$organizationName) && - isTruthy(rv$Personnel$electronicMailAddress) && - all(c("creator", "contact") %in% rv$Personnel$role) + + # Process data ---- + observeEvent(EAL$.next, + { + req(checkTruth(rv$Personnel)) + req(main.env$EAL$current == "Personnel") + + save.variable <- saveReactive( + save.variable, + rv = list(Personnel = rv) + ) + }, + priority = 1, + ignoreInit = TRUE ) + + # Output ---- + return(save.variable) }) - - observeEvent(NSB$SAVE, - { - req(main.env$EAL$current[1] == "Personnel") - - # save - save.variable <- saveReactive( - save.variable = savevar, - rv = list(Personnel = rv) - ) - }, - ignoreInit = TRUE - ) - - # Process data ----------------------------------------------------- - observeEvent(NSB$NEXT, - { - req(checkTruth(rv$Personnel)) - req(main.env$EAL$current == "Personnel") - - save.variable <- saveReactive( - save.variable, - rv = list(Personnel = rv) - ) - }, - priority = 1, - ignoreInit = TRUE - ) - - # Output ----------------------------------------------------- - return(save.variable) } #' @import shiny #' #' @noRd insertPersonnelInput <- function(id, rv, ns, main.env, role = NULL, saved = NULL) { - - # initialize IDs ----------------------------------------------------- + + # initialize IDs ---- div.id <- id site.id <- paste0("site_", id) rmv.id <- paste0("rmv_", id) - - # Proper module server ----------------------------------------------------- + + # Proper module server ---- # insert new UI newUI <- PersonnelModUI( ns(id), div.id, site.id, rmv.id, role = role, saved = saved ) insertUI( - selector = paste0("#", ns("inserthere")), + selector = paste0("#", NS(id, "inserthere")), ui = newUI ) - + # create associated server - rv <- callModule( - PersonnelMod, id, # module args + rv <- PersonnelMod( + id, main.env, rv, # reactiveValues rmv.id, site.id, div.id, # renderUI ids role = role, saved = saved # set saved ) - - # Output ----------------------------------------------------- + + # Output ---- return(rv) } @@ -213,30 +210,30 @@ insertPersonnelInput <- function(id, rv, ns, main.env, role = NULL, saved = NULL #' #' @noRd PersonnelModUI <- function(id, div.id, site.id, rmv.id, - role = NULL, saved = NULL) { + role = NULL, saved = NULL) { ns <- NS(id) - + value <- if (checkTruth(saved)) { saved[saved$id == div.id, ] } else { NULL } - + # set Project Information embedding tag .pi.embed <- if (!is.null(role)) { shinyjs::hidden } else { shiny::tagList } - + tags$div( id = site.id, fluidRow( class = "inputBox", - # Form ----------------------------------------------------- + # Form ---- # column(11, tagList( - # * (ORCID) Personnel identification ----------------------------------------------------- + # * (ORCID) Personnel identification ---- fluidRow( class = "topInputRow", column( @@ -245,7 +242,7 @@ PersonnelModUI <- function(id, div.id, site.id, rmv.id, 4, if (is.null(role)) { selectInput( - ns("role"), + NS(id, "role"), c("creator", "PI (principal investigator)", "contact", "(other)"), label = withRedStar("Role"), selected = if (!is.null(value)) { @@ -266,12 +263,12 @@ PersonnelModUI <- function(id, div.id, site.id, rmv.id, 4, shinyjs::hidden( div( - id = ns("role-other"), + id = NS(id, "role-other"), textInput( - ns("role-other"), + NS(id, "role-other"), label = "Title of the custom role", value = if (!is.null(value) && - !value$role %in% c("creator", "PI (principal investigator)", "contact")) { + !value$role %in% c("creator", "PI (principal investigator)", "contact")) { value$role } else { "" @@ -283,7 +280,7 @@ PersonnelModUI <- function(id, div.id, site.id, rmv.id, column( 4, textInput( - ns("userId"), + NS(id, "userId"), label = "ORCID", value = if (!is.null(value)) value$userId else "" ) @@ -301,13 +298,13 @@ PersonnelModUI <- function(id, div.id, site.id, rmv.id, style = "padding-left: 0" ) ), # end of fluidRow 1 - # * Basic identity ----------------------------------------------------- + # * Basic identity ---- fluidRow( style = "padding:5px", column( 4, textInput( - ns("givenName"), + NS(id, "givenName"), label = withRedStar("First name"), value = if (!is.null(value)) value$givenName else "" ) @@ -315,7 +312,7 @@ PersonnelModUI <- function(id, div.id, site.id, rmv.id, column( 4, textInput( - ns("middleInitial"), + NS(id, "middleInitial"), label = "Middle initial", value = if (!is.null(value)) value$middleInitial else "" ) @@ -323,19 +320,19 @@ PersonnelModUI <- function(id, div.id, site.id, rmv.id, column( 4, textInput( - ns("surName"), + NS(id, "surName"), label = withRedStar("Last name"), value = if (!is.null(value)) value$surName else "" ) ) ), # end of fluidRow 1 - # * Contact ----------------------------------------------------- + # * Contact ---- fluidRow( style = "padding:5px", column( 8, textInput( - ns("organizationName"), + NS(id, "organizationName"), label = withRedStar("Name of organization the person is associated with."), value = if (!is.null(value)) value$organizationName else "" ) @@ -343,13 +340,13 @@ PersonnelModUI <- function(id, div.id, site.id, rmv.id, column( 4, textInput( - ns("electronicMailAddress"), + NS(id, "electronicMailAddress"), label = withRedStar("Email address"), value = if (!is.null(value)) value$electronicMailAddress else "" ) ) ), # end of fluidRow 2 - # * Project information ----------------------------------------------------- + # * Project information ---- .pi.embed( div( style = "padding:5px", @@ -358,7 +355,7 @@ PersonnelModUI <- function(id, div.id, site.id, rmv.id, column( 4, textInput( - ns("projectTitle"), + NS(id, "projectTitle"), label = "Project title for this dataset", value = if (!is.null(value)) value$projectTitle else "" ) @@ -366,7 +363,7 @@ PersonnelModUI <- function(id, div.id, site.id, rmv.id, column( 4, textInput( - ns("fundingAgency"), + NS(id, "fundingAgency"), label = "Entity funding the creation of this dataset", value = if (!is.null(value)) value$fundingAgency else "" ) @@ -374,7 +371,7 @@ PersonnelModUI <- function(id, div.id, site.id, rmv.id, column( 4, textInput( - ns("fundingNumber"), + NS(id, "fundingNumber"), label = "Number of the grant or award that supported creation of this dataset", value = if (!is.null(value)) value$fundingNumber else "" ) @@ -393,16 +390,16 @@ PersonnelModUI <- function(id, div.id, site.id, rmv.id, #' #' @noRd PersonnelMod <- function(input, output, session, main.env, - rv, rmv.id, site.id, ref, role = NULL, saved = NULL) { + rv, rmv.id, site.id, ref, role = NULL, saved = NULL) { ns <- session$ns - - # Variable initialization ----------------------------------------------------- + + # Variable initialization ---- if (!is.null(saved)) { value <- saved[saved$id == ref, ] } else { value <- NULL } - + local.rv <- reactiveValues( id = ref, # Basic Identity @@ -421,46 +418,46 @@ PersonnelMod <- function(input, output, session, main.env, fundingAgency = if (!is.null(value)) value$fundingAgency else NA, fundingNumber = if (!is.null(value)) value$fundingNumber else NA ) - - # * Basic Identity ----------------------------------------------------- + + # * Basic Identity ---- name.pattern <- main.env$PATTERNS$name - + observeEvent(input$givenName, { local.rv$givenName <- if (grepl(name.pattern, input$givenName)) { input$givenName } }) - + observeEvent(input$middleInitial, { local.rv$middleInitial <- input$middleInitial }) - + observeEvent(input$surName, { local.rv$surName <- if (grepl(name.pattern, input$surName)) { input$surName } }) - - # * Contact ----------------------------------------------------- + + # * Contact ---- mail.pattern <- main.env$PATTERNS$email - + observeEvent(input$organizationName, { local.rv$organizationName <- input$organizationName }) - + observeEvent(input$electronicMailAddress, { local.rv$electronicMailAddress <- if (grepl(mail.pattern, input$electronicMailAddress)) { input$electronicMailAddress } }) - - # * (ORCID) Personnel identification ----------------------------------------------------- + + # * (ORCID) Personnel identification ---- orcid.pattern <- main.env$PATTERNS$ORCID - + observeEvent(input$userId, { req(input$userId) local.rv$userId <- input$userId - + if (grepl(orcid.pattern, input$userId)) { local.rv$userId <- stringr::str_extract(local.rv$userId, orcid.pattern) updateTextInput( @@ -469,20 +466,20 @@ PersonnelMod <- function(input, output, session, main.env, value = local.rv$userId ) } - + orcid.connect <- try( rorcid::as.orcid( local.rv$userId #TODO ORCID auth % snake ) ) - + if ( grepl(orcid.pattern, input$userId) && isTruthy(orcid.connect) ) { orcid <- local.rv$userId orcid.info <- list() - + # names orcid.info$names <- rorcid::orcid_person(orcid)[[orcid]]$name if (isTruthy(unlist(orcid.info$names$`given-names`$value))) { @@ -493,7 +490,7 @@ PersonnelMod <- function(input, output, session, main.env, local.rv$surName <- orcid.info$names$`family-name`$value updateTextInput(session, "surName", value = local.rv$surName) } - + # organization orcid.info$employment <- rorcid::orcid_employments(orcid)[[orcid]]$`affiliation-group`$summaries[[1]] if (isTruthy(unlist(orcid.info$employment$`employment-summary.organization.name`))) { @@ -501,20 +498,20 @@ PersonnelMod <- function(input, output, session, main.env, updateTextInput(session, "organizationName", value = local.rv$organizationName) } if (is.null(role) && - isTruthy(unlist(orcid.info$employment$`employment-summary.role-title`))) { + isTruthy(unlist(orcid.info$employment$`employment-summary.role-title`))) { local.rv$role <- "(other)" updateTextInput(session, "role", value = local.rv$role) local.rv$`role-other` <- orcid.info$employment$`employment-summary.role-title` updateTextInput(session, "role-other", value = local.rv$`role-other`) } - + # email orcid.info$email <- rorcid::orcid_email(orcid)[[orcid]]$email if (isTruthy(unlist(orcid.info$email$email))) { local.rv$electronicMailAddress <- orcid.info$email$email updateTextInput(session, "electronicMailAddress", value = local.rv$electronicMailAddress) } - + # fundings if (local.rv$role == "PI (principal investigator)") { orcid.info$fundings <- rorcid::orcid_fundings(orcid)[[orcid]]$group$`funding-summary`[[1]] @@ -533,14 +530,14 @@ PersonnelMod <- function(input, output, session, main.env, } } else { showNotification( - id = ns("invalid_userid"), + id = NS(id, "invalid_userid"), "Input 'userId' is not a valid ORCID.", type = "warning" ) } }) - - # * Project information ----------------------------------------------------- + + # * Project information ---- if (is.null(role)) { observeEvent( { @@ -569,19 +566,19 @@ PersonnelMod <- function(input, output, session, main.env, }, ignoreInit = FALSE ) - + observeEvent(input$projectTitle, { if (input$role == "PI (principal investigator)") { local.rv$projectTitle <- input$projectTitle } }) - + observeEvent(input$fundingAgency, { if (input$role == "PI (principal investigator)") { local.rv$fundingAgency <- input$fundingAgency } }) - + observeEvent(input$fundingNumber, { if (input$role == "PI (principal investigator)") { local.rv$fundingNumber <- input$fundingNumber @@ -593,13 +590,13 @@ PersonnelMod <- function(input, output, session, main.env, local.rv$fundingAgency <- "" local.rv$fundingNumber <- "" } - - # Metadata save ----------------------------------------------------- + + # Metadata save ---- observe({ req( !is.null(role) || (any(grepl(rmv.id, names(input))) && - input[[rmv.id]] < 1) + input[[rmv.id]] < 1) ) personnel <- isolate(rv$Personnel) # Fetch correct index @@ -609,26 +606,26 @@ PersonnelMod <- function(input, output, session, main.env, else { dim(personnel)[1] + 1 } - + # print values into rv at selected index .values <- printReactiveValues(local.rv) .values <- .values[colnames(personnel)] .values[which(!sapply(.values, isTruthy))] <- "" isolate(rv$Personnel[ind, ] <- .values) }) - - # Remove UI ----------------------------------------------------- + + # Remove UI ---- if (is.null(role)) { observeEvent(input$rmv.id, { # unload the RV ind <- match(ref, rv$Personnel$id) rv$Personnel <- rv$Personnel %>% slice(-ind) - + # remove the UI removeUI(selector = paste0("#", site.id), immediate = TRUE) }) } - - # Output ----------------------------------------------------- + + # Output ---- return(rv) } diff --git a/R/eal_8_misc.R b/R/eal_8_misc.R index 1731989..74814a4 100644 --- a/R/eal_8_misc.R +++ b/R/eal_8_misc.R @@ -3,20 +3,25 @@ #' @importFrom data.table fread #' #' @noRd -MiscUI <- function(id, title, dev, save.variable) { +MiscUI <- function(id, main.env) { ns <- NS(id) - - keywords <- fread( - paste0(save.variable$emlal$SelectDP$dp.metadata.path, "/keywords.txt"), - data.table = FALSE, stringsAsFactors = FALSE - ) + + .metadata.path <- isolate(main.env$save.variable$emlal$SelectDP$dp.metadata.path) + + if(file.exists(paste0(.metadata.path, "/keywords.txt"))) + keywords <- data.table::fread( + paste0(.metadata.path, "/keywords.txt"), + data.table = FALSE, stringsAsFactors = FALSE + ) + else + keywords <- "" if (checkTruth(keywords)) { kw <- keywords$keyword %>% strsplit(split = ",") %>% unlist %>% paste(collapse = ",") } - + return( fluidPage( fluidRow( @@ -28,33 +33,35 @@ MiscUI <- function(id, title, dev, save.variable) { "), bsCollapse( - id = ns("Miscs"), - - # * Abstract ----------------------------------------------------- + id = NS(id, "Miscs"), + + # * Abstract ---- bsCollapsePanel( title = withRedStar("Abstract"), value = 1, MiscellaneousUI( - ns("abstract"), - value = readPlainText( - paste0(save.variable$emlal$SelectDP$dp.metadata.path, "/abstract.txt") - ) + NS(id, "abstract"), + value = if(file.exists(paste0(.metadata.path, "/abstract.txt"))) + readPlainText( + paste0(.metadata.path, "/abstract.txt") + ) ) ), - - # * Methods ----------------------------------------------------- + + # * Methods ---- bsCollapsePanel( title = withRedStar("Methods"), value = 2, MiscellaneousUI( - ns("methods"), - value = readPlainText( - paste0(save.variable$emlal$SelectDP$dp.metadata.path, "/methods.txt") - ) + NS(id, "methods"), + value = if(file.exists(paste0(.metadata.path, "/methods.txt"))) + readPlainText( + paste0(.metadata.path, "/methods.txt") + ) ) ), - - # * Keywords ----------------------------------------------------- + + # * Keywords ---- bsCollapsePanel( title = withRedStar("Keywords"), value = 3, @@ -62,7 +69,7 @@ MiscUI <- function(id, title, dev, save.variable) { column( 6, tagsinput::tagsTextInput( - ns("keywords"), + NS(id, "keywords"), tags$p("List the keywords that best describe your dataset. Type a 'tab' to separate each keyword."), value = if (checkTruth(keywords)) keywords[, 1] else c() @@ -75,12 +82,12 @@ MiscUI <- function(id, title, dev, save.variable) { no control is made about thesaurus input field and this can be invalided."), tags$p("You may associate a thesaurus to each keyword."), - uiOutput(ns("thesaurus")) + uiOutput(NS(id, "thesaurus")) ) ) ), - - # * Temporal coverage ----------------------------------------------------- + + # * Temporal coverage ---- bsCollapsePanel( title = "Temporal coverage", value = 4, @@ -88,7 +95,7 @@ MiscUI <- function(id, title, dev, save.variable) { column(10, offset = 1, dateRangeInput( - ns("temporal_coverage"), + NS(id, "temporal_coverage"), "Dates between which dataset's content was produced", max = Sys.Date(), autoclose = FALSE @@ -96,19 +103,20 @@ MiscUI <- function(id, title, dev, save.variable) { ) ) ), - - # * Additional Info ----------------------------------------------------- + + # * Additional Info ---- bsCollapsePanel( title = "Additional Info", value = 5, MiscellaneousUI( - ns("additional.information"), + NS(id, "additional.information"), help.label = tags$p( "If you have additional information that doesn't fall under the scope of the abstract or methods (e.g. a list of research articles or theses derived from this dataset) about your dataset, you may share it here." ), - value = readPlainText( - paste0(save.variable$emlal$SelectDP$dp.metadata.path, "/additional_info.txt") - ) + value = if(file.exists(paste0(.metadata.path, "/additional_info.txt"))) + readPlainText( + paste0(.metadata.path, "/additional_info.txt") + ) ) ) ) @@ -123,176 +131,170 @@ MiscUI <- function(id, title, dev, save.variable) { #' @importFrom data.table fread #' #' @noRd -Misc <- function(input, output, session, save.variable, main.env, NSB) { - ns <- session$ns - - if (main.env$DEV) { - shinyjs::onclick("dev", - { - req(main.env$EAL$navigate == 8) - browser() - }, - asis = TRUE +Misc <- function(id, main.env) { + moduleServer(id, function(input, output, session){ + save.variable <- main.env$save.variable + ns <- session$ns + + # Variable initialization ---- + kw <- fread( + paste0(save.variable$emlal$SelectDP$dp.metadata.path, "/keywords.txt"), + data.table = FALSE, stringsAsFactors = FALSE ) - } - - # Variable initialization ----------------------------------------------------- - kw <- fread( - paste0(save.variable$emlal$SelectDP$dp.metadata.path, "/keywords.txt"), - data.table = FALSE, stringsAsFactors = FALSE - ) - - rv <- reactiveValues( - # Abstract - abstract = reactiveValues( - content = character(), - file = paste( - isolate(save.variable$emlal$SelectDP$dp.metadata.path), - "abstract.txt", - sep = "/" - ) - ), - # Methods - methods = reactiveValues( - content = character(), - file = paste( - isolate(save.variable$emlal$SelectDP$dp.metadata.path), - "methods.txt", - sep = "/" - ) - ), - # Keywords - keywords = reactiveValues( - keyword = kw$keyword, - keyword.thesaurus = kw$keyword.thesaurus - ), - # Temporal coverage - temporal.coverage = c(Sys.Date() - 1, Sys.Date()), - # Additional information - additional.information = reactiveValues( - content = character(), - file = paste( - isolate(save.variable$emlal$SelectDP$dp.metadata.path), - "additional_info.txt", - sep = "/" + + rv <- reactiveValues( + # Abstract + abstract = reactiveValues( + content = character(), + file = paste( + isolate(save.variable$emlal$SelectDP$dp.metadata.path), + "abstract.txt", + sep = "/" + ) + ), + # Methods + methods = reactiveValues( + content = character(), + file = paste( + isolate(save.variable$emlal$SelectDP$dp.metadata.path), + "methods.txt", + sep = "/" + ) + ), + # Keywords + keywords = reactiveValues( + keyword = kw$keyword, + keyword.thesaurus = kw$keyword.thesaurus + ), + # Temporal coverage + temporal.coverage = c(Sys.Date() - 1, Sys.Date()), + # Additional information + additional.information = reactiveValues( + content = character(), + file = paste( + isolate(save.variable$emlal$SelectDP$dp.metadata.path), + "additional_info.txt", + sep = "/" + ) ) ) - ) - - # Fill ----------------------------------------------------- - # * Abstract ==== - rv$abstract <- callModule( - Miscellaneous, - "abstract", - save.variable, - rv = rv$abstract - ) - - # * Methods ==== - rv$methods <- callModule( - Miscellaneous, - "methods", - save.variable, - rv = rv$methods - ) - - # * Keywords ==== - observeEvent(input$keywords, { - req(input$keywords) - - rv$keywords$keyword <- unique(input$keywords) - - output$thesaurus <- renderUI({ + + # Fill ---- + # * Abstract ==== + rv$abstract <- Miscellaneous( + "abstract", + save.variable, + rv = rv$abstract + ) + + # * Methods ==== + rv$methods <- Miscellaneous( + "methods", + save.variable, + rv = rv$methods + ) + + # * Keywords ==== + observeEvent(input$keywords, { + req(input$keywords) + + rv$keywords$keyword <- unique(input$keywords) + + output$thesaurus <- renderUI({ + validate( + need(checkTruth(rv$keywords$keyword), "No keyword input") + ) + tagList( + lapply(seq_along(rv$keywords$keyword), function(kid) { + keyword <- rv$keywords$keyword[kid] + .val <- rv$keywords$keyword.thesaurus[kid] + + textInput( + ns(paste0("thesaurus-for-", keyword)), + keyword, + value = if (isTruthy(.val)) .val else "" + ) + }) + ) + }) + }) + + # NOTE observers are still active after being deleted + observe({ validate( - need(checkTruth(rv$keywords$keyword), "No keyword input") + need(rv$keywords$keyword, "No keyword input") ) - tagList( - lapply(seq_along(rv$keywords$keyword), function(kid) { - keyword <- rv$keywords$keyword[kid] - .val <- rv$keywords$keyword.thesaurus[kid] - - textInput( - ns(paste0("thesaurus-for-", keyword)), - keyword, - value = if (isTruthy(.val)) .val else "" - ) - }) + sapply(seq_along(rv$keywords$keyword), function(kid) { + keyword <- rv$keywords$keyword[kid] + input_id <- paste0("thesaurus-for-", keyword) + .val <- if (isTruthy(input[[input_id]])) input[[input_id]] else "" + + rv$keywords$keyword.thesaurus[kid] <- .val + }) + }) + + # * Temporal coverage ==== + if (!is.null(save.variable$emlal$Misc$temporal.coverage)) { + rv$temporal.coverage <- save.variable$emlal$Misc$temporal.coverage + updateDateRangeInput( + session, + "temporal.coverage", + start = rv$temporal.coverage[1], + end = rv$temporal.coverage[2] ) + } + observeEvent(input$temporal_coverage, { + rv$temporal.coverage <- input$temporal_coverage }) - }) - - # NOTE observers are still active after being deleted - observe({ - validate( - need(rv$keywords$keyword, "No keyword input") + + # * Additional information ==== + rv$additional.information <- Miscellaneous( + "additional.information", + save.variable, + rv = rv$additional.information ) - sapply(seq_along(rv$keywords$keyword), function(kid) { - keyword <- rv$keywords$keyword[kid] - input_id <- paste0("thesaurus-for-", keyword) - .val <- if (isTruthy(input[[input_id]])) input[[input_id]] else "" - - rv$keywords$keyword.thesaurus[kid] <- .val + + # Saves ---- + observe({ + main.env$EAL$completed <- all( + isTruthy(rv$abstract$content()) && + isTruthy(rv$methods$content()) && + isTruthy(rv$keywords$keyword) && + isTruthy(rv$temporal.coverage) + ) }) - }) - - # * Temporal coverage ==== - if (!is.null(save.variable$emlal$Misc$temporal.coverage)) { - rv$temporal.coverage <- save.variable$emlal$Misc$temporal.coverage - updateDateRangeInput( - session, - "temporal.coverage", - start = rv$temporal.coverage[1], - end = rv$temporal.coverage[2] + + # observeEvent(NSB$SAVE, + shinyjs::onclick( + "fill-wizard-save", + asis = TRUE, + add = TRUE, + { + req(main.env$EAL$current == "Miscellaneous") + + save.variable <- saveReactive( + save.variable = savevar, + rv = list(Misc = rv) + ) + }, + ignoreInit = TRUE ) - } - observeEvent(input$temporal_coverage, { - rv$temporal.coverage <- input$temporal_coverage - }) - - # * Additional information ==== - rv$additional.information <- callModule( - Miscellaneous, - "additional.information", - save.variable, - rv = rv$additional.information - ) - - # Saves ----------------------------------------------------- - observe({ - main.env$EAL$current[2] <- all( - isTruthy(rv$abstract$content()) && - isTruthy(rv$methods$content()) && - isTruthy(rv$keywords$keyword) && - isTruthy(rv$temporal.coverage) + + # Process data ---- + observeEvent(EAL$.next, + { + req(main.env$EAL$current == "Miscellaneous") + + save.variable <- saveReactive( + save.variable = savevar, + rv = list(Misc = rv) + ) + }, + priority = 1, + ignoreInit = TRUE ) + + # Output ---- + return(save.variable) }) - - observeEvent(NSB$SAVE, - { - req(main.env$EAL$current[1] == "Miscellaneous") - - save.variable <- saveReactive( - save.variable = savevar, - rv = list(Misc = rv) - ) - }, - ignoreInit = TRUE - ) - - # Process data ----------------------------------------------------- - observeEvent(NSB$NEXT, - { - req(main.env$EAL$current[1] == "Miscellaneous") - - save.variable <- saveReactive( - save.variable = savevar, - rv = list(Misc = rv) - ) - }, - priority = 1, - ignoreInit = TRUE - ) - - # Output ----------------------------------------------------- - return(save.variable) } diff --git a/R/eal_8_miscellaneous.R b/R/eal_8_miscellaneous.R index bf5d61b..bb5039f 100644 --- a/R/eal_8_miscellaneous.R +++ b/R/eal_8_miscellaneous.R @@ -3,7 +3,6 @@ #' #' @noRd MiscellaneousUI <- function(id, help.label = NULL, value = "") { - ns <- NS(id) fluidRow( # file selection @@ -13,13 +12,13 @@ MiscellaneousUI <- function(id, help.label = NULL, value = "") { tags$br(), div( fileInput( - ns("file"), + NS(id, "file"), "", multiple = FALSE, buttonLabel = span("Load file", icon("file")), ) ), - div(textOutput(ns("selected")), class = "ellipsis") + div(textOutput(NS(id, "selected")), class = "ellipsis") ), # Content edition column( @@ -28,7 +27,7 @@ MiscellaneousUI <- function(id, help.label = NULL, value = "") { tags$b("Content"), help.label, markdownInputUI( - ns("content"), + NS(id, "content"), label = "", value = value, preview = FALSE @@ -43,13 +42,13 @@ MiscellaneousUI <- function(id, help.label = NULL, value = "") { #' #' @noRd Miscellaneous <- function(input, output, session, save.variable, rv) { - # Variable initialization ----------------------------------------------------- + # Variable initialization ---- ns <- session$ns - # Get content ----------------------------------------------------- - rv$content <- callModule(markdownInput, "content", preview = FALSE) + # Get content ---- + rv$content <- markdownInput("content", preview = FALSE) - # Get file ----------------------------------------------------- + # Get file ---- observeEvent(input$file, { req(input$file) @@ -81,6 +80,6 @@ Miscellaneous <- function(input, output, session, save.variable, rv) { ) }) - # Output ----------------------------------------------------- + # Output ---- return(rv) } diff --git a/R/eal_9_annotations.R b/R/eal_9_annotations.R index 7acd290..e2a560a 100644 --- a/R/eal_9_annotations.R +++ b/R/eal_9_annotations.R @@ -6,7 +6,7 @@ #' useShinyjs(), #' tags$div( #' tags$br(), -#' actionButton(ns("addui"), "", icon("plus")), +#' actionButton(NS(id, "addui"), "", icon("plus")), #' fluidRow( #' column(11, #' column(4, "Subject"), @@ -15,8 +15,8 @@ #' ), #' style = "background-color: white; text-align: center" #' ), -#' uiOutput(ns("annotation_fields")), -#' tags$div(id = ns("inserthere")), +#' uiOutput(NS(id, "annotation_fields")), +#' tags$div(id = NS(id, "inserthere")), #' tags$br(), #' class = "inputBox wip" #' ) # end of fluidPage @@ -64,7 +64,7 @@ #' footer = tagList( #' modalButton("Cancel"), #' actionButton( -#' ns("insert"), +#' NS(id, "insert"), #' "New annotation" #' ) %>% disabled #' ) @@ -95,19 +95,19 @@ #' #' @import shiny #' insertAnnotInput <- function(id, rv, ns, main.env, value = NULL) { #' -#' # initialize IDs ----------------------------------------------------- +#' # initialize IDs ---- #' div_id <- id #' site_id <- paste0("site_", id) #' rmv_id <- paste0("rmv_", id) #' -#' # Proper module server ----------------------------------------------------- +#' # Proper module server ---- #' # insert new UI #' newUI <- AnnotModUI( #' ns(id), div_id, site_id, rmv_id, #' value = value #' ) #' insertUI( -#' selector = paste0("#", ns("inserthere")), +#' selector = paste0("#", NS(id, "inserthere")), #' ui = newUI #' ) #' @@ -119,7 +119,7 @@ #' value = value # set saved #' ) #' -#' # Output ----------------------------------------------------- +#' # Output ---- #' return(rv) #' } #' @@ -187,7 +187,7 @@ #' rv, rmv_id, site_id, ref, role = NULL, saved = NULL) { #' ns <- session$ns #' -#' # Variable initialization ----------------------------------------------------- +#' # Variable initialization ---- #' if(!is.null(saved)){ #' value <- saved[saved$id == ref,] #' } else { @@ -225,7 +225,7 @@ #' local.rv <- ontoloGUI("object", local.rv) #' }) #' -#' # Metadata save ----------------------------------------------------- +#' # Metadata save ---- #' observe({ #' req( #' !is.null(value) || @@ -259,6 +259,6 @@ #' removeUI(selector = paste0("#", site_id), immediate = TRUE) #' }) #' -#' # Output ----------------------------------------------------- +#' # Output ---- #' return(rv) #' } \ No newline at end of file diff --git a/R/eal_9_makeeml.R b/R/eal_9_makeeml.R index 8f6b02b..b177ad5 100644 --- a/R/eal_9_makeeml.R +++ b/R/eal_9_makeeml.R @@ -2,9 +2,9 @@ #' @importFrom shinyjs hidden disabled #' #' @noRd -MakeEMLUI <- function(id, title, dev) { +MakeEMLUI <- function(id, main.env) { ns <- NS(id) - + return( fluidPage( fluidRow( @@ -14,15 +14,15 @@ MakeEMLUI <- function(id, title, dev) { a EML-valid xml file."), tags$p("(NOTE: you will be able to edit this data package furtherly)"), actionButton( - ns("make_eml"), + NS(id, "make_eml"), "Make EML", icon("edit"), width = "50%" ), - textOutput(ns("warnings")), + textOutput(NS(id, "warnings")), shinyjs::hidden( actionLink( - ns("bug_report"), + NS(id, "bug_report"), span("Please report this to the dev", icon("external-link-alt")) ) ), @@ -42,7 +42,7 @@ MakeEMLUI <- function(id, title, dev) { tags$b("Generate a summary of your data package."), tags$i("(clicking on the below button will open a preview)"), downloadButton( - ns("download_emldown"), + NS(id, "download_emldown"), "Download emldown", width = "50%" ) @@ -59,168 +59,161 @@ MakeEMLUI <- function(id, title, dev) { #' @importFrom emldown render_eml #' #' @noRd -MakeEML <- function(input, output, session, save.variable, main.env) { - ns <- session$ns - - if (main.env$DEV) { - shinyjs::onclick("dev", - { - req(main.env$EAL$navigate == 9) - browser() - }, - asis = TRUE +MakeEML <- function(id, main.env) { + moduleServer(id, function(input, output, session){ + save.variable <- main.env$save.variable + ns <- session$ns + + # Variable initialization ---- + out.file <- paste0( + save.variable$emlal$SelectDP$dp.path, + "/emldown/emldown.html" ) - } - - # Variable initialization ----------------------------------------------------- - out.file <- paste0( - save.variable$emlal$SelectDP$dp.path, - "/emldown/emldown.html" - ) - - # Make eml ----------------------------------------------------- - observeEvent(input$make_eml, { - shinyjs::hide("bug_report") - req(input$make_eml) - withProgress( - { - . <- save.variable$emlal - fileName <- .$SelectDP$dp_title - - x <- try( - EMLassemblyline::template_arguments( - path = .$SelectDP$dp_metadata_path, - data.path = .$SelectDP$dp_data_path, - data.table = dir(.$SelectDP$dp_data_path) - ) - ) - - if (class(x) == "try-error") { - out <- x - out[1] <- paste("Upon templating arguments:", x) - incProgress(0.9) - } else { - incProgress(0.3) - - x$path <- .$SelectDP$dp_metadata_path - x$data.path <- .$SelectDP$dp_data_path - x$eml.path <- .$SelectDP$dp_eml_path - x$data.table <- dir(x$data.path) - x$data.table.name <- .$DataFiles$table_name - x$data.table.description <- .$DataFiles$description - x$dataset.title <- .$SelectDP$dp_title - x$maintenance.description <- "Ongoing" - # TODO better package.id - x$package.id <- fileName - x$return.obj <- TRUE - x$temporal.coverage <- .$Misc$temporal_coverage - # TODO user domain (pndb?) - x$user.domain <- "UserDomain" - # TODO user id (orcid?) - x$user.id <- "UserID" - x$write.file <- TRUE - - # Yet written in the files then used in make_eml - x$geographic.coordinates <- NULL - x$geographic.description <- NULL - - incProgress(0.2) - - .test <- 0 - out <- try( - do.call( - EMLassemblyline::make_eml, - x[names(x) %in% names(formals(make_eml))] + + # Make eml ---- + observeEvent(input$make_eml, { + shinyjs::hide("bug_report") + req(input$make_eml) + withProgress( + { + . <- save.variable$emlal + fileName <- .$SelectDP$dp_title + + x <- try( + EMLassemblyline::template_arguments( + path = .$SelectDP$dp_metadata_path, + data.path = .$SelectDP$dp_data_path, + data.table = dir(.$SelectDP$dp_data_path) ) ) - if (class(out) == "try-error") { - out[1] <- paste("Upon writing EML:", out) + + if (class(x) == "try-error") { + out <- x + out[1] <- paste("Upon templating arguments:", x) + incProgress(0.9) + } else { + incProgress(0.3) + + x$path <- .$SelectDP$dp_metadata_path + x$data.path <- .$SelectDP$dp_data_path + x$eml.path <- .$SelectDP$dp_eml_path + x$data.table <- dir(x$data.path) + x$data.table.name <- .$DataFiles$table_name + x$data.table.description <- .$DataFiles$description + x$dataset.title <- .$SelectDP$dp_title + x$maintenance.description <- "Ongoing" + # TODO better package.id + x$package.id <- fileName + x$return.obj <- TRUE + x$temporal.coverage <- .$Misc$temporal_coverage + # TODO user domain (pndb?) + x$user.domain <- "UserDomain" + # TODO user id (orcid?) + x$user.id <- "UserID" + x$write.file <- TRUE + + # Yet written in the files then used in make_eml + x$geographic.coordinates <- NULL + x$geographic.description <- NULL + + incProgress(0.2) + + .test <- 0 + out <- try( + do.call( + EMLassemblyline::make_eml, + x[names(x) %in% names(formals(make_eml))] + ) + ) + if (class(out) == "try-error") { + out[1] <- paste("Upon writing EML:", out) + } + incProgress(0.4) } - incProgress(0.4) - } - }, - message = "Writing EML ...", - value = 0.1 - ) - - valid.eml <- EML::eml_validate( - dir( - save.variable$emlal$SelectDP$dp.eml.path, - full.names = TRUE + }, + message = "Writing EML ...", + value = 0.1 ) - ) - - output$warnings <- renderText({ - disable("publish") - disable("emldown") - validate( - need( - class(out) != "try-error", - out[1] - ), - need( - !isFALSE(valid.eml), - unique(attr(valid.eml, "errors")) + + valid.eml <- EML::eml_validate( + dir( + save.variable$emlal$SelectDP$dp.eml.path, + full.names = TRUE ) ) - shinyjs::enable("publish") - shinyjs::enable("emldown") - return(NULL) - }) - - if (class(out) == "try-error" || - isFALSE(valid.eml)) { - shinyjs::show("bug_report") - showNotification("EML invalid", type = "error", duration = NULL) - } else { - shinyjs::hide("bug_report") - showNotification("EML written.", type = "message") - # emldown - eml.file <- dir( - save.variable$emlal$SelectDP$dp.eml.path, - full.names = TRUE, - pattern = save.variable$emlal$SelectDP$dp.title - ) - dir.create(dirname(out.file), recursive = TRUE) - old.wd <- getwd() - setwd(dirname(out.file)) - out <- emldown::render_eml( - file = eml.file, - open = TRUE, - out.file = out.file, - publish_mode = TRUE - ) - setwd(old.wd) - if (file.exists(out.file)) { - showNotification("emldown generated", type = "message") + output$warnings <- renderText({ + disable("publish") + disable("emldown") + validate( + need( + class(out) != "try-error", + out[1] + ), + need( + !isFALSE(valid.eml), + unique(attr(valid.eml, "errors")) + ) + ) + shinyjs::enable("publish") + shinyjs::enable("emldown") + return(NULL) + }) + + if (class(out) == "try-error" || + isFALSE(valid.eml)) { + shinyjs::show("bug_report") + showNotification("EML invalid", type = "error", duration = NULL) + } else { + shinyjs::hide("bug_report") + showNotification("EML written.", type = "message") + + # emldown + eml.file <- dir( + save.variable$emlal$SelectDP$dp.eml.path, + full.names = TRUE, + pattern = save.variable$emlal$SelectDP$dp.title + ) + dir.create(dirname(out.file), recursive = TRUE) + old.wd <- getwd() + setwd(dirname(out.file)) + out <- emldown::render_eml( + file = eml.file, + open = TRUE, + out.file = out.file, + publish_mode = TRUE + ) + setwd(old.wd) + if (file.exists(out.file)) { + showNotification("emldown generated", type = "message") + } } - } - }) - - observeEvent(input$bug_report, { - utils::browseURL("https://github.com/earnaud/MetaShARK-v2/issues/26") - }) - - # emldown ----------------------------------------------------- - output$download_emldown <- downloadHandler( - filename = function() { - paste( - save.variable$emlal$SelectDP$dp.name, - "_emldown.zip" - ) - }, - content = function(file) { - utils::zip( - zipfile = file, - files = dir( - dirname(out.file), - recursive = TRUE + }) + + observeEvent(input$bug_report, { + utils::browseURL("https://github.com/earnaud/MetaShARK-v2/issues/26") + }) + + # emldown ---- + output$download_emldown <- downloadHandler( + filename = function() { + paste( + save.variable$emlal$SelectDP$dp.name, + "_emldown.zip" ) - ) - } - ) - - # Output ----------------------------------------------------- - return(save.variable) + }, + content = function(file) { + utils::zip( + zipfile = file, + files = dir( + dirname(out.file), + recursive = TRUE + ) + ) + } + ) + + # Output ---- + return(save.variable) + }) } diff --git a/R/fill-module.R b/R/fill-module.R index d1ebfdd..8643994 100644 --- a/R/fill-module.R +++ b/R/fill-module.R @@ -1,31 +1,265 @@ #' @import shiny #' #' @noRd -fillUI <- function(id, dev = FALSE) { +fillUI <- function(id, main.env) { ns <- NS(id) + tabsetPanel( - id = ns("tabs"), - tabPanel("EAL", EMLALUI(ns("EAL"), dev)), - tabPanel("MetaFIN", h1("Under Construction")) + id = NS(id, "tabs"), + tabPanel("EAL", + # EMLALUI(NS(id, "EAL"), main.env) + fluidPage( + style = "padding-top:2.5%;", + pagesUI( + NS(id, "wizard"), + parent.id = id, + main.env = main.env + ) + ) # end fluidPage + ), + tabPanel( + "MetaFIN", + tags$h1("Under Construction"), + tags$img(src = "media/working.png") + ) ) } #' @import shiny #' #' @noRd -fill <- function(input, output, session, main.env) { - ns <- session$ns - # variable initialization ==== - - # save variable initialization - save.variable <- initReactive(main.env = main.env$EAL) - - # action ==== - save.variable <- callModule( - EMLAL, "EAL", - save.variable, main.env - ) - - # Output ==== - return(save.variable) +fill <- function(id, main.env){ + moduleServer(id, function(input, output, session) { + # Variable initialization ==== + .EAL <- main.env$EAL # local copy + save.variable <- main.env$save.variable + steps <- isolate(main.env$VALUES$steps) + + # Wizard ==== + + # pages change + pagesServer(NS(id, "wizard"), steps) + + # modules content + SelectDP("SelectDP", main.env) + DataFiles("DataFiles", main.env) + Attributes("Attributes", main.env) + CatVars("CatVars", main.env) + GeoCov("GeoCov", main.env) + TaxCov("TaxCov", main.env) + Personnel("Personnel", main.env) + Misc("Misc", main.env) + MakeEML("MakeEML", main.env) + + # Navigation ---- + observeEvent(.EAL$page, { + # set EAL variables + if(identical(.EAL$history, character())){ + .EAL$history <- main.env$VALUES$steps[1:.EAL$page] + .EAL$current <- main.env$VALUES$steps[.EAL$page] + } + + # On loading DP, correct step + isolate({ + if(.EAL$page == -1) + .EAL$page <- match( + utils::tail(save.variable$emlal$history,1), + steps + ) + }) + + if (.EAL$current == "Data Files") { + unlink(main.env$PATHS$eal.tmp) + } + file.remove( + list.files( + save.variable$emlal$SelectDP$dp.data.path, + pattern = "preview___" + ) + ) + .EAL$current <- main.env$VALUES$steps[.EAL$page] + if (.EAL$current == "Data Files" && + !dir.exists(main.env$PATHS$eal.tmp)) { + dir.create(main.env$PATHS$eal.tmp) + } + + if (isFALSE(.EAL$completed)) { + .EAL$completed <- TRUE + } # trigger + .EAL$completed <- FALSE + EAL$tag.list <- tagList() + + # Edition changed path -> remove excedent history + if (!.EAL$current %in% .EAL$history) { + .EAL$history <- c(.EAL$history, .EAL$current) + } + + # Savevar modification + save.variable$emlal$step <- .EAL$page + save.variable$emlal$history <- .EAL$history + + updateTabsetPanel(session, "wizard", selected = steps[to]) + + # Modules helper ---- + NSB$help <- modalDialog( + title = paste0(.EAL$current, " - Help"), + switch(.EAL$page, + # SelectDP + tagList( + tags$p("This module allows you to manage your", tags$strong("data packages"), ". + A data package (aka DP) is a collection of a dataset and its associated metadata + and resources (scripts, literature, ...). You can:"), + tags$ul( + tags$li("Load an existing data package among local ones (left). You + will resume its edition at the last saved encountered step."), + tags$li( + "Create a new data package. You must fill in", tags$strong("three fields"), + tags$i("Data package name"), "will be used for identifying the DP,", + tags$i("Data package title"), "will be displayed when consulting the DP + page once formatted (explained in last step),", + tags$i("Data package license"), "is the license assigned to this production for + intellectual rights properties" + ) + ), + tags$p("Also, notice the", tags$strong("quick"), "check box above DP name. + Checking this box enables \"quick mode\" which will pre-fill most of the + fields in further steps. You still will be able to edit them at your + convenience.") + ), + # Data Files + tagList( + tags$p("This module allows you to load data files from the dataset you want to + describe. Once uploaded, you can set:"), + tags$ul( + tags$li(tags$i("Content name:"), "A name for the data contained in the file (e.g. table name)."), + tags$li(tags$i("URL:"), "If the file is accessible remotely, here is a way to reference it."), + tags$li(tags$i("Description:"), "A short text provided to describe the file, its content, + relevant information about the data in the entity.") + ), + tags$p("To edit your selection, select files among the list with the check boxes on + their left, then click the \"Remove\" button."), + tags$p("Recommended size per file is around 1 Gb. Such files and heavier ones might slow down the + app.") + ), + # Attributes + tagList( + tags$p("This module allows you to describe precisely each attribute of each file. Some of these metadata + are guessed from the data files. Such fields are annoted with a star (*). + For each attribute, you can set:"), + tags$ul( + tags$li(tags$i("Attribute Name*:"), "the name of the attribute."), + tags$li(tags$i("Attribute Description:"), "a "), + tags$li(tags$i("Attribute Class*:"), "the type of content in the attributes among + \"numeric\", \"character\", \"categorical\" and \"Date\". Categorical means a + character string with encoded values (e.g. Male/Female)."), + tags$li(tags$i("Date format (only for Date class): how the dates of the attributes are + written (e.g. DD-MM-YYYY).")), + tags$li(tags$i("Unit (only for Numeric class):"), "which is the unit used for the + numeric data of the attributes. The list is huge and refers to", tags$a("STMML Scientific + units", href = "http://www.ch.ic.ac.uk/rzepa/codata2/"), ". You can also define you own unit + (see Custom Units thereafter)."), + tags$li(tags$i("Missing Value Code:"), "a one-word code used instead of a missing value among + the data of the attribute currently described."), + tags$li(tags$i("Missing Value Code Explanation:"), "a short definition of the meaning(s) given + for the missing value code.") + ), + tags$h3("Custom units creation"), + tags$p("EML allows the user to define its own units, but this require to fulfill some more + fields. However, the custom units you will have defined will be saved into the Custom Units + table at the bottom of this page. You will find the written custom units in the units selection + once they are written. To define a custom unit, chose the unit to be \"custom\". A custom + unit is defined with:"), + tags$ul( + tags$li(tags$i("Unit id:"), "the id of the unit (e.g. gramsPerOneThirdMeter). The unit id + must validate the STMML schema."), + tags$li(tags$i("Unit type:"), "the physical property measured by the custom unit (e.g. mass)."), + tags$li(tags$i("Parent unit in SI:"), "from which unit among the most common one is the custom + unit derived (e.g. gram)."), + tags$li(tags$i("Multiplier to SI:"), "by how many has the custom unit to be multiplied to be + equal to its parent unit."), + tags$li(tags$i("Unit description:"), "some additional notes about the unit, how to compute it.") + ) + ), + # Catvars + tagList( + tags$p("This module allows you to detail the categorical variables (class \"categorical\" in Attributes). + For each variable, you will be able to detail each of its value by a short description.") + ), + # Geocov + tagList( + tags$p("This module allows you to define the geographic area in which the data have been produced. + You have the choice between two methods to define geographic coverage:"), + tags$ul( + tags$li( + tags$h4("Columns description (recommended)"), + tags$p("This method asks you to choose columns in one of your files. For latitude and longitude, + you can select either one or two columns. If a single column contains a pair of numbers, they + will be detected. Chosing single coordinates will be considered as single sites. Chosing pairs of + coordinates will be considered as sub-areas. For each coordinate, you can select a column + containing description for each one.") + ), + tags$li( + tags$h4("Custom description"), + tags$p("With this, you will be able to define by hand each one of the sites covered by your data.") + ) + ) + ), + # Taxcov + tagList( + tags$p("This module allows you to define the taxonomical coverage of the study. You will be asked to + select columns among your files containing the species name. Also, let the app know if the taxonomic + coverage shall be written with scientific, common or both names. At last, select at least one taxonomic + authority among the ones suggested."), + ), + # Personnel + tagList( + tags$p("This module allows you to get a full list of the people who contributed to the creation of + this dataset. The recommended best practice is to", tags$b("use the ORCID"), "of a person. With + this and the help of {rorcid}, the app will be able to fetch all available and interesting data. + You will be able to correct this afterwards. Also, note that you must fill in the fields + for two roles: creator and contact."), + tags$p("Suggested roles are the following:"), + tags$ul( + tags$li("Creator: person who contributed to produce the data."), + tags$li("Contact: persone to contact for any question about the data."), + tags$li("Principal investigator: person who led the creation of the dataset. Selecting this will allow + you to fill in additional information about the project and its funding."), + tags$li("Custom: as the list of roles is not exhaustive, feel free to add any role you consider important.") + ) + ), + # Misc + tagList( + tags$p("This module allows you to define the last details of your data package. Note that you can write + some of these metadata using the markdown syntax. Here are brief descriptions of the fields:"), + tags$ul( + tags$li("Abstract: the abstract of the publication linked to those data."), + tags$li("Methods: the methods used in the production of this dataset."), + tags$li( + "Keywords: you can type a list of keywords for your dataset. For each keyword, you can add a + keyword thesaurus, like", tags$a("the LTER controlled vocabulary ", href = "http://vocab.lternet.edu/vocab/vocab/index.php"), + ", which are controlled vocabulary your exact keyword originates from. Keywords thesaurus are not + required." + ), + tags$li("Temporal coverage: this lets you define the duration of the study during which the data have been produced."), + tags$li("Additional information: if any information has been omitted, you can provide it here (e.g. collection metadata + from GBIF-EML).") + ) + ), + # Make EML + tagList( + tags$p("Here we are (well done) ! This is the final step to write EML. Just click the button and let the magic happen. If an + error occurs, this will be displayed to the screen. In this case, do not hesitate to get in touch with the dev team."), + tags$p("You can also use the {emldown} package to get a human-readable version of the generated EML. The button below it will + let you download the result of this step.") + ) + ), + footer = modalButton("Close"), + easyClose = TRUE, fade = TRUE + ) + }, + label = "EAL0 update" + ) + # Output ==== + return(save.variable) + }) } diff --git a/R/fill_pages.R b/R/fill_pages.R new file mode 100644 index 0000000..95ff7fb --- /dev/null +++ b/R/fill_pages.R @@ -0,0 +1,341 @@ +# UI ==== + +#' @noRd +#' +#' @import shiny +tabPage <- function(title, ui, navTagList = NULL){ + tabPanelBody( + value = title, + tags$span( + div("EML Assembly Line", style = "padding-right: 15px"), + # uiOutput(NS(id, "chain")), + style = "display: inline-flex" + ), + if(is.null(navTagList)) + fluidRow( + column(12, ui) + ) + else + fluidRow( + column(10, ui), + column(2, navTagList) + ) + ) +} + +#' @import shiny +#' +#' @noRd +pagesUI <- function(id, parent.id, main.env){ + steps <- isolate(main.env$VALUES$steps) + .nb <- length(steps) + + .ui.args <- vector("list", .nb) + sapply( + seq_along(steps), + function(i, main.env) { + page <- steps[i] + + .ui.args[[i]] <<- tabPage( + title = page, + ui = do.call( + what = switch(i, + "SelectDPUI", + "DataFilesUI", + "AttributesUI", + "CatVarsUI", + "GeoCovUI", + "TaxCovUI", + "PersonnelUI", + "MiscUI", + "MakeEMLUI" + ), + args = list( + id = NS(parent.id, page), + main.env = main.env + ) + ), + navTagList = if (i > 1) + tagList( + quitButton(id), + saveButton(id), + if (i != 2) prevTabButton(id, i), + if (i != .nb) nextTabButton(id, i), + tags$hr(), + actionButton(NS(id, "help"), "Help", icon("question-circle")) + ) + else + NULL + ) + }, + main.env = main.env) + + .ui.args$id = NS(id, "wizard") + .ui.args$type = "hidden" + + do.call("tabsetPanel", .ui.args) +} + +# Server ==== + +#' @noRd +#' +#' utility function for pages +changePage <- function(from, to) { + observeEvent(input[[paste(from, to, sep = "_")]], { + EAL$page <- EAL$page + to - from + if(to > from) + EAL$.next <- .EAL$.next+1 + if(from > to) + EAL$.prev <- .EAL$.prev+1 + }) +} + +#' Wizard pages server +#' +#' @noRd +pagesServer <- function(id, steps) { + moduleServer(id, function(input, output, session) { + steps <- main.env$VALUES$steps + EAL <- main.env$EAL + + ids <- seq_along(steps) + lapply(ids[-1], function(i) onQuit(i)) # modules + lapply(ids[-1], function(i) onSave(i)) # modules + lapply(ids[-1], function(i) changePage(i, i-1)) # observers + lapply(ids[-length(steps)], function(i) changePage(i, i+1)) # observers + + # * Chain ==== + # output$chain <- renderUI({ + # validate( + # need(.EAL$page > 1, "") + # ) + # + # return( + # tags$span( + # tagList( + # lapply(seq(.EAL$history)[-1], function(ind) { + # .step.name <- .EAL$history[ind] + # + # if (.step.name != "Taxonomic Coverage") { + # .style <- "color: dodgerblue;" + # .description <- paste(.step.name, "(mandatory)") + # } else { + # .style <- "color: lightseagreen;" + # .description <- paste(.step.name, "(facultative)") + # } + # + # return( + # actionLink( + # ns(paste0("chain_", .step.name)), + # "", + # if (.step.name == .EAL$current) { + # icon("map-marker") + # } else { + # icon("circle") + # }, + # style = .style + # ) %>% shinyBS::tipify( + # title = .description + # # , placement = "bottom" + # # , trigger = "hover" + # ) + # ) # end of return + # }), + # paste0( + # "Step ", .EAL$page, + # "/", length(steps), + # ": ", .EAL$current + # ) + # ), + # style = "position: right" + # ) + # ) + # }) + # + # observe({ + # validate( + # need( + # exists("main.env") && isTruthy(names(input)), + # "Not initialized" + # ), + # need( + # isTruthy(.EAL$history), + # "No history available" + # ), + # need( + # any(sapply( + # .EAL$history, + # grepl, + # x = names(input) + # ) %>% unlist()) && + # length(.EAL$history) > 1, + # "No history available" + # ) + # ) + # + # sapply(seq(.EAL$history)[-1], function(.ind) { + # id <- paste0("chain_", .EAL$history[.ind]) + # + # observeEvent(input[[id]], { + # req(input[[id]] && .ind != .EAL$page) + # .EAL$page <- .ind + # saveReactive() # Set this up correctly + # + # # trigger changes + # if(.ind > .EAL$page) + # EAL$.next <- EAL$.next + 1 + # if(.ind < EAL$page) + # EAL$.prev <- EAL$.prev + 1 + # }) + # }) + }) +} + +# * Quit ==== + +#' @noRd +#' +#' @import shiny +quitButton <- function(id) { + actionButton( + NS(id, "quit"), + "Quit", + icon = icon("sign-out-alt"), + width = "100%" + ) +} + +#' @noRd +#' +#' @import shiny +#' @importFrom shinyjs onclick disable enable +onQuit <- function(id, main.env) { + moduleServer(id, function(input, output, session) { + save.variable <- main.env$save.variable + + # modal dialog for quitting data description + quitModal <- modalDialog( + title = "You are leaving data description.", + "Are you sure to leave? Some of your metadata have maybe not been saved.", + easyClose = FALSE, + footer = tagList( + actionButton(NS(id, "cancel"), "Cancel"), + actionButton(NS(id, "save_quit"), "Save & Quit"), + actionButton( + NS(id, "simple_quit"), + "Quit", + icon("times-circle"), + class = "redButton" + ) + ) + ) + + # quits simply + observeEvent(input$cancel, + { + req(input$quit) + req(input$cancel) + removeModal() + }, + label = "Cancel quit" + ) + + # show modal on 'quit' button clicked + observeEvent(input$quit, + { + req(input$quit) + showModal(quitModal) + }, + label = "EAL quit?" + ) + + # calls saveRDS method and quits + observeEvent(input$save_quit_button, + { + req(input$quit) + req(input$save_quit_button) + + # Save work at this state + saveReactive(save.variable) + }, + priority = 1, + label = "EAL save+quit" + ) + + # quits simply + observeEvent({ + input$simple_quit + input$save_quit_button + }, { + req(input$quit) + removeModal() + + # Clean & reset variables + main.env$EAL$history <- "SelectDP" + main.env$EAL$page <- 1 + }, + priority = 0, + label = "EAL quit", + ignoreInit = TRUE + ) + }) +} + +# * Save ==== + +#' @noRd +#' +#' @import shiny +saveButton <- function(id) { + actionButton( + NS(id, "save"), + "Save", + icon = icon("save", class = "regular"), + width = "100%" + ) +} + +#' @noRd +#' +#' @import shiny +#' @importFrom shinyjs onclick disable enable +onSave <- function(id, main.env){ + moduleServer(id, function(input, output, session) { + observeEvent(input$save, + { + req(input$save) + NSB$SAVE <- NSB$SAVE + 1 + }, + label = "NSB save" + ) + }) +} + +# * Previous ==== + +#' @noRd +#' +#' @import shiny +prevTabButton <- function(id, i) { + actionButton( + NS(id, paste(i, i-1, sep = "_")), + "Previous", + icon = icon("arrow-left"), + width = "100%" + ) +} + +# * Next ==== + +#' @noRd +#' +#' @import shiny +nextTabButton <- function(id, i) { + actionButton( + NS(id, paste(i, i+1, sep = "_")), + "Next", + icon = icon("arrow-right"), + width = "100%" + ) +} diff --git a/R/headerScript.R b/R/headerScript.R index e1e9d14..1ffec95 100644 --- a/R/headerScript.R +++ b/R/headerScript.R @@ -79,7 +79,10 @@ reactiveValues( thresholds = reactiveValues( files.size.max = 500000 - ) + ), + steps = c("SelectDP", "Data Files", "Attributes", "Categorical Variables", + "Geographic Coverage", "Taxonomic Coverage", "Personnel", "Miscellaneous", + "Make EML") ), envir = main.env ) @@ -152,23 +155,30 @@ envir = main.env ) - # EAL ==== - + # EAL rv ==== assign( "EAL", reactiveValues( - history = "SelectDP", - navigate = 1, - current = c(name = "SelectDP", completed = FALSE), - iterator = 0 + page = 1, # page number + history = character(), # all browsed pages names in steps + current = character(), # last of history + completed = FALSE, # is current page completed? + tag.list = tagList(), # side HTML tags to display + .next = 0, + .prev = 0 ), envir = main.env ) - # Patterns ==== + assign( + "save.variable", + initReactive(main.env = main.env), + envir = main.env + ) + # Patterns ==== assign( - "PATTERNS", + "PATTERNS", reactiveValues( # match one expression for latitude or longitude coordinates = "[+-]?[[:digit:]]+[.,]*[[:digit:]]*", diff --git a/R/orcid_connect.R b/R/orcid_connect.R index 001a396..f97184a 100644 --- a/R/orcid_connect.R +++ b/R/orcid_connect.R @@ -2,7 +2,7 @@ orcidUI <- function(id, globals) { ns <- NS(id) - uiOutput(ns("infos")) + uiOutput(NS(id, "infos")) } #' @import shiny @@ -18,9 +18,9 @@ orcid <- function(input, output, session, main.env) { output$infos <- renderUI({ if (isFALSE(.SETTINGS$logged)) { tagList( - textInput(ns("orcid"), "Write your ORCID here"), + textInput(NS(id, "orcid"), "Write your ORCID here"), actionButton( - ns("connect"), + NS(id, "connect"), "Connect with ORCID", icon = icon("sign-in-alt") ) @@ -35,7 +35,7 @@ orcid <- function(input, output, session, main.env) { ), column(6) ), - actionButton(ns("disconnect"), "Logout", icon = icon("sign-out-alt")) + actionButton(NS(id, "disconnect"), "Logout", icon = icon("sign-out-alt")) ) } }) diff --git a/R/fill-module_functions.R b/R/savevariable_functions.R similarity index 83% rename from R/fill-module_functions.R rename to R/savevariable_functions.R index b8f6bc1..d771a88 100644 --- a/R/fill-module_functions.R +++ b/R/savevariable_functions.R @@ -1,4 +1,3 @@ -# Manage save.variable variable ----------------------------------------------------- #' @import shiny #' #' @noRd @@ -18,9 +17,9 @@ initReactive <- function(sub.list = NULL, save.variable = NULL, main.env) { # emlal reactivelist management if (is.null(sub.list) || sub.list == "emlal") { save.variable$emlal <- reactiveValues( - step = main.env$EAL$navigate, + step = isolate(main.env$EAL$page), quick = FALSE, - history = main.env$EAL$history, + history = isolate(main.env$EAL$history), SelectDP = reactiveValues( dp.name = NULL, dp.path = NULL, @@ -77,19 +76,14 @@ initReactive <- function(sub.list = NULL, save.variable = NULL, main.env) { }) } -#' @describeIn initReactive -#' -#' @description save the `save.variable` variable at wanted location -#' -#' @return -#' `save.variable` modified. -#' #' @import shiny #' @importFrom jsonlite write_json serializeJSON +#' +#' @noRd saveReactive <- function( save.variable, rv = NULL, - main.env = NULL + write = FALSE ) { withProgress({ setProgress(1 / 3, "Module save") @@ -113,7 +107,8 @@ saveReactive <- function( ), args = list( save.variable = savevar, - rv = rv[[1]] + rv = rv[[1]], + write = write ) ) @@ -189,22 +184,34 @@ saveReactive <- function( return(save.variable) } -#' @title readFilesText -#' -#' @param files files basename located in the same directory or, -#' if prefix = NULL, list of full filenames to read -#' @param prefix common file prefix for all file names -#' specified in 'files'. By default, sep = "/" -#' -#' @importFrom readtext readtext -readPlainText <- function(files, prefix = NULL, sep = "/", ...) { - if (is.null(prefix)) sep <- "" - - readtext::readtext( - paste( - prefix, - files, - sep = sep - ) - )$text +#' @import shiny +setSavevar <- function(content, save.variable, lv = 1, root = "root") { + + lapply( + names(content), + function(label) { + sub.content <- content[[label]] + type.content <- typeof(sub.content) + sub.save.variable <- savevar[[label]] + type.save.variable <- typeof(sub.savevar) + + if (is.reactivevalues(sub.save.variable)) { + if (!is.data.frame(sub.content) && + is.list(sub.content)) { + x <- setSavevar(content[[label]], save.variable[[label]], lv = lv + 1, root = label) + } + else { + x <- sub.content + } + } + else { + x <- sub.content + } + + isolate(save.variable[[label]] <- x) + return(NULL) + } + ) + + return(save.variable) } \ No newline at end of file diff --git a/R/server.R b/R/server.R index 88c9770..1e038ca 100644 --- a/R/server.R +++ b/R/server.R @@ -8,44 +8,31 @@ # get app arguments app.args <- golem::get_golem_options() - dev <- app.args$dev main.env <- app.args$main.env # initialize global variables save.variable <- NULL - # DEV ----------------------------------------------------- - if (dev) { + if (main.env$dev) { shinyjs::onclick("dev", { - req(input$side_menu != "fill") browser() }, asis = TRUE ) } - # Head bar server ----------------------------------------------------- + # Head bar server ---- # Options observeEvent(input$settings, { updateTabItems(session, "side_menu", "settings") }) - callModule(settings, "settings", main.env) + settings("settings", main.env) - ## modules called ----------------------------------------------------- - observeEvent(input$side_menu, { - save.variable <- switch(input$side_menu, - # fill - fill = callModule(fill, "fill", main.env), - # upload - upload = callModule(upload, "upload", main.env), - # doc - documentation = callModule(documentation, "documentation"), - # about - about = callModule(about, "about"), - # default - NULL - ) - }) + ## modules called ---- + fill("fill", main.env) + upload("upload", main.env) + documentation("documentation") + about("about") } diff --git a/R/settings.R b/R/settings.R index 9a97d6a..3dfda07 100644 --- a/R/settings.R +++ b/R/settings.R @@ -18,7 +18,7 @@ settingsUI <- function(id, wip) { created on this instance of MetaShARK. By logging in, you will be able to write private data packages that will not appear on other users list. "), - orcidUI(ns("orcid")), + orcidUI(NS(id, "orcid")), # TODO POC ORCID class = "inputBox wip" ) @@ -28,14 +28,14 @@ settingsUI <- function(id, wip) { column( 8, tags$h2("Metacat settings"), - textAreaInput(ns("metacat_token"), + textAreaInput(NS(id, "metacat_token"), "Authentication token", width = "120%" ), - checkboxInput(ns("test_metacat"), "Test MetaCat", value = TRUE), - actionButton(ns("metacat_save"), "Save"), + checkboxInput(NS(id, "test_metacat"), "Test MetaCat", value = TRUE), + actionButton(NS(id, "metacat_save"), "Save"), if (isTRUE(wip)) { - textOutput(ns("verbose_token")) + textOutput(NS(id, "verbose_token")) } ), column( @@ -59,11 +59,11 @@ settingsUI <- function(id, wip) { column( 8, textAreaInput( - ns("cedar_token"), + NS(id, "cedar_token"), "Authentication token", width = "120%" ), - actionButton(ns("cedar_save"), "Save") + actionButton(NS(id, "cedar_save"), "Save") ), column( 4, @@ -87,28 +87,30 @@ settingsUI <- function(id, wip) { #' @import shiny #' @importFrom shinyjs onclick #' @importFrom cedarr accessOntology -settings <- function(input, output, session, main.env) { - # Sessionning ==== - callModule(orcid, "orcid", main.env) - - # Metacat token ==== - observeEvent(input$test_metacat, { - req(input$test_metacat) - main.env$SETTINGS$metacat.test <- input$test_metacat - }) - - observeEvent(input$metacat_save, { - main.env$SETTINGS$metacat.token <- input$metacat_token - showNotification(id = "metacat_set", "Dataone token set.", type = "message") - }) - - # CEDAR token ==== - observeEvent({ - input$cedar_token - input$cedar_save - }, { - req(input$cedar_token) - .SETTINGS$cedar.token <- input$cedar_token - main.env$SEMANTICS$ontologies <- cedarr::accessOntology(.SETTINGS$cedar.token) +settings <- function(id, main.env){ + moduleServer(id, function(input, output, session) { + # Sessionning ==== + orcid("orcid", main.env) + + # Metacat token ==== + observeEvent(input$test_metacat, { + req(input$test_metacat) + main.env$SETTINGS$metacat.test <- input$test_metacat + }) + + observeEvent(input$metacat_save, { + main.env$SETTINGS$metacat.token <- input$metacat_token + showNotification(id = "metacat_set", "Dataone token set.", type = "message") + }) + + # CEDAR token ==== + observeEvent({ + input$cedar_token + input$cedar_save + }, { + req(input$cedar_token) + .SETTINGS$cedar.token <- input$cedar_token + main.env$SEMANTICS$ontologies <- cedarr::accessOntology(.SETTINGS$cedar.token) + }) }) -} +} \ No newline at end of file diff --git a/R/ui.R b/R/ui.R index 8c4ae7d..39a22bb 100644 --- a/R/ui.R +++ b/R/ui.R @@ -36,7 +36,7 @@ ), titleWidth = .menu.width ), - ## Menus ----------------------------------------------------- + ## Menus ---- dashboardSidebar( sidebarMenu( id = "side_menu", @@ -74,7 +74,7 @@ ), width = .menu.width ), # end sidebar - ## Content ----------------------------------------------------- + ## Content ---- dashboardBody( tags$script(HTML("$('body').addClass('fixed');")), tabItems( @@ -84,7 +84,7 @@ ), tabItem( tabName = "fill", - fillUI("fill", dev) + fillUI("fill", main.env) ), tabItem( tabName = "upload", @@ -103,7 +103,7 @@ settingsUI("settings", wip) ) ) - ) # end body + ) ) # end dashboard - ) %>% shinycssloaders::withSpinner # end taglist + ) # end taglist } diff --git a/R/upload-module.R b/R/upload-module.R index 3c1203b..493f956 100644 --- a/R/upload-module.R +++ b/R/upload-module.R @@ -31,40 +31,40 @@ uploadUI <- function(id, main.env) { tagList( tabsetPanel( id = "upload", - # Upload ----------------------------------------------------- + # Upload ---- tabPanel( title = "upload", - if (dev) actionButton(ns("dev"), "Dev"), - # select endpoint ----------------------------------------------------- + if (dev) actionButton(NS(id, "dev"), "Dev"), + # select endpoint ---- tags$h3("Select your MetaCat portal"), tags$div( tags$p(tags$code("dev"), "portals are under construction. No guarantee is given of their consistance.", tags$code("prod"), "portals are completely functional. Chosing 'Other' will ask you to input some technical information."), selectInput( - ns("endpoint"), + NS(id, "endpoint"), "Available metacats:", c(registeredEndpoints$mn, "Other") ), - uiOutput(ns("actual-endpoint")), + uiOutput(NS(id, "actual-endpoint")), tagList( tags$p("Want your endpoint to be listed? get in touch with the dev team !") ), class = "leftMargin inputBox" ), tags$hr(), - # check authentication token ----------------------------------------------------- + # check authentication token ---- tags$h3("Get your authentication token"), tags$div( tags$p("The ", tags$b("authentication token"), " is a user-specific characters key. It allows the user to authenticate a connection between its current location and a distant server, actually the metadata catalog. To upload a data package, the authentication token is required."), - actionButton(ns("toSettings"), "Go to settings", icon("gear")), + actionButton(NS(id, "toSettings"), "Go to settings", icon("gear")), class = "leftMargin inputBox" ), - # files input ----------------------------------------------------- + # files input ---- tags$h3("Select your data package files"), tags$div( # data package input @@ -76,7 +76,7 @@ uploadUI <- function(id, main.env) { # * DP ==== tags$h4("Select a data package"), selectInput( - ns("DP"), + NS(id, "DP"), "Data package", choices = c( None = "", @@ -88,46 +88,46 @@ uploadUI <- function(id, main.env) { tags$h4("Add or remove files"), # * Metadata ==== fileInput( - ns("metadata"), + NS(id, "metadata"), "EML-valid file (only one allowed)" ), - textOutput(ns("warnings-metadata")), + textOutput(NS(id, "warnings-metadata")), # * Data ==== fileInput( - ns("data"), + NS(id, "data"), "Data files described in your EML file" ), - textOutput(ns("warnings-data")), + textOutput(NS(id, "warnings-data")), # * Scripts ==== fileInput( - ns("scripts"), + NS(id, "scripts"), "Scripts used to produce or process data" ), - textOutput(ns("warnings-scripts")) + textOutput(NS(id, "warnings-scripts")) ), column(3, tags$h4("Files list"), - uiOutput(ns("filesList")) + uiOutput(NS(id, "filesList")) ) ), class = "leftMargin inputBox" ), - # Constraints ----------------------------------------------------- + # Constraints ---- # div(id="constraints_div", # tags$h4("Add constraints between script and data files"), - # actionButton(ns("add_constraint"), "", icon = icon("plus"), width = "40px") + # actionButton(NS(id, "add_constraint"), "", icon = icon("plus"), width = "40px") # ), # tags$hr(), actionButton( - ns("process"), + NS(id, "process"), "Process", icon = icon("rocket"), width = "100%" ) ), # end of upload tab - # Update ----------------------------------------------------- + # Update ---- tabPanel( title = "update", tags$div( @@ -153,229 +153,230 @@ uploadUI <- function(id, main.env) { #' @importFrom shinyjs enable disable click #' @importFrom data.table fread fwrite #' @importFrom mime guess_type -upload <- function(input, output, session, main.env) { - ns <- session$ns - - registeredEndpoints <- data.table::fread(main.env$PATHS$resources$registeredEndpoints.txt) - dev <- main.env$dev - - # Select endpoint ---- - endpoint <- reactive({ - input$endpoint - }) - - memberNode <- reactive({ - if (endpoint() != "Other") { - registeredEndpoints %>% - dplyr::filter(mn == endpoint()) %>% - dplyr::select(URL) - } else { - callModule(URL_Input, "actual-endpoint") - } - }) - - output$`actual-endpoint` <- renderUI({ - if (endpoint() != "Other") { - tags$p(tags$b("Current endpoint:"), memberNode()) - } else { - URL_Input_UI(ns("actual-endpoint"), "Write the URL of the Member Node") - } - }) - - # Token input ----------------------------------------------------- - observeEvent(input$toSettings, { - shinyjs::click("appOptions", asis = TRUE) - }, ignoreInit = TRUE) - - observe({ - if (!is.character(options("dataone_token")) || - !is.character(options("dataone_test_token")) || - (is.null(options("dataone_token")) && is.null(options("dataone_test_token"))) - ) { - output$token_status <- renderUI({ - tags$div("UNFILLED", class = "danger") - }) - shinyjs::disable("process") - } - else { - output$token_status <- renderUI({ - tags$div("FILLED", class = "valid") - }) - shinyjs::enable("process") - } - }) - - # Files input ----------------------------------------------------- - rv <- reactiveValues( - md = data.frame(stringsAsFactors = FALSE), - data = data.frame(stringsAsFactors = FALSE), - scr = data.frame(stringsAsFactors = FALSE) - ) - - observeEvent(input$DP, { - .dir <- gsub("/+", "/", input$DP) - .id <- basename(.dir) %>% sub("_emldp$", "", .) - .eml.files <- sprintf("%s/%s/eml", .dir, .id) %>% - dir(full.names = TRUE) - rv$md <- data.frame( - name = basename(.eml.files), - size = base::file.size(.eml.files), - type = mime::guess_type(.eml.files), - datapath= .eml.files - ) +upload <- function(id, main.env){ + moduleServer(id, function(input, output, session) { - .data.files <- sprintf("%s/%s/data_objects", .dir, .id) %>% - dir(full.names = TRUE) - rv$data <- data.frame( - name = basename(.data.files), - size = base::file.size(.data.files), - type = mime::guess_type(.data.files), - datapath = .data.files - ) - }, - ignoreInit = TRUE, - label = "DPinput" - ) - - observeEvent(input$metadata,{ - rv$md <- input$metadata - showNotification( - "Only one metadata file allowed", - type = "message" + registeredEndpoints <- data.table::fread(main.env$PATHS$resources$registeredEndpoints.txt) + dev <- main.env$dev + + # Select endpoint ---- + endpoint <- reactive({ + input$endpoint + }) + + memberNode <- reactive({ + if (endpoint() != "Other") { + registeredEndpoints %>% + dplyr::filter(mn == endpoint()) %>% + dplyr::select(URL) + } else { + URL_Input("actual-endpoint") + } + }) + + output$`actual-endpoint` <- renderUI({ + if (endpoint() != "Other") { + tags$p(tags$b("Current endpoint:"), memberNode()) + } else { + URL_Input_UI(NS(id, "actual-endpoint"), "Write the URL of the Member Node") + } + }) + + # Token input ---- + observeEvent(input$toSettings, { + shinyjs::click("appOptions", asis = TRUE) + }, ignoreInit = TRUE) + + observe({ + if (!is.character(options("dataone_token")) || + !is.character(options("dataone_test_token")) || + (is.null(options("dataone_token")) && is.null(options("dataone_test_token"))) + ) { + output$token_status <- renderUI({ + tags$div("UNFILLED", class = "danger") + }) + shinyjs::disable("process") + } + else { + output$token_status <- renderUI({ + tags$div("FILLED", class = "valid") + }) + shinyjs::enable("process") + } + }) + + # Files input ---- + rv <- reactiveValues( + md = data.frame(stringsAsFactors = FALSE), + data = data.frame(stringsAsFactors = FALSE), + scr = data.frame(stringsAsFactors = FALSE) ) - }) - observeEvent(input$data,{ - .add <- input$data - req(checkTruth(.add)) - browser() # Update list instead of erasing - rv$data <- rbind(rv$data, .add) - }) - observeEvent(input$scripts,{ - .add <- input$scripts - req(checkTruth(.add)) - browser() # Update list instead of erasing - rv$scr <- rbind(input$scripts, .add) - }) - - output$filesList <- renderUI({ - validate( - need( - dim(rv$md) > 0 || - dim(rv$data) > 0 || - dim(rv$scr) > 0, - "No file selected" + + observeEvent(input$DP, { + .dir <- gsub("/+", "/", input$DP) + .id <- basename(.dir) %>% sub("_emldp$", "", .) + .eml.files <- sprintf("%s/%s/eml", .dir, .id) %>% + dir(full.names = TRUE) + rv$md <- data.frame( + name = basename(.eml.files), + size = base::file.size(.eml.files), + type = mime::guess_type(.eml.files), + datapath= .eml.files ) + + .data.files <- sprintf("%s/%s/data_objects", .dir, .id) %>% + dir(full.names = TRUE) + rv$data <- data.frame( + name = basename(.data.files), + size = base::file.size(.data.files), + type = mime::guess_type(.data.files), + datapath = .data.files + ) + }, + ignoreInit = TRUE, + label = "DPinput" ) - tagList( - if(dim(rv$md)[1] > 0) - checkboxGroupInput( - ns("md-files"), - label = "EML file", - choices = rv$md$name - ), - if(dim(rv$data)[1] > 0) - checkboxGroupInput( - ns("data-files"), - label = "Data files", - choices = rv$data$name - ), - if(dim(rv$scr)[1] > 0) - checkboxGroupInput( - ns("scr-files"), - label = "Scripts", - choices = rv$scr$name - ), - actionButton(ns("rmv"), "Remove", class = "danger") - ) - }) - - observeEvent(input$rmv, { - .rmv <- input$`md-files` - if(checkTruth(.rmv)){ - .ind <- match(.rmv, rv$md$name) - rv$md <- rv$md[-.ind,] - } - .rmv <- input$`data-files` - if(checkTruth(.rmv)){ - .ind <- match(.rmv, rv$data$name) - rv$data <- rv$data[-.ind,] - } - .rmv <- input$`scr-files` - if(checkTruth(.rmv)){ - .ind <- match(.rmv, rv$scr$name) - rv$scr <- rv$scr[-.ind,] - } - }, ignoreInit = TRUE) - - observe({ - if ( - dim(rv$md)[1] != 1 || - dim(rv$data)[1] < 1 - ) { - shinyjs::disable("process") - } else { - shinyjs::enable("process") - } + observeEvent(input$metadata,{ + rv$md <- input$metadata + showNotification( + "Only one metadata file allowed", + type = "message" + ) + }) + observeEvent(input$data,{ + .add <- input$data + req(checkTruth(.add)) + browser() # Update list instead of erasing + rv$data <- rbind(rv$data, .add) + }) + observeEvent(input$scripts,{ + .add <- input$scripts + req(checkTruth(.add)) + browser() # Update list instead of erasing + rv$scr <- rbind(input$scripts, .add) + }) - if ( - dim(rv$scr)[1] == 0 || - dim(rv$data)[1] == 0 - ) { - shinyjs::disable("add_constraint") - } else { - shinyjs::enable("add_constraint") - } - }) - - # Process ----------------------------------------------------- - observeEvent(input$process, { - disable("process") + output$filesList <- renderUI({ + validate( + need( + dim(rv$md) > 0 || + dim(rv$data) > 0 || + dim(rv$scr) > 0, + "No file selected" + ) + ) + + tagList( + if(dim(rv$md)[1] > 0) + checkboxGroupInput( + NS(id, "md-files"), + label = "EML file", + choices = rv$md$name + ), + if(dim(rv$data)[1] > 0) + checkboxGroupInput( + NS(id, "data-files"), + label = "Data files", + choices = rv$data$name + ), + if(dim(rv$scr)[1] > 0) + checkboxGroupInput( + NS(id, "scr-files"), + label = "Scripts", + choices = rv$scr$name + ), + actionButton(NS(id, "rmv"), "Remove", class = "danger") + ) + }) - md.format <- EML::read_eml(as.character(rv$md$datapath))$schemaLocation %>% - strsplit(split = " ") %>% - unlist %>% - utils::head(n = 1) + observeEvent(input$rmv, { + .rmv <- input$`md-files` + if(checkTruth(.rmv)){ + .ind <- match(.rmv, rv$md$name) + rv$md <- rv$md[-.ind,] + } + .rmv <- input$`data-files` + if(checkTruth(.rmv)){ + .ind <- match(.rmv, rv$data$name) + rv$data <- rv$data[-.ind,] + } + .rmv <- input$`scr-files` + if(checkTruth(.rmv)){ + .ind <- match(.rmv, rv$scr$name) + rv$scr <- rv$scr[-.ind,] + } + }, ignoreInit = TRUE) - out <- uploadDP( - mn = registeredEndpoints %>% - dplyr::filter(mn == endpoint()) %>% - dplyr::select(URL) %>% - as.character, - cn = registeredEndpoints %>% - dplyr::filter(mn == endpoint()) %>% - dplyr::select(cn) %>% - as.character, - token = list( - test = main.env$SETTINGS$metacat.test, - prod = main.env$SETTINGS$metacat.token - ), - eml = list( - file = rv$md$datapath, - format = md.format - ), - data = list( - file = rv$data$datapath, - format = mime::guess_type(rv$data$datapath) - ), - scripts = if (dim(rv$scr)[1] > 0) { - list( - file = rv$scr$datapath, - format = mime::guess_type(rv$scr$datapath) - ) + observe({ + if ( + dim(rv$md)[1] != 1 || + dim(rv$data)[1] < 1 + ) { + shinyjs::disable("process") } else { - c() - }, - formats = main.env$FORMAT$dataone.list$MediaType, - use.doi = FALSE - ) - - if (class(out) == "try-error") { - showNotification(out[1], type = "error") - } else { - showNotification(paste("Uploaded DP", out), type = "message") - } + shinyjs::enable("process") + } + + if ( + dim(rv$scr)[1] == 0 || + dim(rv$data)[1] == 0 + ) { + shinyjs::disable("add_constraint") + } else { + shinyjs::enable("add_constraint") + } + }) - shinyjs::enable("process") + # Process ---- + observeEvent(input$process, { + disable("process") + + md.format <- EML::read_eml(as.character(rv$md$datapath))$schemaLocation %>% + strsplit(split = " ") %>% + unlist %>% + utils::head(n = 1) + + out <- uploadDP( + mn = registeredEndpoints %>% + dplyr::filter(mn == endpoint()) %>% + dplyr::select(URL) %>% + as.character, + cn = registeredEndpoints %>% + dplyr::filter(mn == endpoint()) %>% + dplyr::select(cn) %>% + as.character, + token = list( + test = main.env$SETTINGS$metacat.test, + prod = main.env$SETTINGS$metacat.token + ), + eml = list( + file = rv$md$datapath, + format = md.format + ), + data = list( + file = rv$data$datapath, + format = mime::guess_type(rv$data$datapath) + ), + scripts = if (dim(rv$scr)[1] > 0) { + list( + file = rv$scr$datapath, + format = mime::guess_type(rv$scr$datapath) + ) + } else { + c() + }, + formats = main.env$FORMAT$dataone.list$MediaType, + use.doi = FALSE + ) + + if (class(out) == "try-error") { + showNotification(out[1], type = "error") + } else { + showNotification(paste("Uploaded DP", out), type = "message") + } + + shinyjs::enable("process") + }) }) } diff --git a/R/upload-module_functions.R b/R/upload-module_functions.R index 34db758..fa61ab9 100644 --- a/R/upload-module_functions.R +++ b/R/upload-module_functions.R @@ -28,7 +28,7 @@ uploadDP <- function( formats, use.doi = FALSE ) { - # Set variables ----------------------------------------------------- + # Set variables ---- message("Init") @@ -38,7 +38,7 @@ uploadDP <- function( doi <- dataone::generateIdentifier(mn, "DOI") } # TODO check this feature - # # Write DP ----------------------------------------------------- + # # Write DP ---- # set data package dp <- methods::new("DataPackage") @@ -90,13 +90,13 @@ uploadDP <- function( ) } - # # Access rules ----------------------------------------------------- + # # Access rules ---- message("Access") accessRules <- NA # TODO allow customized access rules - # # Upload ----------------------------------------------------- + # # Upload ---- d1c <- dataone::D1Client(cn, mn) @@ -130,15 +130,15 @@ describeWorkflowUI <- function(id, sources, targets) { ns <- NS(id) span( - id = ns("span"), - div(selectInput(ns("script"), "Source script", sources), + id = NS(id, "span"), + div(selectInput(NS(id, "script"), "Source script", sources), style = "display: inline-block; vertical-align: middle;" ), "describes", - div(selectInput(ns("data"), "Target data file", targets), + div(selectInput(NS(id, "data"), "Target data file", targets), style = "display: inline-block; vertical-align: middle;" ), - actionButton(ns("remove"), "", icon("minus"), class = "redButton"), + actionButton(NS(id, "remove"), "", icon("minus"), class = "redButton"), style = "display: inline-block;" ) } @@ -157,7 +157,7 @@ describeWorkflow <- function(input, output, session) { # Remove observeEvent(input$remove, { removeUI( - selector = paste0("#", ns("span")) + selector = paste0("#", NS(id, "span")) ) rv <- NULL }) diff --git a/R/utils-URL_Input.R b/R/utils-URL_Input.R index be44b8b..f92be5f 100644 --- a/R/utils-URL_Input.R +++ b/R/utils-URL_Input.R @@ -13,10 +13,10 @@ #' @import shiny URL_Input_UI <- function(id, label = "URL", width = "100%") { ns <- NS(id) - + tagList( - textInput(ns("url"), label, placeholder = "https://github.com/earnaud/MetaShARK-v2"), - textOutput(ns("warnings")) + textInput(NS(id, "url"), label, placeholder = "https://github.com/earnaud/MetaShARK-v2"), + textOutput(NS(id, "warnings")) ) } @@ -26,25 +26,27 @@ URL_Input_UI <- function(id, label = "URL", width = "100%") { #' #' @import shiny #' @importFrom RCurl url.exists -URL_Input <- function(input, output, session) { - # variable initialization - url <- reactiveVal(character()) - - # actions - observeEvent(input$url, { - is.url <- RCurl::url.exists(input$url) - - output$warnings <- renderText({ - validate( - need(is.url, "Invalid URL target.") - ) - return(NULL) +URL_Input <- function(id){ + moduleServer(id, function(input, output, session) { + # variable initialization + url <- reactiveVal(character()) + + # actions + observeEvent(input$url, { + is.url <- RCurl::url.exists(input$url) + + output$warnings <- renderText({ + validate( + need(is.url, "Invalid URL target.") + ) + return(NULL) + }) + + url <- NA_character_ + req(is.url) + url <- input$url }) - - url <- NA_character_ - req(is.url) - url <- input$url + + return(url) }) - - return(url) } diff --git a/R/utils-collapsible.R b/R/utils-collapsible.R index 2dc91e6..ca97a69 100644 --- a/R/utils-collapsible.R +++ b/R/utils-collapsible.R @@ -12,13 +12,13 @@ #' @importFrom shinyjs useShinyjs hidden collapsibleUI <- function(id, label, .hidden = TRUE, ..., class = NULL) { ns <- NS(id) - - content <- tags$div(id = ns("area"), tagList(...), class = class) - + + content <- tags$div(id = NS(id, "area"), tagList(...), class = class) + tagList( shinyjs::useShinyjs(), actionLink( - ns("link"), + NS(id, "link"), label, icon = if (isTRUE(.hidden)) icon("chevron-right") else icon("chevron-down") ), @@ -36,21 +36,23 @@ collapsibleUI <- function(id, label, .hidden = TRUE, ..., class = NULL) { #' @importFrom shinyjs toggle #' #' @noRd -collapsible <- function(input, output, session) { - observeEvent(input$link, { - shinyjs::toggle( - id = "area", - anim = TRUE, - animType = "slide", - time = 0.25 - ) - - if (input$link %% 2 == 1) { - .tmp <- "chevron-down" - } else { - .tmp <- "chevron-right" - } - - updateActionButton(session, "link", icon = icon(.tmp)) +collapsible <- function(id){ + moduleServer(id, function(input, output, session) { + observeEvent(input$link, { + shinyjs::toggle( + id = "area", + anim = TRUE, + animType = "slide", + time = 0.25 + ) + + if (input$link %% 2 == 1) { + .tmp <- "chevron-down" + } else { + .tmp <- "chevron-right" + } + + updateActionButton(session, "link", icon = icon(.tmp)) + }) }) -} +} \ No newline at end of file diff --git a/R/utils-listReactiveValues.R b/R/utils-listReactiveValues.R index d450c15..e084d62 100644 --- a/R/utils-listReactiveValues.R +++ b/R/utils-listReactiveValues.R @@ -1,7 +1,7 @@ #' @title listReactiveValues #' -#' @description Allows to turn a `reactiveValues`` object -#' into a list. Uses recursive method. +#' @description Allows to turn a `reactiveValues`` object into a list. Uses +#' recursive method. #' #' @param rv reactiveValues to turn into list #' @param lv (verbose purposes) diff --git a/R/utils-markdownInput.R b/R/utils-markdownInput.R index 220ef16..3290e9e 100644 --- a/R/utils-markdownInput.R +++ b/R/utils-markdownInput.R @@ -3,7 +3,7 @@ #' @description A shiny input module designed to allow the user to write markdown and render it as #' a HTML fix. #' -#' @param inputId character. The input slot that will be used to access the value. +#' @param id character. The input slot that will be used to access the value. #' @param label character. Display label for the control, or NULL for no label. #' @param icon character. An optional `icon()` to appear on the button. #' @param preview logical. Shall a preview panel appear? (right-sided, 50\% width) @@ -27,15 +27,14 @@ #' } #' #' shinyApp(ui, server) -markdownInputUI <- function(inputId, label = "Text", icon = TRUE, preview = FALSE, value = "") { - ns <- NS(inputId) +markdownInputUI <- function(id, label = "Text", icon = TRUE, preview = FALSE, value = "") { div( fluidRow( column( if (preview) 6 else 12, if (isFALSE(icon)) tags$b(label) else span(tags$b(label), "(", icon("markdown"), "supported)"), aceEditor( - ns("md"), + NS(id, "md"), value = value, mode = "markdown", showLineNumbers = FALSE, @@ -46,7 +45,7 @@ markdownInputUI <- function(inputId, label = "Text", icon = TRUE, preview = FALS column( 6, h3("Preview:"), - uiOutput(ns("preview")) + uiOutput(NS(id, "preview")) ) } ), @@ -59,16 +58,18 @@ markdownInputUI <- function(inputId, label = "Text", icon = TRUE, preview = FALS #' #' @import shiny #' @importFrom markdown markdownToHTML -markdownInput <- function(input, output, session, preview = FALSE) { - rv <- reactive({ - input$md - }) - - if (preview) { - output$preview <- renderUI({ - HTML(markdownToHTML(file = NULL, text = rv())) +markdownInput <- function(id, preview = FALSE){ + moduleServer(id, function(input, output, session) { + rv <- reactive({ + input$md }) - } - - return(rv) + + if (preview) { + output$preview <- renderUI({ + HTML(markdownToHTML(file = NULL, text = rv())) + }) + } + + return(rv) + }) } diff --git a/R/utils-observersSet.R b/R/utils-observersSet.R deleted file mode 100644 index 039f227..0000000 --- a/R/utils-observersSet.R +++ /dev/null @@ -1,14 +0,0 @@ -observersSet <- function(){ - # Variable - obs <- list() - - # Methods - list( - suspendAll = function(obsSet){ - - }, - runAll = function(obsSet){ - - } - ) -} \ No newline at end of file diff --git a/R/utils-readPlaintext.R b/R/utils-readPlaintext.R new file mode 100644 index 0000000..090018d --- /dev/null +++ b/R/utils-readPlaintext.R @@ -0,0 +1,19 @@ +#' @title readFilesText +#' +#' @param files files basename located in the same directory or, +#' if prefix = NULL, list of full filenames to read +#' @param prefix common file prefix for all file names +#' specified in 'files'. By default, sep = "/" +#' +#' @importFrom readtext readtext +readPlainText <- function(files, prefix = NULL, sep = "/", ...) { + if (is.null(prefix)) sep <- "" + + readtext::readtext( + paste( + prefix, + files, + sep = sep + ) + )$text +} \ No newline at end of file diff --git a/R/utils-setSavevar.R b/R/utils-setSavevar.R deleted file mode 100644 index 6f4c648..0000000 --- a/R/utils-setSavevar.R +++ /dev/null @@ -1,31 +0,0 @@ -#' @import shiny -setSavevar <- function(content, save.variable, lv = 1, root = "root") { - - lapply( - names(content), - function(label) { - sub.content <- content[[label]] - type.content <- typeof(sub.content) - sub.save.variable <- savevar[[label]] - type.save.variable <- typeof(sub.savevar) - - if (is.reactivevalues(sub.save.variable)) { - if (!is.data.frame(sub.content) && - is.list(sub.content)) { - x <- setSavevar(content[[label]], save.variable[[label]], lv = lv + 1, root = label) - } - else { - x <- sub.content - } - } - else { - x <- sub.content - } - - isolate(save.variable[[label]] <- x) - return(NULL) - } - ) - - return(save.variable) -} diff --git a/R/utils-writeText.R b/R/utils-writeText.R index 1a4e87a..090355c 100644 --- a/R/utils-writeText.R +++ b/R/utils-writeText.R @@ -9,7 +9,7 @@ #' #' @export write.text <- function(x, file = ".", collapse = "\n") { - # Validity check ----------------------------------------------------- + # Validity check ---- if (missing(x)) { stop("Error: no text has been provided.") } @@ -24,7 +24,7 @@ write.text <- function(x, file = ".", collapse = "\n") { warning("Length of 'file' > 1 : only the first element has been used.") } - # Process data ----------------------------------------------------- + # Process data ---- if (is.list(x)) { x <- unlist(x) } @@ -32,7 +32,7 @@ write.text <- function(x, file = ".", collapse = "\n") { x <- paste(x, collapse = collapse) } - # Proper write ----------------------------------------------------- + # Proper write ---- fileConn <- file(file) writeLines(x, fileConn) close(fileConn) diff --git a/R/golem_utils_ui.R b/R/utils_withRedStar.R similarity index 100% rename from R/golem_utils_ui.R rename to R/utils_withRedStar.R diff --git a/inst/media/hex-MetaShARK.hex b/inst/media/hex-MetaShARK.hex new file mode 100644 index 0000000000000000000000000000000000000000..190afa6fc7b693b20d96968d139246d448c756d4 GIT binary patch literal 17311 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 literal 0 HcmV?d00001 diff --git a/inst/media/hex-MetaShARK.png b/inst/media/hex-MetaShARK.png new file mode 100644 index 0000000000000000000000000000000000000000..a323b3a95809ab0b10eff0c8824425ad93977623 GIT binary patch literal 117572 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

h_ta=cf;Ey>PmD;;R#-uTh@ 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 literal 0 HcmV?d00001 diff --git a/man/AttributesUI.Rd b/man/AttributesUI.Rd deleted file mode 100644 index 5c541b5..0000000 --- a/man/AttributesUI.Rd +++ /dev/null @@ -1,21 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/eal_3_Attributes.R -\name{AttributesUI} -\alias{AttributesUI} -\alias{Attributes} -\title{Data Package Template filling} -\usage{ -AttributesUI(id, title, dev) - -Attributes(input, output, session, save.variable, main.env, NSB) -} -\description{ -UI part of the Attributes module. Fill in the attributes of the data package - -server part of the Attributes module. -} -\section{Functions}{ -\itemize{ -\item \code{Attributes}: -}} - diff --git a/man/CatVars.Rd b/man/CatVars.Rd deleted file mode 100644 index c94ba0d..0000000 --- a/man/CatVars.Rd +++ /dev/null @@ -1,11 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/eal_4_CatVars.R -\name{CatVars} -\alias{CatVars} -\title{Geographic coverage} -\usage{ -CatVars(input, output, session, save.variable, main.env, NSB) -} -\description{ -UI part for the Geographic Coverage module -} diff --git a/man/CatVarsUI.Rd b/man/CatVarsUI.Rd deleted file mode 100644 index 7b9a5c8..0000000 --- a/man/CatVarsUI.Rd +++ /dev/null @@ -1,11 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/eal_4_CatVars.R -\name{CatVarsUI} -\alias{CatVarsUI} -\title{Geographic coverage} -\usage{ -CatVarsUI(id, title, dev) -} -\description{ -UI part for the Geographic Coverage module -} diff --git a/man/DataFiles.Rd b/man/DataFiles.Rd deleted file mode 100644 index d7b321c..0000000 --- a/man/DataFiles.Rd +++ /dev/null @@ -1,11 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/eal_2_DataFiles.R -\name{DataFiles} -\alias{DataFiles} -\title{Data Package files} -\usage{ -DataFiles(input, output, session, save.variable, main.env, NSB) -} -\description{ -server part of the DataFiles module. -} diff --git a/man/DataFilesUI.Rd b/man/DataFilesUI.Rd deleted file mode 100644 index 2506882..0000000 --- a/man/DataFilesUI.Rd +++ /dev/null @@ -1,11 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/eal_2_DataFiles.R -\name{DataFilesUI} -\alias{DataFilesUI} -\title{Data Package files} -\usage{ -DataFilesUI(id, dev = FALSE) -} -\description{ -UI part of the DataFiles module. -} diff --git a/man/EMLAL.Rd b/man/EMLAL.Rd deleted file mode 100644 index a0fa9bd..0000000 --- a/man/EMLAL.Rd +++ /dev/null @@ -1,12 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/eal_0.R -\name{EMLAL} -\alias{EMLAL} -\title{EMLAL} -\usage{ -EMLAL(input, output, session, save.variable, main.env) -} -\description{ -server part of the EMLAL module. Allow the user to use a front-end shiny interface to the EML Assembly Line package, from -Environmental Data Initiative. -} diff --git a/man/EMLALUI.Rd b/man/EMLALUI.Rd deleted file mode 100644 index 95bda46..0000000 --- a/man/EMLALUI.Rd +++ /dev/null @@ -1,12 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/eal_0.R -\name{EMLALUI} -\alias{EMLALUI} -\title{EMLALUI} -\usage{ -EMLALUI(id, dev = FALSE) -} -\description{ -UI part of the EMLAL module. Allow the user to use a front-end shiny interface to the EML Assembly Line package, from -Environmental Data Initiative. ARAR -} diff --git a/man/GeoCov.Rd b/man/GeoCov.Rd deleted file mode 100644 index c71fcf1..0000000 --- a/man/GeoCov.Rd +++ /dev/null @@ -1,11 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/eal_5_geographicCoverage.R -\name{GeoCov} -\alias{GeoCov} -\title{Geographic coverage} -\usage{ -GeoCov(input, output, session, save.variable, main.env, NSB) -} -\description{ -server part for the Geographic Coverage module -} diff --git a/man/GeoCovInputUI.Rd b/man/GeoCovInputUI.Rd deleted file mode 100644 index 52c8c20..0000000 --- a/man/GeoCovInputUI.Rd +++ /dev/null @@ -1,20 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/eal_5_GeoCovInput.R -\name{GeoCovInputUI} -\alias{GeoCovInputUI} -\alias{GeoCovInput} -\title{Geographic coverage modular Input} -\usage{ -GeoCovInputUI(id, site.id, rmv.id, default = NULL) - -GeoCovInput(input, output, session, rv, rmv.id, site.id, ref) -} -\description{ -UI part for the Geographic Coverage modular input, used -in Geographic Coverage module to input a custom entry in the dataset. -} -\section{Functions}{ -\itemize{ -\item \code{GeoCovInput}: -}} - diff --git a/man/GeoCovUI.Rd b/man/GeoCovUI.Rd deleted file mode 100644 index 6161e97..0000000 --- a/man/GeoCovUI.Rd +++ /dev/null @@ -1,11 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/eal_5_geographicCoverage.R -\name{GeoCovUI} -\alias{GeoCovUI} -\title{Geographic coverage} -\usage{ -GeoCovUI(id, title, dev) -} -\description{ -UI part for the Geographic Coverage module -} diff --git a/man/MakeEMLUI.Rd b/man/MakeEMLUI.Rd deleted file mode 100644 index d8d385f..0000000 --- a/man/MakeEMLUI.Rd +++ /dev/null @@ -1,21 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/eal_9_makeeml.R -\name{MakeEMLUI} -\alias{MakeEMLUI} -\alias{MakeEML} -\title{MakeEMLUI} -\usage{ -MakeEMLUI(id, title, dev) - -MakeEML(input, output, session, save.variable, main.env) -} -\description{ -UI part for the Make EML module - -server part of the make EML module -} -\section{Functions}{ -\itemize{ -\item \code{MakeEML}: -}} - diff --git a/man/MiscUI.Rd b/man/MiscUI.Rd deleted file mode 100644 index 7d45d6a..0000000 --- a/man/MiscUI.Rd +++ /dev/null @@ -1,19 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/eal_8_misc.R -\name{MiscUI} -\alias{MiscUI} -\alias{Misc} -\title{MiscUI} -\usage{ -MiscUI(id, title, dev, save.variable) - -Misc(input, output, session, save.variable, main.env, NSB) -} -\description{ -UI for "last but not least" module -} -\section{Functions}{ -\itemize{ -\item \code{Misc}: -}} - diff --git a/man/Miscellaneous.Rd b/man/Miscellaneous.Rd deleted file mode 100644 index 335253b..0000000 --- a/man/Miscellaneous.Rd +++ /dev/null @@ -1,11 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/eal_8_miscellaneous.R -\name{Miscellaneous} -\alias{Miscellaneous} -\title{Miscellaneous} -\usage{ -Miscellaneous(input, output, session, save.variable, rv) -} -\description{ -Miscellaneous -} diff --git a/man/MiscellaneousUI.Rd b/man/MiscellaneousUI.Rd deleted file mode 100644 index 4f55efd..0000000 --- a/man/MiscellaneousUI.Rd +++ /dev/null @@ -1,11 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/eal_8_miscellaneous.R -\name{MiscellaneousUI} -\alias{MiscellaneousUI} -\title{MiscellaneousUI} -\usage{ -MiscellaneousUI(id, help.label = NULL, value = "") -} -\description{ - -} diff --git a/man/Personnel.Rd b/man/Personnel.Rd deleted file mode 100644 index 75a1e5c..0000000 --- a/man/Personnel.Rd +++ /dev/null @@ -1,11 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/eal_7_personnel.R -\name{Personnel} -\alias{Personnel} -\title{Personnel} -\usage{ -Personnel(input, output, session, save.variable, main.env, NSB) -} -\description{ -server part of Personnel module -} diff --git a/man/PersonnelModUI.Rd b/man/PersonnelModUI.Rd deleted file mode 100644 index 9b62072..0000000 --- a/man/PersonnelModUI.Rd +++ /dev/null @@ -1,30 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/eal_7_personnel.R -\name{PersonnelModUI} -\alias{PersonnelModUI} -\alias{PersonnelMod} -\title{PersonnelModUI} -\usage{ -PersonnelModUI(id, div.id, site.id, rmv.id, role = NULL, saved = NULL) - -PersonnelMod( - input, - output, - session, - main.env, - rv, - rmv.id, - site.id, - ref, - role = NULL, - saved = NULL -) -} -\description{ -module to document EML Personnel -} -\section{Functions}{ -\itemize{ -\item \code{PersonnelMod}: -}} - diff --git a/man/PersonnelUI.Rd b/man/PersonnelUI.Rd deleted file mode 100644 index 022a35d..0000000 --- a/man/PersonnelUI.Rd +++ /dev/null @@ -1,11 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/eal_7_personnel.R -\name{PersonnelUI} -\alias{PersonnelUI} -\title{PersonnelUI} -\usage{ -PersonnelUI(id, title, dev) -} -\description{ -PersonnelUI -} diff --git a/man/SelectDP.Rd b/man/SelectDP.Rd deleted file mode 100644 index 45c356c..0000000 --- a/man/SelectDP.Rd +++ /dev/null @@ -1,12 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/eal_1_SelectDP.R -\name{SelectDP} -\alias{SelectDP} -\title{Data Package selection} -\usage{ -SelectDP(input, output, session, save.variable, main.env) -} -\description{ -UI part for the Data Package selection. Allow the user to choose between -creating a new data package or loading an existing one. -} diff --git a/man/SelectDPUI.Rd b/man/SelectDPUI.Rd deleted file mode 100644 index c4cda88..0000000 --- a/man/SelectDPUI.Rd +++ /dev/null @@ -1,20 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/eal_1_SelectDP.R -\name{SelectDPUI} -\alias{SelectDPUI} -\alias{loadFromDP} -\title{Data Package selection} -\usage{ -SelectDPUI(id, width = 12, dev = FALSE) - -loadFromDP(save.variable, file) -} -\description{ -UI part for the Data Package selection. Allow the user to choose between -creating a new data package or loading an existing one. -} -\section{Functions}{ -\itemize{ -\item \code{loadFromDP}: Sets up a DP from a pre-written EML file. -}} - diff --git a/man/TaxCov.Rd b/man/TaxCov.Rd deleted file mode 100644 index 46151ce..0000000 --- a/man/TaxCov.Rd +++ /dev/null @@ -1,11 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/eal_6_taxonomicCoverage.R -\name{TaxCov} -\alias{TaxCov} -\title{Taxonomic coverage} -\usage{ -TaxCov(input, output, session, save.variable, main.env, NSB) -} -\description{ -server part for the Taxonomic Coverage module -} diff --git a/man/TaxCovUI.Rd b/man/TaxCovUI.Rd deleted file mode 100644 index 2de741c..0000000 --- a/man/TaxCovUI.Rd +++ /dev/null @@ -1,11 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/eal_6_taxonomicCoverage.R -\name{TaxCovUI} -\alias{TaxCovUI} -\title{Taxonomic coverage} -\usage{ -TaxCovUI(id, title, dev) -} -\description{ -UI part for the Taxonomic Coverage module -} diff --git a/man/URL_Input_UI.Rd b/man/URL_Input_UI.Rd index b3794b5..553bb84 100644 --- a/man/URL_Input_UI.Rd +++ b/man/URL_Input_UI.Rd @@ -7,7 +7,15 @@ \usage{ URL_Input_UI(id, label = "URL", width = "100\%") -URL_Input(input, output, session) +URL_Input(id) +} +\arguments{ +\item{id}{(character) shiny module inputId.} + +\item{label}{(character) display label for the control, or NULL for no label.} + +\item{width}{(character) the width of the input, e.g. '400px', or '100%'; see +validateCssUnit().} } \value{ (output of `callModule`) If input is a valid URL (regex-tested + curl-tested), returns input. diff --git a/man/about.Rd b/man/about.Rd deleted file mode 100644 index 1bcdb77..0000000 --- a/man/about.Rd +++ /dev/null @@ -1,11 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/about-module.R -\name{about} -\alias{about} -\title{about} -\usage{ -about(input, output, session) -} -\description{ -server part of the about module. -} diff --git a/man/aboutUI.Rd b/man/aboutUI.Rd deleted file mode 100644 index 5d481b3..0000000 --- a/man/aboutUI.Rd +++ /dev/null @@ -1,11 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/aboutUI-module.R -\name{aboutUI} -\alias{aboutUI} -\title{aboutUI} -\usage{ -aboutUI(id) -} -\description{ -UI part of the about module. -} diff --git a/man/checkTruth.Rd b/man/checkTruth.Rd index da8e1ce..ff2dec7 100644 --- a/man/checkTruth.Rd +++ b/man/checkTruth.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/fill-module_functions.R +% Please edit documentation in R/utils-checkTruth.R \name{checkTruth} \alias{checkTruth} \title{checkTruth} @@ -8,8 +8,6 @@ checkTruth(x) } \arguments{ \item{x}{argument to check fo truthiness} - -\item{output}{what to return if `x` is not truthy} } \description{ check if `x` is truthy (as shiny::isTruthy) or not. diff --git a/man/collapsibleUI.Rd b/man/collapsibleUI.Rd index 385922c..bc523d1 100644 --- a/man/collapsibleUI.Rd +++ b/man/collapsibleUI.Rd @@ -2,14 +2,13 @@ % Please edit documentation in R/utils-collapsible.R \name{collapsibleUI} \alias{collapsibleUI} -\alias{collapsible} \title{collapsibleUI} \usage{ collapsibleUI(id, label, .hidden = TRUE, ..., class = NULL) - -collapsible(input, output, session) } \arguments{ +\item{id}{character. The input slot that will be used to access the value.} + \item{label}{character. A label appearing on the clickable link.} \item{.hidden}{logical. A flag to make the UI display as collapsed or not.} @@ -21,8 +20,3 @@ collapsible(input, output, session) \description{ A shiny module to get a div collapsed by clicking on a link. } -\section{Functions}{ -\itemize{ -\item \code{collapsible}: -}} - diff --git a/man/describeWorkflowUI.Rd b/man/describeWorkflowUI.Rd deleted file mode 100644 index 85c5e3b..0000000 --- a/man/describeWorkflowUI.Rd +++ /dev/null @@ -1,21 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/upload-module_functions.R -\name{describeWorkflowUI} -\alias{describeWorkflowUI} -\alias{describeWorkflow} -\title{describeWorkflowUI} -\usage{ -describeWorkflowUI(id, sources, targets) - -describeWorkflow(input, output, session) -} -\description{ -UI part of the script-data workflow-describing linking module (in upload). - -server part of the script-data workflow-describing linking module (in upload). -} -\section{Functions}{ -\itemize{ -\item \code{describeWorkflow}: -}} - diff --git a/man/docUI.Rd b/man/docUI.Rd deleted file mode 100644 index 9afceed..0000000 --- a/man/docUI.Rd +++ /dev/null @@ -1,11 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/documentation-module.R -\name{docUI} -\alias{docUI} -\title{docUI} -\usage{ -docUI(id) -} -\description{ -UI part of the documentation module -} diff --git a/man/documentation.Rd b/man/documentation.Rd deleted file mode 100644 index 5ca5e68..0000000 --- a/man/documentation.Rd +++ /dev/null @@ -1,11 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/documentation-module.R -\name{documentation} -\alias{documentation} -\title{documentation} -\usage{ -documentation(input, output, session) -} -\description{ -server part of the documentation module. -} diff --git a/man/dot-app_server.Rd b/man/dot-app_server.Rd deleted file mode 100644 index b5405ee..0000000 --- a/man/dot-app_server.Rd +++ /dev/null @@ -1,11 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/server.R -\name{.app_server} -\alias{.app_server} -\title{.app_server} -\usage{ -.app_server(input, output, session) -} -\description{ -server part for the app's main script. -} diff --git a/man/dot-app_ui.Rd b/man/dot-app_ui.Rd deleted file mode 100644 index 3eabc7a..0000000 --- a/man/dot-app_ui.Rd +++ /dev/null @@ -1,11 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/ui.R -\name{.app_ui} -\alias{.app_ui} -\title{.app_ui} -\usage{ -.app_ui() -} -\description{ -UI part of the mainapp's script -} diff --git a/man/dot-globalScript.Rd b/man/dot-globalScript.Rd deleted file mode 100644 index b1e8100..0000000 --- a/man/dot-globalScript.Rd +++ /dev/null @@ -1,11 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/headerScript.R -\name{.globalScript} -\alias{.globalScript} -\title{.globalScript} -\usage{ -.globalScript(dev = FALSE) -} -\description{ -script to generate `globals` reactiveValues -} diff --git a/man/dot-headerScript.Rd b/man/dot-headerScript.Rd deleted file mode 100644 index b02f0a3..0000000 --- a/man/dot-headerScript.Rd +++ /dev/null @@ -1,11 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/headerScript.R -\name{.headerScript} -\alias{.headerScript} -\title{.headerScript} -\usage{ -.headerScript() -} -\description{ -Misc preparations commands -} diff --git a/man/extractCoordinates.Rd b/man/extractCoordinates.Rd deleted file mode 100644 index 1989156..0000000 --- a/man/extractCoordinates.Rd +++ /dev/null @@ -1,11 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/eal_5_GeoCovInput.R -\name{extractCoordinates} -\alias{extractCoordinates} -\title{extractCoordinates} -\usage{ -extractCoordinates(rv, coord.cols, .pattern, files.data) -} -\description{ -extractCoordinates -} diff --git a/man/fillUI.Rd b/man/fillUI.Rd deleted file mode 100644 index ccdafdc..0000000 --- a/man/fillUI.Rd +++ /dev/null @@ -1,19 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/fill-module.R -\name{fillUI} -\alias{fillUI} -\alias{fill} -\title{Fill} -\usage{ -fillUI(id, dev = FALSE) - -fill(input, output, session, main.env) -} -\description{ -server part of the fill module. Root script for whole module (comprise EML AL and MetaFIN) -} -\section{Functions}{ -\itemize{ -\item \code{fill}: -}} - diff --git a/man/followPath.Rd b/man/followPath.Rd index 9bc5cdc..df638e9 100644 --- a/man/followPath.Rd +++ b/man/followPath.Rd @@ -1,12 +1,9 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/documentation-module_functions.R, -% R/utils-followPath.R +% Please edit documentation in R/utils-followPath.R \name{followPath} \alias{followPath} \title{followPath} \usage{ -followPath(tree, path, sep = "/", root = "root") - followPath(tree, path, sep = "/", root = "root") } \arguments{ @@ -19,17 +16,7 @@ separated with sep} \item{root}{if your path has a root name for root node, enter its name here. Else, enter NULL.} - -\item{tree:}{explored hierarchy list thanks to @path} - -\item{path:}{vector of characters matching some of @tree names and -separated with sep} - -\item{sep:}{separators between path elements (aka @tree names)} } \description{ -Takes a hierarchy list (tree), a path written in a vector pasted -with sep = sep, and returns the targetted node - Takes a hierarchy list (tree), a path written in a vector pasted with sep, and returns the leaf } diff --git a/man/initReactive.Rd b/man/initReactive.Rd deleted file mode 100644 index cbbba2b..0000000 --- a/man/initReactive.Rd +++ /dev/null @@ -1,27 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/fill-module_functions.R -\name{initReactive} -\alias{initReactive} -\alias{saveReactive} -\title{initReactive} -\usage{ -initReactive(sub.list = NULL, save.variable = NULL, main.env) - -saveReactive(save.variable, rv = NULL, main.env = NULL) -} -\arguments{ -\item{sub.list}{either NULL, "emlal", "metafin" to precise which sub.list to initialize (NULL initializes the whole variable)} -} -\value{ -`save.variable` modified. -} -\description{ -EMLAL module specific function. Initialize `save.variable` variable. - -save the `save.variable` variable at wanted location -} -\section{Functions}{ -\itemize{ -\item \code{saveReactive}: -}} - diff --git a/man/insertGeoCovInput.Rd b/man/insertGeoCovInput.Rd deleted file mode 100644 index 845614b..0000000 --- a/man/insertGeoCovInput.Rd +++ /dev/null @@ -1,12 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/eal_5_GeoCovInput.R -\name{insertGeoCovInput} -\alias{insertGeoCovInput} -\title{insertGeoCovInput} -\usage{ -insertGeoCovInput(id, rv, ns, default = NULL) -} -\description{ -Leads all the process of rendering a GeoCovInput -GUI and its associated server -} diff --git a/man/insertPersonnelInput.Rd b/man/insertPersonnelInput.Rd deleted file mode 100644 index 9b2330a..0000000 --- a/man/insertPersonnelInput.Rd +++ /dev/null @@ -1,13 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/eal_7_personnel.R -\name{insertPersonnelInput} -\alias{insertPersonnelInput} -\title{insertPersonnelInput} -\usage{ -insertPersonnelInput(id, rv, ns, main.env, role = NULL, saved = NULL) -} -\description{ -helper function to insert PersonnelMod* functions. Calling this from -a shiny server will insert PersonnelModUI and create its server part. Provided with -features to delete them. -} diff --git a/man/listReactiveValues.Rd b/man/listReactiveValues.Rd index aa85950..93f4fa4 100644 --- a/man/listReactiveValues.Rd +++ b/man/listReactiveValues.Rd @@ -10,8 +10,10 @@ listReactiveValues(rv, lv = 0, name = "root") \item{rv}{reactiveValues to turn into list} \item{lv}{(verbose purposes)} + +\item{name}{root node name} } \description{ -Allows to turn a `reactiveValues`` object -into a list. Uses recursive method. +Allows to turn a `reactiveValues`` object into a list. Uses +recursive method. } diff --git a/man/markdownInputUI.Rd b/man/markdownInputUI.Rd index 5077f6b..59644b8 100644 --- a/man/markdownInputUI.Rd +++ b/man/markdownInputUI.Rd @@ -5,21 +5,17 @@ \alias{markdownInput} \title{markdownInputUI} \usage{ -markdownInputUI( - inputId, - label = "Text", - icon = TRUE, - preview = FALSE, - value = "" -) +markdownInputUI(id, label = "Text", icon = TRUE, preview = FALSE, value = "") -markdownInput(input, output, session, preview = FALSE) +markdownInput(id, preview = FALSE) } \arguments{ -\item{inputId}{character. The input slot that will be used to access the value.} +\item{id}{character. The input slot that will be used to access the value.} \item{label}{character. Display label for the control, or NULL for no label.} +\item{icon}{character. An optional `icon()` to appear on the button.} + \item{preview}{logical. Shall a preview panel appear? (right-sided, 50\% width)} \item{value}{character. Initial value of the text input (default to "")} diff --git a/man/navSidebar.Rd b/man/navSidebar.Rd deleted file mode 100644 index 057da37..0000000 --- a/man/navSidebar.Rd +++ /dev/null @@ -1,42 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/eal_0_functions.R -\name{navSidebar} -\alias{navSidebar} -\alias{onQuit} -\alias{onSave} -\alias{nextTab} -\alias{prevTab} -\title{navSidebar} -\usage{ -navSidebar(id, main.env, save.variable) - -onQuit(input, output, session, main.env, save.variable, NSB) - -onSave(input, output, session, save.variable, NSB) - -nextTab(input, output, session, main.env, save.variable, NSB) - -prevTab(input, output, session, main.env, NSB) -} -\arguments{ -\item{id}{shiny server id} - -\item{main.env}{MetaShARK main.env variable} - -\item{save.variable}{MetaShARK savevar variable} -} -\description{ -server part for shiny navigation sidebar module (see [navSidebar()]). -The functions are very specific and thus are not exported. -} -\section{Functions}{ -\itemize{ -\item \code{onQuit}: - -\item \code{onSave}: - -\item \code{nextTab}: - -\item \code{prevTab}: -}} - diff --git a/man/navSidebarUI.Rd b/man/navSidebarUI.Rd deleted file mode 100644 index 633e543..0000000 --- a/man/navSidebarUI.Rd +++ /dev/null @@ -1,50 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/eal_0_functions.R -\name{navSidebarUI} -\alias{navSidebarUI} -\alias{quitButton} -\alias{saveButton} -\alias{nextTabButton} -\alias{prevTabButton} -\title{navSidebarUI} -\usage{ -navSidebarUI(id, class = "navSidebar", .prev = TRUE, .next = TRUE) - -quitButton(id) - -saveButton(id) - -nextTabButton(id) - -prevTabButton(id) -} -\arguments{ -\item{id}{shiny id} - -\item{class}{css class style. Default is set to "navSidebar": -.navSidebar { - width: 100%; - text-align: center; - padding: 0; -}} - -\item{.prev}{logical. Do you want a "Previous" actionButton? (prevTabButton)} - -\item{.next}{logical. Do you want a "Next" actionButton? (nextTabButton)} - -\item{...}{UI tags set at the bottom of the navigation side bar} -} -\description{ -UI part for shiny navigation sidebar module -} -\section{Functions}{ -\itemize{ -\item \code{quitButton}: - -\item \code{saveButton}: - -\item \code{nextTabButton}: - -\item \code{prevTabButton}: -}} - diff --git a/man/readPlainText.Rd b/man/readPlainText.Rd index 27e28cb..e349889 100644 --- a/man/readPlainText.Rd +++ b/man/readPlainText.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/fill-module_functions.R +% Please edit documentation in R/utils-readPlaintext.R \name{readPlainText} \alias{readPlainText} \title{readFilesText} diff --git a/man/settings.Rd b/man/settings.Rd index 2399e1d..12efeac 100644 --- a/man/settings.Rd +++ b/man/settings.Rd @@ -4,7 +4,7 @@ \alias{settings} \title{settings} \usage{ -settings(input, output, session, main.env) +settings(id, main.env) } \description{ server part of the settings module. Allow the user to change several settings in the app. diff --git a/man/uploadUI.Rd b/man/uploadUI.Rd index c94b49f..9c2b522 100644 --- a/man/uploadUI.Rd +++ b/man/uploadUI.Rd @@ -7,7 +7,7 @@ \usage{ uploadUI(id, main.env) -upload(input, output, session, main.env) +upload(id, main.env) } \arguments{ \item{id}{shiny module id} diff --git a/man/withRedStar.Rd b/man/withRedStar.Rd index 5c0f686..7188c4e 100644 --- a/man/withRedStar.Rd +++ b/man/withRedStar.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/golem_utils_ui.R +% Please edit documentation in R/utils_withRedStar.R \name{withRedStar} \alias{withRedStar} \title{withRedStar}