From 708a6c29df2039665d5e4084fa53f7005c9b92ea Mon Sep 17 00:00:00 2001 From: afwillia Date: Thu, 26 Oct 2023 11:30:51 -0700 Subject: [PATCH 01/41] Read in dcc config as json instead of csv. Move template menu config to server.R --- global.R | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/global.R b/global.R index 585042df..62a303f7 100644 --- a/global.R +++ b/global.R @@ -35,8 +35,10 @@ plan(multicore, workers = ncores) source_files <- list.files(c("functions", "modules"), pattern = "*\\.R$", recursive = TRUE, full.names = TRUE) sapply(source_files, FUN = source) -dcc_config_file <- Sys.getenv("DCA_DCC_CONFIG") -dcc_config <- read_csv(dcc_config_file, show_col_types = FALSE) +if (Sys.getenv("DCA_DCC_CONFIG") == "") stop("missing DCA_DCC_CONFIG environment variable") +dca_dcc_config <- read_json(Sys.getenv("DCA_DCC_CONFIG"), simplifyVector = TRUE) +tenants_config <- dca_dcc_config$tenants + ## Set Up OAuth client_id <- Sys.getenv("DCA_CLIENT_ID") @@ -125,11 +127,6 @@ api <- oauth_endpoint( # The 'openid' scope is required by the protocol for retrieving user information. scope <- "openid view download modify" -template_config_files <- setNames(dcc_config$template_menu_config_file, -dcc_config$synapse_asset_view) -if (dca_schematic_api == "offline") template_config_files <- setNames("www/template_config/config_offline.json", - "synXXXXXX") - ## Set Up Virtual Environment # ShinyAppys has a limit of 7000 files which this app' grossly exceeds # due to its Python dependencies. To get around the limit we zip up From 7b19f592aee7cd241373d8232817f9b25e4adec2 Mon Sep 17 00:00:00 2001 From: afwillia Date: Thu, 26 Oct 2023 11:31:44 -0700 Subject: [PATCH 02/41] Refactor asset view dropdown to be consistent with new config in global.R --- ui.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui.R b/ui.R index bcc3a80a..d39afd82 100644 --- a/ui.R +++ b/ui.R @@ -138,8 +138,8 @@ ui <- shinydashboardPlus::dashboardPage( selectInput( inputId = "dropdown_asset_view", label = NULL, - choices = setNames(dcc_config$synapse_asset_view, - dcc_config$project_name) + choices = setNames(tenants_config$synapse_asset_view, + tenants_config$name) ), actionButton("btn_asset_view", "Next", class = "btn-primary-color" From 759bc1319ff5549ffefd450724bf7b0d2d2d6185 Mon Sep 17 00:00:00 2001 From: afwillia Date: Thu, 26 Oct 2023 11:32:45 -0700 Subject: [PATCH 03/41] WIP: first pass at refactoring server code to handle the new dcc config json file --- server.R | 60 ++++++++++++++++++++------------------------------------ 1 file changed, 21 insertions(+), 39 deletions(-) diff --git a/server.R b/server.R index c05bd399..4015ffab 100644 --- a/server.R +++ b/server.R @@ -34,25 +34,18 @@ shinyServer(function(input, output, session) { ######## session global variables ######## # read config in - if (grepl("dev", dcc_config_file)) { - def_config <- fromJSON("https://raw.githubusercontent.com/Sage-Bionetworks/data_curator_config/dev/demo/dca-template-config.json") - } else if (grepl("staging", dcc_config_file)) { - def_config <- fromJSON("https://raw.githubusercontent.com/Sage-Bionetworks/data_curator_config/staging/demo/dca-template-config.json") - } else def_config <- fromJSON("https://raw.githubusercontent.com/Sage-Bionetworks/data_curator_config/main/demo/dca-template-config.json") - config <- reactiveVal() - config_schema <- reactiveVal(def_config) - model_ops <- setNames(dcc_config$data_model_url, - dcc_config$synapse_asset_view) + config_schema <- reactiveVal() # mapping from display name to schema name template_namedList <- reactiveVal() - all_asset_views <- setNames(dcc_config$synapse_asset_view, - dcc_config$project_name) + all_asset_views <- setNames(tenants_config$synapse_asset_view, + tenants_config$name) asset_views <- reactiveVal(c("mock dca fileview"="syn33715412")) - dcc_config_react <- reactiveVal(dcc_config) + dcc_config_react <- reactiveVal() + tenant_config_react <- reactiveVal() manifest_data <- reactiveVal() validation_res <- reactiveVal() @@ -60,7 +53,7 @@ shinyServer(function(input, output, session) { data_list <- list( projects = reactiveVal(NA), folders = reactiveVal(NULL), - template = reactiveVal(setNames(def_config$schema_name, def_config$display_name)), + template = reactiveVal(NULL), files = reactiveVal(NULL), master_asset_view = reactiveVal(NULL) ) @@ -74,10 +67,11 @@ shinyServer(function(input, output, session) { isUpdateFolder <- reactiveVal(FALSE) - data_model_options <- setNames(dcc_config$data_model_url, - dcc_config$synapse_asset_view) data_model = reactiveVal(NULL) + if (dca_schematic_api == "offline") template_config_files <- setNames("www/template_config/config_offline.json", + "synXXXXXX") + # data available to the user syn_store <- NULL # gets list of projects they have access to @@ -169,10 +163,18 @@ shinyServer(function(input, output, session) { av_names <- names(asset_views()[asset_views() %in% selected$master_asset_view()]) selected$master_asset_view_label(av_names) - dcc_config_react(dcc_config[dcc_config$synapse_asset_view == selected$master_asset_view(), ]) - if (dca_schematic_api == "offline") dcc_config_react(dcc_config[dcc_config$project_name == "DCA Demo", ]) + tenant_config_react(tenants_config[tenants_config$synapse_asset_view == selected$master_asset_view(), ]) + if (dca_schematic_api == "offline") tenant_config_react(tenants_config[tenants_config$name == "DCA Demo", ]) + + dcc_config_react(read_json(tenant_config_react()$config_location)) + + model_ops <- reactive(setNames(dcc_config_react()$data_model_url, + dcc_config_react()$synapse_asset_view)) - data_model(data_model_options[selected$master_asset_view()]) + data_model(model_ops()) + + template_config_files <- setNames(dcc_config_react()$template_menu_config_file, + dcc_config_react()$synapse_asset_view) output$sass <- renderUI({ tags$head(tags$style(css())) @@ -232,27 +234,7 @@ shinyServer(function(input, output, session) { # Use the template dropdown config file from the appropriate branch of # data_curator_config conf_file <- reactiveVal(template_config_files[input$dropdown_asset_view]) - if (!file.exists(conf_file())){ - if (grepl("dev", dcc_config_file)) { - conf_file( - file.path("https://raw.githubusercontent.com/Sage-Bionetworks/data_curator_config/dev", - conf_file() - ) - ) - } else if (grepl("staging", dcc_config_file)) { - conf_file( - file.path("https://raw.githubusercontent.com/Sage-Bionetworks/data_curator_config/staging", - conf_file() - ) - ) - } else { - conf_file( - file.path("https://raw.githubusercontent.com/Sage-Bionetworks/data_curator_config/main", - conf_file() - ) - ) - } - } + config_df <- jsonlite::fromJSON(conf_file()) conf_template <- setNames(config_df[[1]]$schema_name, config_df[[1]]$display_name) From 9788024941ee401aadeacb3639357e87f4f71380 Mon Sep 17 00:00:00 2001 From: afwillia Date: Thu, 26 Oct 2023 12:15:22 -0700 Subject: [PATCH 04/41] update logo location for new config structure --- server.R | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/server.R b/server.R index 4015ffab..56b69911 100644 --- a/server.R +++ b/server.R @@ -192,8 +192,7 @@ shinyServer(function(input, output, session) { color = col2rgba(dcc_config_react()$primary_col, 255*0.9)) logo_img <- ifelse(!is.na(dcc_config_react()$logo_location), - paste0("https://raw.githubusercontent.com/Sage-Bionetworks/data_curator_config/main/", - dcc_config_react()$logo_location), + dcc_config_react()$logo_location, "https://raw.githubusercontent.com/Sage-Bionetworks/data_curator_config/main/demo/Logo_Sage_Logomark.png") logo_link <- ifelse(!is.na(dcc_config_react()$logo_link), From 0576e86007bb49ac31b828f55c49ac0a9195e509 Mon Sep 17 00:00:00 2001 From: afwillia Date: Thu, 26 Oct 2023 12:23:58 -0700 Subject: [PATCH 05/41] Fix color on initial waiter screen after selecting asset view. --- server.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server.R b/server.R index 56b69911..d5641065 100644 --- a/server.R +++ b/server.R @@ -156,7 +156,7 @@ shinyServer(function(input, output, session) { # within the selected asset view. observeEvent(input$btn_asset_view, { dcWaiter("show", msg = paste0("Getting data. This may take a minute."), - color=col2rgba(col2rgb("#CD0BBC01"))) + color="#2a668d") shinyjs::disable("btn_asset_view") selected$master_asset_view(input$dropdown_asset_view) From 4bc9b3b796293988eb8596df48cf5a6f0801f2f1 Mon Sep 17 00:00:00 2001 From: afwillia Date: Fri, 27 Oct 2023 09:10:25 -0700 Subject: [PATCH 06/41] Create a variable for the root directory of the config file --- global.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/global.R b/global.R index 62a303f7..7a91d30a 100644 --- a/global.R +++ b/global.R @@ -38,7 +38,7 @@ sapply(source_files, FUN = source) if (Sys.getenv("DCA_DCC_CONFIG") == "") stop("missing DCA_DCC_CONFIG environment variable") dca_dcc_config <- read_json(Sys.getenv("DCA_DCC_CONFIG"), simplifyVector = TRUE) tenants_config <- dca_dcc_config$tenants - +config_dir <- dirname(Sys.getenv("DCA_DCC_CONFIG")) ## Set Up OAuth client_id <- Sys.getenv("DCA_CLIENT_ID") From 9356ecb3f1413f765dca596956c0bd696efdc2e0 Mon Sep 17 00:00:00 2001 From: afwillia Date: Fri, 27 Oct 2023 09:11:04 -0700 Subject: [PATCH 07/41] Combine config root dir and config filepath to read files. --- server.R | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/server.R b/server.R index d5641065..83297e28 100644 --- a/server.R +++ b/server.R @@ -166,7 +166,9 @@ shinyServer(function(input, output, session) { tenant_config_react(tenants_config[tenants_config$synapse_asset_view == selected$master_asset_view(), ]) if (dca_schematic_api == "offline") tenant_config_react(tenants_config[tenants_config$name == "DCA Demo", ]) - dcc_config_react(read_json(tenant_config_react()$config_location)) + dcc_config_react(read_json( + file.path(config_dir, tenant_config_react()$config_location)) + ) model_ops <- reactive(setNames(dcc_config_react()$data_model_url, dcc_config_react()$synapse_asset_view)) @@ -192,7 +194,7 @@ shinyServer(function(input, output, session) { color = col2rgba(dcc_config_react()$primary_col, 255*0.9)) logo_img <- ifelse(!is.na(dcc_config_react()$logo_location), - dcc_config_react()$logo_location, + file.path(config_dir, dcc_config_react()$logo_location), "https://raw.githubusercontent.com/Sage-Bionetworks/data_curator_config/main/demo/Logo_Sage_Logomark.png") logo_link <- ifelse(!is.na(dcc_config_react()$logo_link), @@ -232,7 +234,9 @@ shinyServer(function(input, output, session) { } # Use the template dropdown config file from the appropriate branch of # data_curator_config - conf_file <- reactiveVal(template_config_files[input$dropdown_asset_view]) + conf_file <- reactiveVal( + file.path(config_dir, template_config_files[input$dropdown_asset_view]) + ) config_df <- jsonlite::fromJSON(conf_file()) From 02958635736b592da03d64a209fa70ff35382719 Mon Sep 17 00:00:00 2001 From: afwillia Date: Thu, 2 Nov 2023 13:35:05 -0700 Subject: [PATCH 08/41] Add functions to generate template config --- DESCRIPTION | 2 +- NAMESPACE | 6 +++++ R/template_config.R | 57 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 R/template_config.R diff --git a/DESCRIPTION b/DESCRIPTION index b1c50b7e..01dbb94b 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -6,6 +6,6 @@ Authors: Rongrong Chai, Xengie Doan, Milen Nikolov, Sujay Patil, Robert Allaway, License: file LICENSE Encoding: UTF-8 Roxygen: list(markdown = TRUE) -RoxygenNote: 7.2.1 +RoxygenNote: 7.2.3 Suggests: covr diff --git a/NAMESPACE b/NAMESPACE index 69ce606e..e2614d54 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,6 +1,11 @@ # Generated by roxygen2: do not edit by hand +export(create_json_template_config) +export(create_template_config) +export(format_edge_type) export(get_asset_view_table) +export(get_display_names) +export(graph_by_edge_type) export(manifest_download) export(manifest_generate) export(manifest_populate) @@ -14,3 +19,4 @@ export(synapse_access) export(synapse_get) export(synapse_is_certified) export(synapse_user_profile) +export(write_template_config) diff --git a/R/template_config.R b/R/template_config.R new file mode 100644 index 00000000..420b9c00 --- /dev/null +++ b/R/template_config.R @@ -0,0 +1,57 @@ +#' @export +graph_by_edge_type <- function(url = "https://schematic-dev.api.sagebionetworks.org/v1/schemas/get/graph_by_edge_type", + schema_url, relationship = "requiresDependency") { + req <- httr::GET(url = url, + query = list( + schema_url = schema_url, + relationship = relationship + )) + httr::content(req) +} + +#' @export +format_edge_type <- function(edge_types) { + et <- dplyr::bind_rows(lapply(edge_types, function(x) data.frame(value=x[[2]], schema_name=x[[1]]))) + et |> dplyr::filter(value %in% c("Component", "Filename")) |> + dplyr::group_by(schema_name) |> + dplyr::summarise(file_based = "Filename" %in% value) +} + +#' @export +get_display_names <- function(qlist) { + if (!"schema_url" %in% names(qlist)) stop("qlist needs element named `schema_url`") + if (!"node_list" %in% names(qlist)) stop("qlist needs at least one element named `node_list`") + httr::GET(url = "https://schematic-dev.api.sagebionetworks.org/v1/schemas/get_nodes_display_names", + query = qlist + ) +} + +#' @export +create_template_config <- function(data_model) { + edges <- graph_by_edge_type(schema_url = data_model) + schema_names <- format_edge_type(edges) + nl <- setNames(as.list(schema_names$schema_name), rep("node_list", length(schema_names$schema_name))) + dnames <- get_display_names(c(schema_url = data_model, nl)) |> httr::content() + data.frame(display_name = unlist(dnames), schema_name = unlist(nl)) |> + dplyr::left_join(schema_names, by = "schema_name") |> + dplyr::mutate(type = ifelse(file_based, "file", "record")) |> + dplyr::select(-file_based) +} + +#' @export +create_json_template_config <- function(data_model) { + df <- create_template_config(data_model) + schematic_version <- httr::GET("https://schematic-dev.api.sagebionetworks.org/v1/version") |> + httr::content() + list( + manifest_schemas = df, + service_version = schematic_version, + schema_version = "" + ) +} + +#' @export +write_template_config <- function(data_model, file) { + df <- create_json_template_config(data_model) + jsonlite::write_json(data_model, file) +} From 1787935846e0f9b637db1bfca72f58a69259fc0d Mon Sep 17 00:00:00 2001 From: afwillia Date: Thu, 2 Nov 2023 14:13:53 -0700 Subject: [PATCH 09/41] add httr to imports --- DESCRIPTION | 1 + NAMESPACE | 2 ++ 2 files changed, 3 insertions(+) diff --git a/DESCRIPTION b/DESCRIPTION index 01dbb94b..8187773d 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -7,5 +7,6 @@ License: file LICENSE Encoding: UTF-8 Roxygen: list(markdown = TRUE) RoxygenNote: 7.2.3 +Imports: httr Suggests: covr diff --git a/NAMESPACE b/NAMESPACE index e2614d54..ec428efc 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -20,3 +20,5 @@ export(synapse_get) export(synapse_is_certified) export(synapse_user_profile) export(write_template_config) +importFrom(httr,GET) +importFrom(httr,content) From 14188c88c9ebc51b932bbb1a057efcdac90b83ff Mon Sep 17 00:00:00 2001 From: afwillia Date: Thu, 2 Nov 2023 14:16:42 -0700 Subject: [PATCH 10/41] add dplyr and jsonlite to imports --- DESCRIPTION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DESCRIPTION b/DESCRIPTION index 8187773d..e4c778ef 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -7,6 +7,6 @@ License: file LICENSE Encoding: UTF-8 Roxygen: list(markdown = TRUE) RoxygenNote: 7.2.3 -Imports: httr +Imports: httr, dplyr, jsonlite Suggests: covr From afe02176d8bf9b0f9946a168d1767fe6d634b08d Mon Sep 17 00:00:00 2001 From: afwillia Date: Thu, 2 Nov 2023 14:26:19 -0700 Subject: [PATCH 11/41] use df not argument --- R/template_config.R | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/R/template_config.R b/R/template_config.R index 420b9c00..5aff82da 100644 --- a/R/template_config.R +++ b/R/template_config.R @@ -1,4 +1,5 @@ #' @export +#' @importFrom httr GET content graph_by_edge_type <- function(url = "https://schematic-dev.api.sagebionetworks.org/v1/schemas/get/graph_by_edge_type", schema_url, relationship = "requiresDependency") { req <- httr::GET(url = url, @@ -53,5 +54,5 @@ create_json_template_config <- function(data_model) { #' @export write_template_config <- function(data_model, file) { df <- create_json_template_config(data_model) - jsonlite::write_json(data_model, file) + jsonlite::write_json(df, file) } From db1827af0eb9cc5cf6ff02cd916353e23f76662b Mon Sep 17 00:00:00 2001 From: afwillia Date: Thu, 2 Nov 2023 14:29:22 -0700 Subject: [PATCH 12/41] add pretty and flatten argument to write json --- R/template_config.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/template_config.R b/R/template_config.R index 5aff82da..03ad2423 100644 --- a/R/template_config.R +++ b/R/template_config.R @@ -54,5 +54,5 @@ create_json_template_config <- function(data_model) { #' @export write_template_config <- function(data_model, file) { df <- create_json_template_config(data_model) - jsonlite::write_json(df, file) + jsonlite::write_json(df, file, pretty = TRUE, flatten = TRUE) } From 2c97e9ffd8615beccb82fdcfcd7107fc30a53661 Mon Sep 17 00:00:00 2001 From: afwillia Date: Thu, 2 Nov 2023 14:34:27 -0700 Subject: [PATCH 13/41] use autounbox to write config --- R/template_config.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/template_config.R b/R/template_config.R index 03ad2423..b0548147 100644 --- a/R/template_config.R +++ b/R/template_config.R @@ -54,5 +54,5 @@ create_json_template_config <- function(data_model) { #' @export write_template_config <- function(data_model, file) { df <- create_json_template_config(data_model) - jsonlite::write_json(df, file, pretty = TRUE, flatten = TRUE) + jsonlite::write_json(df, file, pretty = TRUE, auto_unbox = TRUE) } From c903aed863c2d0e3f2216a4dc50c5a5d2c63b18f Mon Sep 17 00:00:00 2001 From: afwillia Date: Tue, 7 Nov 2023 08:10:50 -0800 Subject: [PATCH 14/41] put graph_by_edge_type in schematic rest api file --- R/schematic_rest_api.R | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/R/schematic_rest_api.R b/R/schematic_rest_api.R index c2db54ad..6e293987 100644 --- a/R/schematic_rest_api.R +++ b/R/schematic_rest_api.R @@ -317,3 +317,17 @@ get_asset_view_table <- function(url="http://localhost:3001/v1/storage/assets/ta } +#' @param url URL of schematic API endpoint +#' @param schema_url URL of data model +#' @param relationship Argument to schematic graph_by_edge_type +#' @export +#' @importFrom httr GET content +graph_by_edge_type <- function(url = "https://schematic-dev.api.sagebionetworks.org/v1/schemas/get/graph_by_edge_type", + schema_url, relationship = "requiresDependency") { + req <- httr::GET(url = url, + query = list( + schema_url = schema_url, + relationship = relationship + )) + httr::content(req) +} From 11c164d034377ce4f40dc4878430ce14c1ef6605 Mon Sep 17 00:00:00 2001 From: afwillia Date: Tue, 7 Nov 2023 08:11:19 -0800 Subject: [PATCH 15/41] Clarify function names --- R/template_config.R | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/R/template_config.R b/R/template_config.R index b0548147..060da0e3 100644 --- a/R/template_config.R +++ b/R/template_config.R @@ -1,15 +1,3 @@ -#' @export -#' @importFrom httr GET content -graph_by_edge_type <- function(url = "https://schematic-dev.api.sagebionetworks.org/v1/schemas/get/graph_by_edge_type", - schema_url, relationship = "requiresDependency") { - req <- httr::GET(url = url, - query = list( - schema_url = schema_url, - relationship = relationship - )) - httr::content(req) -} - #' @export format_edge_type <- function(edge_types) { et <- dplyr::bind_rows(lapply(edge_types, function(x) data.frame(value=x[[2]], schema_name=x[[1]]))) @@ -40,7 +28,7 @@ create_template_config <- function(data_model) { } #' @export -create_json_template_config <- function(data_model) { +create_dca_template_config <- function(data_model) { df <- create_template_config(data_model) schematic_version <- httr::GET("https://schematic-dev.api.sagebionetworks.org/v1/version") |> httr::content() @@ -51,8 +39,8 @@ create_json_template_config <- function(data_model) { ) } -#' @export -write_template_config <- function(data_model, file) { +# Create a DCA-specific template generation function +write_dca_template_config <- function(data_model, file) { df <- create_json_template_config(data_model) jsonlite::write_json(df, file, pretty = TRUE, auto_unbox = TRUE) } From 9da3090219a9921e1684e591286da97296cd1637 Mon Sep 17 00:00:00 2001 From: afwillia Date: Tue, 7 Nov 2023 08:13:06 -0800 Subject: [PATCH 16/41] export write_dca_template_config --- R/template_config.R | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/R/template_config.R b/R/template_config.R index 060da0e3..52370104 100644 --- a/R/template_config.R +++ b/R/template_config.R @@ -39,7 +39,8 @@ create_dca_template_config <- function(data_model) { ) } -# Create a DCA-specific template generation function +#' @export +#' @description Create a DCA-specific template generation function write_dca_template_config <- function(data_model, file) { df <- create_json_template_config(data_model) jsonlite::write_json(df, file, pretty = TRUE, auto_unbox = TRUE) From 0c76c2ae43e7b426b07d0f774aa6cfac168ffe58 Mon Sep 17 00:00:00 2001 From: afwillia Date: Tue, 7 Nov 2023 08:19:26 -0800 Subject: [PATCH 17/41] export write_dca_template_config --- NAMESPACE | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/NAMESPACE b/NAMESPACE index ec428efc..61256a54 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,6 +1,6 @@ # Generated by roxygen2: do not edit by hand -export(create_json_template_config) +export(create_dca_template_config) export(create_template_config) export(format_edge_type) export(get_asset_view_table) @@ -19,6 +19,5 @@ export(synapse_access) export(synapse_get) export(synapse_is_certified) export(synapse_user_profile) -export(write_template_config) importFrom(httr,GET) importFrom(httr,content) From 59c714bd9bf2d883fda6a6dacca54a1c247dbabc Mon Sep 17 00:00:00 2001 From: afwillia Date: Tue, 7 Nov 2023 08:24:04 -0800 Subject: [PATCH 18/41] export write_dca_template_config for real --- NAMESPACE | 1 + 1 file changed, 1 insertion(+) diff --git a/NAMESPACE b/NAMESPACE index 61256a54..f36e80b2 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -19,5 +19,6 @@ export(synapse_access) export(synapse_get) export(synapse_is_certified) export(synapse_user_profile) +export(write_dca_template_config) importFrom(httr,GET) importFrom(httr,content) From b285343ea756a1621e1b964a280189c845f966d4 Mon Sep 17 00:00:00 2001 From: afwillia Date: Tue, 7 Nov 2023 08:26:34 -0800 Subject: [PATCH 19/41] fix function name in write_dca_template_config --- R/template_config.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/template_config.R b/R/template_config.R index 52370104..51272b45 100644 --- a/R/template_config.R +++ b/R/template_config.R @@ -42,6 +42,6 @@ create_dca_template_config <- function(data_model) { #' @export #' @description Create a DCA-specific template generation function write_dca_template_config <- function(data_model, file) { - df <- create_json_template_config(data_model) + df <- create_dca_json_template_config(data_model) jsonlite::write_json(df, file, pretty = TRUE, auto_unbox = TRUE) } From 05dc6577a2f5bfb1b2e3e954c55118d7355a1ec9 Mon Sep 17 00:00:00 2001 From: afwillia Date: Tue, 7 Nov 2023 08:30:09 -0800 Subject: [PATCH 20/41] fix function name in write_dca_template_config again --- R/template_config.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/template_config.R b/R/template_config.R index 51272b45..d341a767 100644 --- a/R/template_config.R +++ b/R/template_config.R @@ -42,6 +42,6 @@ create_dca_template_config <- function(data_model) { #' @export #' @description Create a DCA-specific template generation function write_dca_template_config <- function(data_model, file) { - df <- create_dca_json_template_config(data_model) + df <- create_dca_template_config(data_model) jsonlite::write_json(df, file, pretty = TRUE, auto_unbox = TRUE) } From d583b95afdf4d2d5f3fc2ee9a88b41ac027a1331 Mon Sep 17 00:00:00 2001 From: afwillia Date: Tue, 7 Nov 2023 10:14:54 -0800 Subject: [PATCH 21/41] remove dca and schematic version from footer --- ui.R | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/ui.R b/ui.R index 60070479..532bb9f7 100644 --- a/ui.R +++ b/ui.R @@ -124,7 +124,7 @@ ui <- shinydashboardPlus::dashboardPage( ), uiOutput("sass"), # load dependencies - use_notiflix_report(width = "400px"), + use_notiflix_report(width = "500px", messageMaxLength = 10000), use_waiter(), tabItems( # second tab content @@ -298,9 +298,6 @@ ui <- shinydashboardPlus::dashboardPage( ), # waiter loading screen dcWaiter("show", landing = TRUE) - ), - footer = dashboardFooter( - left = sprintf("DCA %s - Schematic %s", dca_version, schematic_version) ) ) From 403e10c5ddcc9885571123b185e22bcf88854381 Mon Sep 17 00:00:00 2001 From: afwillia Date: Tue, 7 Nov 2023 10:15:24 -0800 Subject: [PATCH 22/41] display dcc and portal help links if set --- server.R | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/server.R b/server.R index abc7a345..8cab7d20 100644 --- a/server.R +++ b/server.R @@ -309,13 +309,21 @@ shinyServer(function(input, output, session) { }) observeEvent(input$info_box, { + + data_model_link <- ifelse(dcc_config_react()$data_model_info == "", + dcc_config_react()$data_model_url, + dcc_config_react()$data_model_info) + dca_help_link <- ifelse(is.null(dcc_config_react()$dca_help_link), "", dcc_config_react()$dca_help_link) + portal_help_link <- ifelse(is.null(dcc_config_react()$portal_help_link), "", dcc_config_react()$portal_help_link) + nx_report_info( - title = "App Info", + title = "About Data Curator", tags$ul( - tags$li("DCA Help Docs: ", "todo"), - tags$li("Portal Help Docs: ", "todo"), - tags$li("Data model: ", data_model()), - tags$li("Asset view: ", selected$master_asset_view()), + #tags$li(tags$a(href = "https://sagebionetworks.jira.com/wiki/spaces/SCHEM/pages/2732818485/Data+Curator+App+Setup+for+DCCs+and+Science+Teams+at+Sage", "DCA Help Docs", target = "_blank")), + if (dca_help_link != "") tags$li(tags$a(href = dca_help_link, "DCA Help Docs", target = "_blank")), + if (portal_help_link != "") tags$li(tags$a(href = portal_help_link, "Portal Help Docs", target = "_blank")), + if (data_model_link != "") tags$li(tags$a(href = data_model_link, "Data Model Info", target = "_blank")), + tags$li(tags$a(href = paste0("https://www.synapse.org/#!Synapse:", selected$master_asset_view()), paste("Asset View:", selected$master_asset_view()), target = "_blank")), tags$li("DCA version: ", dca_version), tags$li("Schematic version: ", schematic_version), ) From 6549cda9be47b080ef262bb863d382c565b136a5 Mon Sep 17 00:00:00 2001 From: afwillia Date: Tue, 7 Nov 2023 15:28:54 -0800 Subject: [PATCH 23/41] Use nested structure for dca_config and only reference primary_col in once place --- server.R | 84 +++++++++++++++++++++++++++++--------------------------- 1 file changed, 43 insertions(+), 41 deletions(-) diff --git a/server.R b/server.R index 8cab7d20..0d4bdfe8 100644 --- a/server.R +++ b/server.R @@ -170,35 +170,37 @@ shinyServer(function(input, output, session) { file.path(config_dir, tenant_config_react()$config_location)) ) - model_ops <- reactive(setNames(dcc_config_react()$data_model_url, - dcc_config_react()$synapse_asset_view)) + model_ops <- reactive(setNames(dcc_config_react()$dcc$data_model_url, + dcc_config_react()$dcc$synapse_asset_view)) data_model(model_ops()) - template_config_files <- setNames(dcc_config_react()$template_menu_config_file, - dcc_config_react()$synapse_asset_view) + template_config_files <- setNames(dcc_config_react()$dcc$template_menu_config_file, + dcc_config_react()$dcc$synapse_asset_view) output$sass <- renderUI({ tags$head(tags$style(css())) }) + + primary_col <- reactive(col2rgba(dcc_config_react()$dca$primary_col, 255*0.9)) css <- reactive({ # Don't change theme for default projects - sass(input = list(primary_col=dcc_config_react()$primary_col, - htan_col=dcc_config_react()$secondary_col, - sidebar_col=dcc_config_react()$sidebar_col, + sass(input = list(primary_col=dcc_config_react()$dca$primary_col, + htan_col=dcc_config_react()$dca$secondary_col, + sidebar_col=dcc_config_react()$dca$sidebar_col, sass_file("www/scss/main.scss"))) }) dcWaiter("hide") dcWaiter("show", msg = paste0("Getting data. This may take a minute."), - color = col2rgba(dcc_config_react()$primary_col, 255*0.9)) + color = primary_col()) - logo_img <- ifelse(!is.na(dcc_config_react()$logo_location), - file.path(config_dir, dcc_config_react()$logo_location), + logo_img <- ifelse(!is.na(dcc_config_react()$dcc$logo_location), + file.path(config_dir, dcc_config_react()$dcc$logo_location), "https://raw.githubusercontent.com/Sage-Bionetworks/data_curator_config/main/demo/Logo_Sage_Logomark.png") - logo_link <- ifelse(!is.na(dcc_config_react()$logo_link), - dcc_config_react()$logo_link, + logo_link <- ifelse(!is.na(dcc_config_react()$dcc$logo_link), + dcc_config_react()$dcc$logo_link, "https://synapse.org" ) @@ -310,11 +312,11 @@ shinyServer(function(input, output, session) { observeEvent(input$info_box, { - data_model_link <- ifelse(dcc_config_react()$data_model_info == "", - dcc_config_react()$data_model_url, - dcc_config_react()$data_model_info) - dca_help_link <- ifelse(is.null(dcc_config_react()$dca_help_link), "", dcc_config_react()$dca_help_link) - portal_help_link <- ifelse(is.null(dcc_config_react()$portal_help_link), "", dcc_config_react()$portal_help_link) + data_model_link <- ifelse(dcc_config_react()$dcc$data_model_info == "", + dcc_config_react()$dcc$data_model_url, + dcc_config_react()$dcc$data_model_info) + dca_help_link <- ifelse(is.null(dcc_config_react()$dcc$dca_help_link), "", dcc_config_react()$dcc$dca_help_link) + portal_help_link <- ifelse(is.null(dcc_config_react()$dcc$portal_help_link), "", dcc_config_react()$dcc$portal_help_link) nx_report_info( title = "About Data Curator", @@ -335,7 +337,7 @@ shinyServer(function(input, output, session) { observeEvent(input$btn_project, { ######## Update Folder List ######## dcWaiter("show", msg = paste0("Getting data"), - color = col2rgba(dcc_config_react()$primary_col, 255*0.9)) + color = primary_col()) shinyjs::disable("btn_project") selected$project(data_list$projects()[names(data_list$projects()) == input$dropdown_project]) @@ -407,7 +409,7 @@ shinyServer(function(input, output, session) { # Goal of this button is to updpate the template reactive object # with the template the user chooses observeEvent(input$btn_template_select, { - dcWaiter("show", msg = "Please wait", color = col2rgba(dcc_config_react()$primary_col, 255*0.9), sleep=0) + dcWaiter("show", msg = "Please wait", color = primary_col(), sleep=0) shinyjs::disable("btn_template_select") selected$schema(data_list$template()[input$dropdown_template]) shinyjs::show(select = "li:nth-child(5)") @@ -427,7 +429,7 @@ shinyServer(function(input, output, session) { # Goal of this button is to get the files within a folder the user selects observeEvent(input$btn_folder, { - dcWaiter("show", msg = paste0("Getting data"), color = col2rgba(dcc_config_react()$primary_col, 255*0.9)) + dcWaiter("show", msg = paste0("Getting data"), color = primary_col()) shinyjs::disable("btn_folder") shinyjs::show(select = "li:nth-child(4)") @@ -586,7 +588,7 @@ shinyServer(function(input, output, session) { observeEvent(c(input$`switchTab4-Next`, input$tabs), { req(input$tabs == "tab_template") - dcWaiter("show", msg = "Getting template. This may take a minute.", color = dcc_config_react()$primary_col) + dcWaiter("show", msg = "Getting template. This may take a minute.", color = dcc_config_react()$dca$primary_col) ### This doesn't work - try moving manifest_generate outside of downloadButton .schema <- selected$schema() @@ -594,15 +596,15 @@ shinyServer(function(input, output, session) { .schema_url <- data_model() .asset_view <- selected$master_asset_view() .template <- paste( - dcc_config_react()$project_name, + dcc_config_react()$dcc$project_name, "-", input$dropdown_template ) .url <- ifelse(dca_schematic_api != "offline", file.path(api_uri, "v1/manifest/generate"), NA) - .output_format <- dcc_config_react()$manifest_output_format - .use_annotations <- dcc_config_react()$manifest_use_annotations + .output_format <- dcc_config_react()$schematic$manifest_generate$output_format + .use_annotations <- dcc_config_react()$schematic$manifest_generate$use_annotations promises::future_promise({ try({ @@ -642,7 +644,7 @@ shinyServer(function(input, output, session) { shinyjs::enable("btn_template_select") updateTabsetPanel(session, "tab_template_select") } else { - if (dcc_config_react()$manifest_output_format == "google_sheet") { + if (dcc_config_react()$schematic$manifest_generate$output_format == "google_sheet") { shinyjs::show("div_template") } else shinyjs::show("div_download_data") } @@ -660,7 +662,7 @@ shinyServer(function(input, output, session) { filename = function() sprintf("%s.xlsx", input$dropdown_template), #filename = function() sprintf("%s.csv", input$dropdown_template), content = function(file) { - dcWaiter("show", msg = "Downloading data", color = dcc_config_react()$primary_col) + dcWaiter("show", msg = "Downloading data", color = dcc_config_react()$dca$primary_col) dcWaiter("hide", sleep = 0) writeBin(manifest_data(), file) } @@ -705,7 +707,7 @@ shinyServer(function(input, output, session) { ######## Validation Section ####### observeEvent(input$btn_validate, { - dcWaiter("show", msg = "Validating manifest. This may take a minute.", color = col2rgba(dcc_config_react()$primary_col, 255*0.9)) + dcWaiter("show", msg = "Validating manifest. This may take a minute.", color = primary_col()) # Reset validation_result in case user reuploads the same file. This makes # the validation_res observer trigger any time this button is pressed. @@ -718,7 +720,7 @@ shinyServer(function(input, output, session) { .data_model <- data_model() .infile_data <- inFile$data() .dd_template <- input$dropdown_template - .restrict_rules <- dcc_config_react()$validate_restrict_rules + .restrict_rules <- dcc_config_react()$schematic$model_validate$restrict_rules promises::future_promise({ annotation_status <- switch(dca_schematic_api, @@ -774,7 +776,7 @@ shinyServer(function(input, output, session) { dcWaiter("update", msg = paste0(validation_res()$error_type, " Found !!! "), spin = spin_inner_circles(), sleep = 2.5) shinyjs::show("box_submit") } else { - if (dca_schematic_api != "offline" & dcc_config_react()$manifest_output_format == "google_sheet") { + if (dca_schematic_api != "offline" & dcc_config_react()$schematic$manifest_generate$output_format == "google_sheet") { #output$val_gsheet <- renderUI( #actionButton("btn_val_gsheet", " Generate Google Sheet Link", icon = icon("table"), class = "btn-primary-color") #) @@ -796,7 +798,7 @@ shinyServer(function(input, output, session) { # if user click gsheet_btn, generating gsheet observeEvent(input$btn_val_gsheet, { # loading screen for Google link generation - dcWaiter("show", msg = "Generating link...", color = col2rgba(dcc_config_react()$primary_col, 255*0.9)) + dcWaiter("show", msg = "Generating link...", color = primary_col()) filled_manifest <- switch(dca_schematic_api, reticulate = manifest_populate_py(paste0(config$community, " ", input$dropdown_template), inFile$raw()$datapath, @@ -832,7 +834,7 @@ shinyServer(function(input, output, session) { ######## Submission Section ######## observeEvent(input$btn_submit, { # loading screen for submitting data - dcWaiter("show", msg = "Submitting data. This may take a minute.", color = col2rgba(dcc_config_react()$primary_col, 255*0.9)) + dcWaiter("show", msg = "Submitting data. This may take a minute.", color = primary_col()) if (is.null(selected$folder())) { @@ -896,11 +898,11 @@ shinyServer(function(input, output, session) { .data_model <- data_model() .schema <- selected$schema() .asset_view <- selected$master_asset_view() - .submit_use_schema_labels <- dcc_config_react()$submit_use_schema_labels - .table_manipulation <- dcc_config_react()$submit_table_manipulation - .submit_manifest_record_type <- dcc_config_react()$submit_manifest_record_type - .restrict_rules <- dcc_config_react()$validate_restrict_rules - .hide_blanks <- dcc_config_react()$submit_hide_blanks + .submit_use_schema_labels <- dcc_config_react()$schematic$model_submit$use_schema_labels + .table_manipulation <- dcc_config_react()$schematic$model_submit$table_manipulation + .submit_manifest_record_type <- dcc_config_react()$schematic$model_submit$manifest_record_type + .restrict_rules <- dcc_config_react()$schematic$model_validate$restrict_rules + .hide_blanks <- dcc_config_react()$schematic$model_submit$hide_blanks # associates metadata with data and returns manifest id promises::future_promise({ @@ -941,11 +943,11 @@ shinyServer(function(input, output, session) { .data_model <- data_model() .schema <- selected$schema() .asset_view <- selected$master_asset_view() - .submit_use_schema_labels <- dcc_config_react()$submit_use_schema_labels - .table_manipulation <- dcc_config_react()$submit_table_manipulation - .submit_manifest_record_type <- dcc_config_react()$submit_manifest_record_type - .restrict_rules <- dcc_config_react()$validate_restrict_rules - .hide_blanks <- dcc_config_react()$submit_hide_blanks + .submit_use_schema_labels <- dcc_config_react()$schematic$model_submit$use_schema_labels + .table_manipulation <- dcc_config_react()$schematic$model_submit$table_manipulation + .submit_manifest_record_type <- dcc_config_react()$schematic$model_submit$manifest_record_type + .restrict_rules <- dcc_config_react()$schematic$model_validate$restrict_rules + .hide_blanks <- dcc_config_react()$schematic$model_submit$hide_blanks # associates metadata with data and returns manifest id promises::future_promise({ try({ From fe1e76ad5909eae54b74e9561f173875e337f729 Mon Sep 17 00:00:00 2001 From: afwillia Date: Wed, 8 Nov 2023 16:05:45 -0800 Subject: [PATCH 24/41] When determining which components are file- or record-based, filter to all components first, then use this to filter against attributes that depend on component and filename --- R/template_config.R | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/R/template_config.R b/R/template_config.R index d341a767..6d2b47b6 100644 --- a/R/template_config.R +++ b/R/template_config.R @@ -1,9 +1,13 @@ #' @export format_edge_type <- function(edge_types) { et <- dplyr::bind_rows(lapply(edge_types, function(x) data.frame(value=x[[2]], schema_name=x[[1]]))) + components <- et |> + dplyr::filter(, tolower(value) == "component") |> + dplyr::pull(schema_name) et |> dplyr::filter(value %in% c("Component", "Filename")) |> dplyr::group_by(schema_name) |> - dplyr::summarise(file_based = "Filename" %in% value) + dplyr::summarise(file_based = "Filename" %in% value) %>% + dplyr::filter(schema_name %in% components) } #' @export From 0a7cc6c98c5191cbfbd73afadc895f9f2f324635 Mon Sep 17 00:00:00 2001 From: afwillia Date: Wed, 8 Nov 2023 17:02:02 -0800 Subject: [PATCH 25/41] Add options to include or exclude schemas from template config --- R/template_config.R | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/R/template_config.R b/R/template_config.R index 6d2b47b6..59da14c7 100644 --- a/R/template_config.R +++ b/R/template_config.R @@ -20,20 +20,24 @@ get_display_names <- function(qlist) { } #' @export -create_template_config <- function(data_model) { +create_template_config <- function(data_model, include_schemas=NULL, exclude_schemas=NULL) { + if (!is.null(include_schemas) & !is.null(exclude_schemas)) stop("include_schemas and exclude_schemas cannot both have values") edges <- graph_by_edge_type(schema_url = data_model) schema_names <- format_edge_type(edges) nl <- setNames(as.list(schema_names$schema_name), rep("node_list", length(schema_names$schema_name))) dnames <- get_display_names(c(schema_url = data_model, nl)) |> httr::content() - data.frame(display_name = unlist(dnames), schema_name = unlist(nl)) |> + config <- data.frame(display_name = unlist(dnames), schema_name = unlist(nl)) |> dplyr::left_join(schema_names, by = "schema_name") |> dplyr::mutate(type = ifelse(file_based, "file", "record")) |> dplyr::select(-file_based) + if (!is.null(include_schemas)) config <- dplyr::filter(config, schema_name %in% include_schemas) + if (!is.null(exclude_schemas)) config <- dplyr::filter(config, !schema_name %in% exclude_schemas) + config } #' @export -create_dca_template_config <- function(data_model) { - df <- create_template_config(data_model) +create_dca_template_config <- function(data_model, include_schemas=NULL, exclude_schemas=NULL) { + df <- create_template_config(data_model, include_schemas, exclude_schemas) schematic_version <- httr::GET("https://schematic-dev.api.sagebionetworks.org/v1/version") |> httr::content() list( @@ -45,7 +49,7 @@ create_dca_template_config <- function(data_model) { #' @export #' @description Create a DCA-specific template generation function -write_dca_template_config <- function(data_model, file) { - df <- create_dca_template_config(data_model) +write_dca_template_config <- function(data_model, file, include_schemas, exclude_schemas) { + df <- create_dca_template_config(data_model, include_schemas, exclude_schemas) jsonlite::write_json(df, file, pretty = TRUE, auto_unbox = TRUE) } From 491f6d951225e7dd9f36ee88ddc673d3edd8c8d5 Mon Sep 17 00:00:00 2001 From: afwillia Date: Thu, 9 Nov 2023 13:44:00 -0800 Subject: [PATCH 26/41] default include_schemas and exclude_schemas to NULL. Check if values are in the data model --- R/template_config.R | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/R/template_config.R b/R/template_config.R index 59da14c7..f322b940 100644 --- a/R/template_config.R +++ b/R/template_config.R @@ -21,7 +21,7 @@ get_display_names <- function(qlist) { #' @export create_template_config <- function(data_model, include_schemas=NULL, exclude_schemas=NULL) { - if (!is.null(include_schemas) & !is.null(exclude_schemas)) stop("include_schemas and exclude_schemas cannot both have values") + if (!is.null(include_schemas) && !is.null(exclude_schemas)) stop("include_schemas and exclude_schemas cannot both have values") edges <- graph_by_edge_type(schema_url = data_model) schema_names <- format_edge_type(edges) nl <- setNames(as.list(schema_names$schema_name), rep("node_list", length(schema_names$schema_name))) @@ -30,8 +30,14 @@ create_template_config <- function(data_model, include_schemas=NULL, exclude_sch dplyr::left_join(schema_names, by = "schema_name") |> dplyr::mutate(type = ifelse(file_based, "file", "record")) |> dplyr::select(-file_based) - if (!is.null(include_schemas)) config <- dplyr::filter(config, schema_name %in% include_schemas) - if (!is.null(exclude_schemas)) config <- dplyr::filter(config, !schema_name %in% exclude_schemas) + if (!is.null(include_schemas)) { + if (any(length(x <- setdiff(include_schemas, config$schema_name)))) stop(sprintf("%s is not a schema name in the data model", x)) + config <- dplyr::filter(config, schema_name %in% include_schemas) + } + if (!is.null(exclude_schemas)) { + if (any(length(y <- setdiff(exclude_schemas, config$schema_name)))) stop(sprintf("%s is not a schema name in the data model", y)) + config <- dplyr::filter(config, !schema_name %in% exclude_schemas) + } config } From c0e749e6474fa9968d3973077ce4c4591a2d871f Mon Sep 17 00:00:00 2001 From: afwillia Date: Thu, 9 Nov 2023 14:09:32 -0800 Subject: [PATCH 27/41] set include_schemas and exclude_schemas to NULL --- R/template_config.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/template_config.R b/R/template_config.R index f322b940..1cbb891d 100644 --- a/R/template_config.R +++ b/R/template_config.R @@ -55,7 +55,7 @@ create_dca_template_config <- function(data_model, include_schemas=NULL, exclude #' @export #' @description Create a DCA-specific template generation function -write_dca_template_config <- function(data_model, file, include_schemas, exclude_schemas) { +write_dca_template_config <- function(data_model, file, include_schemas=NULL, exclude_schemas=NULL) { df <- create_dca_template_config(data_model, include_schemas, exclude_schemas) jsonlite::write_json(df, file, pretty = TRUE, auto_unbox = TRUE) } From e4bbc21364c7ad4043bf973188ea7b698546ddd0 Mon Sep 17 00:00:00 2001 From: afwillia Date: Thu, 9 Nov 2023 14:13:07 -0800 Subject: [PATCH 28/41] use base pipe operator --- R/template_config.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/template_config.R b/R/template_config.R index 1cbb891d..2844d9a3 100644 --- a/R/template_config.R +++ b/R/template_config.R @@ -6,7 +6,7 @@ format_edge_type <- function(edge_types) { dplyr::pull(schema_name) et |> dplyr::filter(value %in% c("Component", "Filename")) |> dplyr::group_by(schema_name) |> - dplyr::summarise(file_based = "Filename" %in% value) %>% + dplyr::summarise(file_based = "Filename" %in% value) |> dplyr::filter(schema_name %in% components) } From ebe4ed39e72b9c151d319e8f92cd20aad49fe017 Mon Sep 17 00:00:00 2001 From: afwillia Date: Thu, 9 Nov 2023 14:26:07 -0800 Subject: [PATCH 29/41] remove empty argument from filter --- R/template_config.R | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/R/template_config.R b/R/template_config.R index 2844d9a3..f421bd8c 100644 --- a/R/template_config.R +++ b/R/template_config.R @@ -1,11 +1,12 @@ #' @export format_edge_type <- function(edge_types) { - et <- dplyr::bind_rows(lapply(edge_types, function(x) data.frame(value=x[[2]], schema_name=x[[1]]))) + et <- dplyr::bind_rows(lapply(edge_types, function(x) data.frame(value = x[[2]], schema_name = x[[1]]))) components <- et |> - dplyr::filter(, tolower(value) == "component") |> + dplyr::filter(tolower(value) == "component") |> dplyr::pull(schema_name) - et |> dplyr::filter(value %in% c("Component", "Filename")) |> - dplyr::group_by(schema_name) |> + et |> + dplyr::filter(value %in% c("Component", "Filename")) |> + dplyr::group_by(schema_name) |> dplyr::summarise(file_based = "Filename" %in% value) |> dplyr::filter(schema_name %in% components) } @@ -14,13 +15,14 @@ format_edge_type <- function(edge_types) { get_display_names <- function(qlist) { if (!"schema_url" %in% names(qlist)) stop("qlist needs element named `schema_url`") if (!"node_list" %in% names(qlist)) stop("qlist needs at least one element named `node_list`") - httr::GET(url = "https://schematic-dev.api.sagebionetworks.org/v1/schemas/get_nodes_display_names", - query = qlist + httr::GET( + url = "https://schematic-dev.api.sagebionetworks.org/v1/schemas/get_nodes_display_names", + query = qlist ) } #' @export -create_template_config <- function(data_model, include_schemas=NULL, exclude_schemas=NULL) { +create_template_config <- function(data_model, include_schemas = NULL, exclude_schemas = NULL) { if (!is.null(include_schemas) && !is.null(exclude_schemas)) stop("include_schemas and exclude_schemas cannot both have values") edges <- graph_by_edge_type(schema_url = data_model) schema_names <- format_edge_type(edges) @@ -42,7 +44,7 @@ create_template_config <- function(data_model, include_schemas=NULL, exclude_sch } #' @export -create_dca_template_config <- function(data_model, include_schemas=NULL, exclude_schemas=NULL) { +create_dca_template_config <- function(data_model, include_schemas = NULL, exclude_schemas = NULL) { df <- create_template_config(data_model, include_schemas, exclude_schemas) schematic_version <- httr::GET("https://schematic-dev.api.sagebionetworks.org/v1/version") |> httr::content() @@ -55,7 +57,7 @@ create_dca_template_config <- function(data_model, include_schemas=NULL, exclude #' @export #' @description Create a DCA-specific template generation function -write_dca_template_config <- function(data_model, file, include_schemas=NULL, exclude_schemas=NULL) { +write_dca_template_config <- function(data_model, file, include_schemas = NULL, exclude_schemas = NULL) { df <- create_dca_template_config(data_model, include_schemas, exclude_schemas) jsonlite::write_json(df, file, pretty = TRUE, auto_unbox = TRUE) } From 18db322be9cf7e8f1ab0f207cacc0c18e6244990 Mon Sep 17 00:00:00 2001 From: afwillia Date: Fri, 10 Nov 2023 10:19:18 -0800 Subject: [PATCH 30/41] Update info panel for json config --- server.R | 54 ++++++++++++++++++++---------------------------------- 1 file changed, 20 insertions(+), 34 deletions(-) diff --git a/server.R b/server.R index d594bb74..1be601b8 100644 --- a/server.R +++ b/server.R @@ -34,12 +34,6 @@ shinyServer(function(input, output, session) { ######## session global variables ######## # read config in - if (grepl("dev", dcc_config_file)) { - def_config <- fromJSON("https://raw.githubusercontent.com/Sage-Bionetworks/data_curator_config/dev-old/demo/dca-template-config.json") - } else if (grepl("staging", dcc_config_file)) { - def_config <- fromJSON("https://raw.githubusercontent.com/Sage-Bionetworks/data_curator_config/staging/demo/dca-template-config.json") - } else def_config <- fromJSON("https://raw.githubusercontent.com/Sage-Bionetworks/data_curator_config/main/demo/dca-template-config.json") - config <- reactiveVal() config_schema <- reactiveVal() @@ -57,6 +51,8 @@ shinyServer(function(input, output, session) { validation_res <- reactiveVal() manifest_id <- reactiveVal() + primary_col <- reactiveVal() + data_list <- list( projects = reactiveVal(NA), folders = reactiveVal(NULL), template = reactiveVal(NULL), @@ -188,7 +184,7 @@ shinyServer(function(input, output, session) { tags$head(tags$style(css())) }) - primary_col <- reactive(col2rgba(dcc_config_react()$dca$primary_col, 255*0.9)) + primary_col(col2rgba(dcc_config_react()$dca$primary_col, 255*0.9)) css <- reactive({ # Don't change theme for default projects sass(input = list(primary_col=dcc_config_react()$dca$primary_col, @@ -242,28 +238,7 @@ shinyServer(function(input, output, session) { } # Use the template dropdown config file from the appropriate branch of # data_curator_config - conf_file <- reactiveVal(template_config_files[input$dropdown_asset_view]) - if (!file.exists(conf_file())){ - if (grepl("dev", dcc_config_file)) { - conf_file( - file.path("https://raw.githubusercontent.com/Sage-Bionetworks/data_curator_config/dev-old", - conf_file() - ) - ) - } else if (grepl("staging", dcc_config_file)) { - conf_file( - file.path("https://raw.githubusercontent.com/Sage-Bionetworks/data_curator_config/staging", - conf_file() - ) - ) - } else { - conf_file( - file.path("https://raw.githubusercontent.com/Sage-Bionetworks/data_curator_config/main", - conf_file() - ) - ) - } - } + conf_file <- reactiveVal(file.path(config_dir, template_config_files[input$dropdown_asset_view])) config_df <- jsonlite::fromJSON(conf_file()) conf_template <- setNames(config_df[[1]]$schema_name, config_df[[1]]$display_name) @@ -335,13 +310,24 @@ shinyServer(function(input, output, session) { }) observeEvent(input$info_box, { - + has_dcc <- ifelse(is.na(dcc_config_react()$dcc$dcc_help_link) | + dcc_config_react()$dcc$dcc_help_link == "" | + is.null(dcc_config_react()$dcc$dcc_help_link), + FALSE, TRUE) + has_portal <- ifelse(is.na(dcc_config_react()$dcc$portal_help_link) | + dcc_config_react()$dcc$portal_help_link == "" | + is.null(dcc_config_react()$dcc$portal_help_link), + FALSE, TRUE) + has_dm <- ifelse(is.na(dcc_config_react()$dcc$data_model_info) | + dcc_config_react()$dcc$data_model_info == "" | + is.null(dcc_config_react()$dcc$data_model_info), + FALSE, TRUE) nx_report_info( - title = sprintf("DCA for %s", dcc_config_react()$project_name), + title = sprintf("DCA for %s", dcc_config_react()$dcc$project_name), tags$ul( - if (!is.na(dcc_config_react()$dca_help_link)) tags$li(tags$a(href = dcc_config_react()$dca_help_link, "DCA Help Docs", target = "_blank")), - if (!is.na(dcc_config_react()$portal_help_link)) tags$li(tags$a(href = dcc_config_react()$portal_help_link, "Portal Help Docs", target = "_blank")), - if (!is.na(dcc_config_react()$data_model_info)) tags$li(tags$a(href = dcc_config_react()$data_model_info, "Data Model Info", target = "_blank")), + if (has_dcc) tags$li(tags$a(href = dcc_config_react()$dcc$dcc_help_link, "DCA Help Docs", target = "_blank")), + if (has_portal) tags$li(tags$a(href = dcc_config_react()$dcc$portal_help_link, "Portal Help Docs", target = "_blank")), + if (has_dm) tags$li(tags$a(href = dcc_config_react()$dcc$data_model_info, "Data Model Info", target = "_blank")), tags$li(tags$a(href = paste0("https://www.synapse.org/#!Synapse:", selected$master_asset_view()), paste("Asset View:", selected$master_asset_view()), target = "_blank")), tags$li("DCA version: ", dca_version), tags$li("Schematic version: ", schematic_version), From 2cd381a618e79e8ac155dc97d2bcced0de020f5b Mon Sep 17 00:00:00 2001 From: afwillia Date: Wed, 15 Nov 2023 08:47:15 -0800 Subject: [PATCH 31/41] WIP: add project_scope to validation endpoint --- R/schematic_rest_api.R | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/R/schematic_rest_api.R b/R/schematic_rest_api.R index b2e39e0e..31d032e2 100644 --- a/R/schematic_rest_api.R +++ b/R/schematic_rest_api.R @@ -115,12 +115,13 @@ manifest_populate <- function(url="http://localhost:3001/v1/manifest/populate", #' @export manifest_validate <- function(url="http://localhost:3001/v1/model/validate", schema_url="https://raw.githubusercontent.com/ncihtan/data-models/main/HTAN.model.jsonld", #nolint - data_type, file_name, restrict_rules=FALSE) { + data_type, file_name, restrict_rules=FALSE, project_scope = NULL) { req <- httr::POST(url, query=list( schema_url=schema_url, data_type=data_type, - restrict_rules=restrict_rules), + restrict_rules=restrict_rules, + project_scope = project_scope), body=list(file_name=httr::upload_file(file_name)) ) From a9f25f0622d75a077236213dd745bc0245097cf5 Mon Sep 17 00:00:00 2001 From: afwillia Date: Wed, 15 Nov 2023 08:49:04 -0800 Subject: [PATCH 32/41] WIP: add asset view as project scope to validation endpoint --- server.R | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/server.R b/server.R index a6a22874..7a60e62d 100644 --- a/server.R +++ b/server.R @@ -727,7 +727,8 @@ shinyServer(function(input, output, session) { .infile_data <- inFile$data() .dd_template <- input$dropdown_template .restrict_rules <- dcc_config_react()$validate_restrict_rules - + .project_scope <- selected$master_asset_view() + promises::future_promise({ annotation_status <- switch(dca_schematic_api, reticulate = manifest_validate_py( @@ -740,7 +741,8 @@ shinyServer(function(input, output, session) { schema_url=.data_model, data_type=.schema, file_name=.datapath, - restrict_rules = .restrict_rules), + restrict_rules = .restrict_rules, + project_scope = .project_scope), { Sys.sleep(0) list(list( From 38ed6dd56fb38428481a24246d04b6cbbfa3ee51 Mon Sep 17 00:00:00 2001 From: afwillia Date: Thu, 16 Nov 2023 16:12:46 -0800 Subject: [PATCH 33/41] remove config dir from urls in config files --- server.R | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/server.R b/server.R index 1be601b8..66918c8b 100644 --- a/server.R +++ b/server.R @@ -198,7 +198,7 @@ shinyServer(function(input, output, session) { color = primary_col()) logo_img <- ifelse(!is.na(dcc_config_react()$dcc$logo_location), - file.path(config_dir, dcc_config_react()$dcc$logo_location), + dcc_config_react()$dcc$logo_location, "https://raw.githubusercontent.com/Sage-Bionetworks/data_curator_config/main/demo/Logo_Sage_Logomark.png") logo_link <- ifelse(!is.na(dcc_config_react()$dcc$logo_link), @@ -238,7 +238,7 @@ shinyServer(function(input, output, session) { } # Use the template dropdown config file from the appropriate branch of # data_curator_config - conf_file <- reactiveVal(file.path(config_dir, template_config_files[input$dropdown_asset_view])) + conf_file <- reactiveVal(template_config_files[input$dropdown_asset_view]) config_df <- jsonlite::fromJSON(conf_file()) conf_template <- setNames(config_df[[1]]$schema_name, config_df[[1]]$display_name) @@ -323,7 +323,7 @@ shinyServer(function(input, output, session) { is.null(dcc_config_react()$dcc$data_model_info), FALSE, TRUE) nx_report_info( - title = sprintf("DCA for %s", dcc_config_react()$dcc$project_name), + title = sprintf("DCA for %s", dcc_config_react()$dcc$name), tags$ul( if (has_dcc) tags$li(tags$a(href = dcc_config_react()$dcc$dcc_help_link, "DCA Help Docs", target = "_blank")), if (has_portal) tags$li(tags$a(href = dcc_config_react()$dcc$portal_help_link, "Portal Help Docs", target = "_blank")), @@ -599,7 +599,7 @@ shinyServer(function(input, output, session) { .schema_url <- data_model() .asset_view <- selected$master_asset_view() .template <- paste( - dcc_config_react()$dcc$project_name, + dcc_config_react()$dcc$name, "-", input$dropdown_template ) From aef9d0b686de011d2cc3164b7a11a397dfc39f44 Mon Sep 17 00:00:00 2001 From: afwillia Date: Tue, 28 Nov 2023 15:55:56 -0800 Subject: [PATCH 34/41] WIP: add ability to pass multiple project_scope to manifest_validate --- R/schematic_rest_api.R | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/R/schematic_rest_api.R b/R/schematic_rest_api.R index c691b822..794c1afa 100644 --- a/R/schematic_rest_api.R +++ b/R/schematic_rest_api.R @@ -115,13 +115,36 @@ manifest_populate <- function(url="http://localhost:3001/v1/manifest/populate", #' @export manifest_validate <- function(url="http://localhost:3001/v1/model/validate", schema_url="https://raw.githubusercontent.com/ncihtan/data-models/main/HTAN.model.jsonld", #nolint - data_type, file_name, restrict_rules=FALSE, project_scope = NULL) { + data_type, file_name, restrict_rules=FALSE, project_scope = NULL, + access_token, asset_view = NULL) { + + flattenbody <- function(x) { + # A form/query can only have one value per name, so take + # any values that contain vectors length >1 and + # split them up + # list(x=1:2, y="a") becomes list(x=1, x=2, y="a") + if (all(lengths(x)<=1)) return(x); + do.call("c", mapply(function(name, val) { + if (length(val)==1 || any(c("form_file", "form_data") %in% class(val))) { + x <- list(val) + names(x) <- name + x + } else { + x <- as.list(val) + names(x) <- rep(name, length(val)) + x + } + }, names(x), x, USE.NAMES = FALSE, SIMPLIFY = FALSE)) + } + req <- httr::POST(url, - query=list( + httr::add_headers(Authorization = sprintf("Bearer %s", access_token)), + query=flattenbody(list( schema_url=schema_url, data_type=data_type, restrict_rules=restrict_rules, - project_scope = project_scope), + project_scope = project_scope, + asset_view = asset_view)), body=list(file_name=httr::upload_file(file_name)) ) From e9a4aece5db6c83c08504057645003fba6096731 Mon Sep 17 00:00:00 2001 From: afwillia Date: Tue, 28 Nov 2023 15:56:10 -0800 Subject: [PATCH 35/41] Add asset view to manifest_validate --- server.R | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/server.R b/server.R index 644affc1..8e202fb7 100644 --- a/server.R +++ b/server.R @@ -723,9 +723,11 @@ shinyServer(function(input, output, session) { .data_model <- data_model() .infile_data <- inFile$data() .dd_template <- input$dropdown_template - .restrict_rules <- dcc_config_react()$validate_restrict_rules - .project_scope <- selected$master_asset_view() - + .restrict_rules <- dcc_config_react()$schematic$model_validate$restrict_rules + .project_scope <- data_list$projects() + .access_token <- access_token + .asset_view <- selected$master_asset_view() +browser() promises::future_promise({ annotation_status <- switch(dca_schematic_api, reticulate = manifest_validate_py( @@ -739,7 +741,9 @@ shinyServer(function(input, output, session) { data_type=.schema, file_name=.datapath, restrict_rules = .restrict_rules, - project_scope = .project_scope), + project_scope = .project_scope, + access_token = .access_token, + asset_view <- .asset_view), { Sys.sleep(0) list(list( From 99854d044d6fc7a5318ed0b8871f7910bba0d871 Mon Sep 17 00:00:00 2001 From: afwillia Date: Tue, 5 Dec 2023 11:17:20 -0800 Subject: [PATCH 36/41] Remove node uninstall/install from Dockerfile. --- Dockerfile | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index 98204915..65dfda63 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,10 +13,6 @@ RUN apt-get install -y libxml2 libglpk-dev libicu-dev libicu70 curl COPY shiny-server.conf /etc/shiny-server/shiny-server.conf RUN chmod 777 /etc/shiny-server/shiny-server.conf -# Update node. https://github.com/nodesource/distributions -RUN apt-get remove nodejs -RUN curl -fsSL https://deb.nodesource.com/setup_16.x | sudo -E bash - && apt-get install -y nodejs - USER shiny WORKDIR /srv/shiny-server/app From 4f0e69b7e742ac3d588cbb2d090c8cd044c44f2d Mon Sep 17 00:00:00 2001 From: afwillia Date: Tue, 28 Nov 2023 15:56:10 -0800 Subject: [PATCH 37/41] remove browser statement --- server.R | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/server.R b/server.R index 644affc1..c08c288f 100644 --- a/server.R +++ b/server.R @@ -723,8 +723,10 @@ shinyServer(function(input, output, session) { .data_model <- data_model() .infile_data <- inFile$data() .dd_template <- input$dropdown_template - .restrict_rules <- dcc_config_react()$validate_restrict_rules - .project_scope <- selected$master_asset_view() + .restrict_rules <- dcc_config_react()$schematic$model_validate$restrict_rules + .project_scope <- data_list$projects() + .access_token <- access_token + .asset_view <- selected$master_asset_view() promises::future_promise({ annotation_status <- switch(dca_schematic_api, @@ -739,7 +741,9 @@ shinyServer(function(input, output, session) { data_type=.schema, file_name=.datapath, restrict_rules = .restrict_rules, - project_scope = .project_scope), + project_scope = .project_scope, + access_token = .access_token, + asset_view <- .asset_view), { Sys.sleep(0) list(list( From 1c8626189ce764b9f62c1d22f96f50e2ca1ef38c Mon Sep 17 00:00:00 2001 From: afwillia Date: Thu, 14 Dec 2023 14:50:47 -0800 Subject: [PATCH 38/41] fix argument assignment operator in manifest_validation function call --- server.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server.R b/server.R index c08c288f..41d51847 100644 --- a/server.R +++ b/server.R @@ -743,7 +743,7 @@ shinyServer(function(input, output, session) { restrict_rules = .restrict_rules, project_scope = .project_scope, access_token = .access_token, - asset_view <- .asset_view), + asset_view = .asset_view), { Sys.sleep(0) list(list( From 7042e23ac9c01cce46c5ade84737e2a862cea409 Mon Sep 17 00:00:00 2001 From: afwillia Date: Thu, 14 Dec 2023 15:46:09 -0800 Subject: [PATCH 39/41] WIP: check the template config for project scope. If no project scope, set project_scope and asset_view to NULL in manifest_validate to avoid cross-manifest validation --- server.R | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/server.R b/server.R index 41d51847..954189ea 100644 --- a/server.R +++ b/server.R @@ -64,7 +64,8 @@ shinyServer(function(input, output, session) { project = reactiveVal(NULL), folder = reactiveVal(""), schema = reactiveVal(NULL), schema_type = reactiveVal(NULL), master_asset_view = reactiveVal(NULL), - master_asset_view_label = reactiveVal(NULL) + master_asset_view_label = reactiveVal(NULL), + project_scope = reactiveVal(NULL) ) isUpdateFolder <- reactiveVal(FALSE) @@ -540,6 +541,14 @@ shinyServer(function(input, output, session) { selected$schema(data_list$template()[input$dropdown_template]) schema_type <- config_schema()[[1]]$type[which(config_schema()[[1]]$display_name == input$dropdown_template)] selected$schema_type(schema_type) + + # set project scope for each template for cross-manifest validation. + # If project_scope is missing from dca_template_config.json then + # this value will be NULL and cross-manifest validation won't happen. + # validation will occur. + project_scope <- config_schema()[[1]]$project_scope[which(config_schema()[[1]]$display_name == input$dropdown_template)] + selected$project_scope(project_scope) + # clean all tags related with selected template sapply(clean_tags, FUN = hide) }, ignoreInit = TRUE) @@ -724,9 +733,12 @@ shinyServer(function(input, output, session) { .infile_data <- inFile$data() .dd_template <- input$dropdown_template .restrict_rules <- dcc_config_react()$schematic$model_validate$restrict_rules - .project_scope <- data_list$projects() + .project_scope <- selected$project_scope() .access_token <- access_token - .asset_view <- selected$master_asset_view() + # asset view must be NULL to avoid cross-manifest validation. + # doing this in a verbose way to avoid warning with ifelse + .asset_view <- NULL + if (!is.null(.project_scope)) .asset_view <- selected$master_asset_view() promises::future_promise({ annotation_status <- switch(dca_schematic_api, @@ -754,7 +766,7 @@ shinyServer(function(input, output, session) { )) } ) - + # validation messages validationResult(annotation_status, .dd_template, .infile_data) From c397b7a722b302376634996db1a4e8766002a59b Mon Sep 17 00:00:00 2001 From: afwillia Date: Tue, 2 Jan 2024 08:55:15 -0800 Subject: [PATCH 40/41] Remove two obsolete statements. --- server.R | 2 -- 1 file changed, 2 deletions(-) diff --git a/server.R b/server.R index 954189ea..8e3ce26d 100644 --- a/server.R +++ b/server.R @@ -635,7 +635,6 @@ shinyServer(function(input, output, session) { ), { message("Downloading offline manifest") - Sys.sleep(0) tibble(a="b", c="d") } ) @@ -757,7 +756,6 @@ shinyServer(function(input, output, session) { access_token = .access_token, asset_view = .asset_view), { - Sys.sleep(0) list(list( "errors" = list( Row = NA, Column = NA, Value = NA, From c28db5ade71145420970aa9c09abe07b10f3f5a0 Mon Sep 17 00:00:00 2001 From: afwillia Date: Tue, 2 Jan 2024 13:50:38 -0800 Subject: [PATCH 41/41] Read the project scope into a vector from the template config file. --- server.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server.R b/server.R index 8e3ce26d..21177f24 100644 --- a/server.R +++ b/server.R @@ -546,9 +546,9 @@ shinyServer(function(input, output, session) { # If project_scope is missing from dca_template_config.json then # this value will be NULL and cross-manifest validation won't happen. # validation will occur. - project_scope <- config_schema()[[1]]$project_scope[which(config_schema()[[1]]$display_name == input$dropdown_template)] + project_scope <- config_schema()[[1]]$project_scope[[which(config_schema()[[1]]$display_name == input$dropdown_template)]] selected$project_scope(project_scope) - + # clean all tags related with selected template sapply(clean_tags, FUN = hide) }, ignoreInit = TRUE)