diff --git a/components/board.upload/R/upload_module_preview_counts.R b/components/board.upload/R/upload_module_preview_counts.R index e94c5b38e..8438fdd6a 100644 --- a/components/board.upload/R/upload_module_preview_counts.R +++ b/components/board.upload/R/upload_module_preview_counts.R @@ -13,29 +13,33 @@ upload_table_preview_counts_ui <- function(id) { } upload_table_preview_counts_server <- function( - id, - create_raw_dir, - auth, - uploaded, - checked_matrix, - is_logscale, - checklist, - scrollY, - width, - height, - title, - info.text, - caption, - upload_datatype, - is.olink - ) { + id, + create_raw_dir, + auth, + uploaded, + checked_matrix, + is_logscale, + checklist, + scrollY, + width, + height, + title, + info.text, + caption, + upload_datatype, + is.olink, + public_dataset_id + ) { moduleServer(id, function(input, output, session) { + ns <- session$ns + GEO_alert_shown <- reactiveVal(FALSE) + table_data <- shiny::reactive({ shiny::req(!is.null(uploaded$counts.csv)) - dt <- uploaded$counts.csv + dt <- uploaded$counts.csv nrow0 <- nrow(dt) ncol0 <- ncol(dt) MAXROW <- 1000 @@ -58,10 +62,8 @@ upload_table_preview_counts_server <- function( table.RENDER <- function() { dt <- table_data() req(!is.null(dt)) - is.integer <- is.integer(dt) || all(round(dt) == dt, na.rm = TRUE) digits <- ifelse(is.integer, 0, 2) - DT::datatable(dt, class = "compact hover", rownames = TRUE, @@ -82,6 +84,7 @@ upload_table_preview_counts_server <- function( } output$table_counts <- shiny::renderUI({ + action_buttons <- div( style = "display: flex; justify-content: left; margin: 8px;", if (is.null(uploaded$counts.csv)) { @@ -115,95 +118,31 @@ upload_table_preview_counts_server <- function( ) ) - div( - bslib::as_fill_carrier(), - style = "width: 100%; display: flex; ", - if (is.null(uploaded$counts.csv)) { - if (upload_datatype() == "proteomics") { - msg <- "The counts file (counts.csv) contains the gene counts for all samples. For proteomics data types other than Olink NPX, the file should be a tabular text file (.csv), where each row corresponds to a feature (i.e. genes) and each column corresponds to a sample. For Olink NPX, the uploaded file needs to be the standard Olink format." - } else { - msg <- "The counts file (counts.csv) contains the gene counts for all samples. The file should be a tabular text file (.csv), where each row corresponds to a feature (i.e. genes) and each column corresponds to a sample." - } - bslib::layout_columns( - col_widths = c(-3, 6, -3), - row_heights = list("auto", 8, 1, 2), - gap = "0.5rem", - bslib::as_fill_carrier(bs_alert(tspan(msg), closable = FALSE, translate_js = FALSE)), - bslib::card( - if (upload_datatype() == "multi-omics") { - shiny::radioButtons( - ns("data_source"), - label = "Select input files from:", - choices = c("multi-csv", "pgx", "single-csv"), - selected = "multi-csv", - inline = TRUE - ) - }, - if (upload_datatype() == "multi-omics") { - shiny::conditionalPanel( - condition = sprintf("input['%s'] == 'pgx'", ns("data_source")), - div( - div( - style = "margin-bottom: 15px;", - shiny::radioButtons( - ns("data_processing"), - label = "Select data processing level:", - choices = c("Raw" = "raw", "Normalized (also batch corrected if selected on computation)" = "normalized"), - selected = "raw", - inline = TRUE - ) - ), - div( - style = "display: flex; align-items: center; gap: 10px; margin-bottom: 10px;", - span("Selected:", style = "font-weight: bold;"), - textOutput(ns("selected_rows_text")), - ), - div( - style = "height: 350px; overflow-y: auto;", - DT::DTOutput(ns("available_data_table")) - ), - style = "width: 100%; max-height: 400px; overflow-y: auto;" - ), - selection = "multiple", - options = list(pageLength = 5, dom = "tp", scrollY = TRUE) - ) - }, - - if (upload_datatype() == "multi-omics") { - shiny::conditionalPanel( - condition = sprintf("input['%s'] == 'multi-csv'", ns("data_source")), - shiny::uiOutput(ns("dynamic_file_inputs"))#, - ) - }, + if (public_dataset_id() != "") { - if (upload_datatype() == "multi-omics") { - shiny::conditionalPanel( - condition = sprintf("input['%s'] == 'single-csv'", ns("data_source")), - fileInputArea( - ns("counts_csv"), - shiny::h4(tspan("Upload counts.csv", js = FALSE), class = "mb-0"), - multiple = FALSE, - accept = c(".csv"), - width = "100%" - ) - ) - }, - - if (upload_datatype() != "multi-omics") { - fileInputArea( - ns("counts_csv"), - shiny::h4(tspan("Upload counts.csv", js = FALSE), class = "mb-0"), - multiple = FALSE, - accept = c(".csv"), - width = "100%" - ) - }, - style = "background-color: aliceblue; border: 0.07rem dashed steelblue;" - ), - action_buttons, - br() - ) - }, + ID <- public_dataset_id() + msg <- paste0("Retrieving ", ID, " from GEO, ReCount, or ArrayExpress...
", "Please wait. Most datasets take 2-3 mins.") + + showModal(modalDialog( + div(id = "custom-progress-modal", HTML(msg), + div(id = "custom-progress-container", + div(id = "custom-progress-bar"))), + footer = NULL, fade = FALSE)) + GEO <- tryCatch({ playbase::pgx.getGEOseries(accession = ID, archs.h5 = NULL, get.info = FALSE)}, + error = function(w) { NULL }) + removeModal() + + if (!is.null(GEO)) { + if (!GEO_alert_shown()) { + msg <- paste0("Success! ", ID, " found in ", GEO[["source"]], ".\nWe're preparing it...") + GEO_alert_shown(TRUE) + } + uploaded$counts.csv <- GEO[["counts"]] + uploaded$samples.csv <- GEO[["samples"]] + cm <- intersect(colnames(GEO[["counts"]]), rownames(GEO[["samples"]])) + GEO <- NULL + } + if (!is.null(uploaded$counts.csv)) { bslib::layout_columns( col_widths = 12, @@ -227,8 +166,129 @@ upload_table_preview_counts_server <- function( ), bslib::layout_columns(action_buttons, br(), uiOutput(ns("error_summary"))) ) - } ## end of if-else - ) ## end of div + } else { + div("No counts data available for this public dataset.") + } + + } else { + + div( + bslib::as_fill_carrier(), + style = "width: 100%; display: flex; ", + if (is.null(uploaded$counts.csv)) { + if (upload_datatype() == "proteomics") { + msg <- "The counts file (counts.csv) contains the gene counts for all samples. For proteomics data types other than Olink NPX, the file should be a tabular text file (.csv), where each row corresponds to a feature (i.e. genes) and each column corresponds to a sample. For Olink NPX, the uploaded file needs to be the standard Olink format." + } else { + msg <- "The counts file (counts.csv) contains the gene counts for all samples. The file should be a tabular text file (.csv), where each row corresponds to a feature (i.e. genes) and each column corresponds to a sample." + } + bslib::layout_columns( + col_widths = c(-3, 6, -3), + row_heights = list("auto", 8, 1, 2), + gap = "0.5rem", + bslib::as_fill_carrier(bs_alert(tspan(msg), closable = FALSE, translate_js = FALSE)), + bslib::card( + if (upload_datatype() == "multi-omics") { + shiny::radioButtons( + ns("data_source"), + label = "Select input files from:", + choices = c("multi-csv", "pgx", "single-csv"), + selected = "multi-csv", + inline = TRUE + ) + }, + if (upload_datatype() == "multi-omics") { + shiny::conditionalPanel( + condition = sprintf("input['%s'] == 'pgx'", ns("data_source")), + div( + div( + style = "margin-bottom: 15px;", + shiny::radioButtons( + ns("data_processing"), + label = "Select data processing level:", + choices = c("Raw" = "raw", "Normalized (also batch corrected if selected on computation)" = "normalized"), + selected = "raw", + inline = TRUE + ) + ), + div( + style = "display: flex; align-items: center; gap: 10px; margin-bottom: 10px;", + span("Selected:", style = "font-weight: bold;"), + textOutput(ns("selected_rows_text")), + ), + div( + style = "height: 350px; overflow-y: auto;", + DT::DTOutput(ns("available_data_table")) + ), + style = "width: 100%; max-height: 400px; overflow-y: auto;" + ), + selection = "multiple", + options = list(pageLength = 5, dom = "tp", scrollY = TRUE) + ) + }, + + if (upload_datatype() == "multi-omics") { + shiny::conditionalPanel( + condition = sprintf("input['%s'] == 'multi-csv'", ns("data_source")), + shiny::uiOutput(ns("dynamic_file_inputs"))#, + ) + }, + + if (upload_datatype() == "multi-omics") { + shiny::conditionalPanel( + condition = sprintf("input['%s'] == 'single-csv'", ns("data_source")), + fileInputArea( + ns("counts_csv"), + shiny::h4(tspan("Upload counts.csv", js = FALSE), class = "mb-0"), + multiple = FALSE, + accept = c(".csv"), + width = "100%" + ) + ) + }, + + if (upload_datatype() != "multi-omics") { + fileInputArea( + ns("counts_csv"), + shiny::h4(tspan("Upload counts.csv", js = FALSE), class = "mb-0"), + multiple = FALSE, + accept = c(".csv"), + width = "100%" + ) + }, + + style = "background-color: aliceblue; border: 0.07rem dashed steelblue;" + ), + action_buttons, + br() + ) + }, + if (!is.null(uploaded$counts.csv)) { + bslib::layout_columns( + col_widths = 12, + bslib::layout_columns( + col_widths = c(8, 4), + TableModuleUI( + ns("counts_datasets"), + width = width, + height = height, + title = title, + info.text = info.text, + caption = caption, + label = "", + show.maximize = FALSE, + translate_js = FALSE + ), + bslib::navset_card_pill( + bslib::nav_panel(title = "Histogram", br(), plotOutput(ns("histogram"))), + bslib::nav_panel(title = "Box plots", br(), plotOutput(ns("boxplots"))) + ) + ), + bslib::layout_columns(action_buttons, br(), uiOutput(ns("error_summary"))) + ) + } ## end of if-else + ) ## end of div + } + }) output$selected_rows_text <- renderText({ @@ -485,7 +545,7 @@ upload_table_preview_counts_server <- function( shinyalert::shinyalert(title = "Warning", text = err.html, html = TRUE) } }) - + # pass counts to uploaded when uploaded observeEvent(input$counts_csv, { # check if counts is csv (necessary due to drag and drop of any file) @@ -526,7 +586,7 @@ upload_table_preview_counts_server <- function( overwrite = TRUE ) } - + ##---counts---## sel <- grep("count|expression|abundance|concentration", tolower(input$counts_csv$name)) if (length(sel)) { @@ -572,7 +632,7 @@ upload_table_preview_counts_server <- function( if (upload_datatype() == "proteomics" && is.olink() && !is.null(df.samples)) { uploaded$samples.csv <- df.samples } - + ## ##---samples---## ## sel <- grep("samples", tolower(input$counts_csv$name)) ## if (length(sel)) { @@ -670,3 +730,4 @@ upload_table_preview_counts_server <- function( ) }) ## end of moduleServer } ## end of server + diff --git a/components/board.upload/R/upload_module_preview_samples.R b/components/board.upload/R/upload_module_preview_samples.R index b60156bf7..c61ae756d 100644 --- a/components/board.upload/R/upload_module_preview_samples.R +++ b/components/board.upload/R/upload_module_preview_samples.R @@ -21,15 +21,31 @@ upload_table_preview_samples_server <- function( title, info.text, caption, - upload_datatype) { + upload_datatype, + public_dataset_id + ) { moduleServer(id, function(input, output, session) { ns <- session$ns + public_metadata_full <- shiny::reactiveVal(NULL) + shiny::observe({ + if (public_dataset_id() != "" && !is.null(uploaded$samples.csv)) { + orig_sample_matrix(uploaded$samples.csv) + if (is.null(public_metadata_full())) { + public_metadata_full(orig_sample_matrix()) + } + } + }) + table_data <- shiny::reactive({ shiny::req(!is.null(uploaded$samples.csv)) - dt <- orig_sample_matrix() + dt <- if (public_dataset_id() != "" && !is.null(public_metadata_full())) { + public_metadata_full() + } else { + orig_sample_matrix() + } nrow0 <- nrow(dt) ncol0 <- ncol(dt) MAXSHOW <- 100 @@ -50,25 +66,43 @@ upload_table_preview_samples_server <- function( dt <- dt[, vars_selected, drop = FALSE] uploaded$samples.csv <- dt loaded_samples(TRUE) - dt + return(dt) }) shiny::observeEvent(input$vars_selected, { - if (all(input$vars_selected %in% colnames(orig_sample_matrix()))) { + dt_cols <- if (public_dataset_id() != "" && !is.null(public_metadata_full())) { + colnames(public_metadata_full()) + } else { + colnames(orig_sample_matrix()) + } + if (all(input$vars_selected %in% dt_cols)) { vars_selected(input$vars_selected) } }) - - shiny::observeEvent(orig_sample_matrix(), { - vars_selected(colnames(orig_sample_matrix())) + + shiny::observe({ + cols <- if (public_dataset_id() != "" && !is.null(public_metadata_full())) { + colnames(public_metadata_full()) + } else { + colnames(orig_sample_matrix()) + } + current_selected <- vars_selected() + if (is.null(current_selected) || length(current_selected) == 0 || !all(current_selected %in% cols)) { + vars_selected(cols) + } }) output$col_sel <- renderUI({ + choices <- if (public_dataset_id() != "" && !is.null(public_metadata_full())) { + colnames(public_metadata_full()) + } else { + colnames(orig_sample_matrix()) + } shiny::checkboxGroupInput( ns("vars_selected"), label = "Retain variable:", - choices = colnames(orig_sample_matrix()), - selected = colnames(orig_sample_matrix()), + choices = choices, + selected = vars_selected(), inline = TRUE ) }) @@ -125,7 +159,7 @@ upload_table_preview_samples_server <- function( div( bslib::as_fill_carrier(), - if (!loaded_samples()) { + if (!loaded_samples() && public_dataset_id() == "") { bslib::layout_columns( col_widths = c(-3, 6, -3), row_heights = list("auto", 8, 1, 2), diff --git a/components/board.upload/R/upload_server.R b/components/board.upload/R/upload_server.R index e359c112c..0be5ab003 100644 --- a/components/board.upload/R/upload_server.R +++ b/components/board.upload/R/upload_server.R @@ -30,6 +30,7 @@ UploadBoard <- function(id, upload_name <- reactiveVal(NULL) upload_description <- reactiveVal(NULL) upload_datatype <- reactiveVal(NULL) + public_dataset_id <- reactiveVal(NULL) upload_gset_methods <- reactiveVal(NULL) upload_gx_methods <- reactiveVal(NULL) process_counter <- reactiveVal(0) @@ -103,20 +104,7 @@ UploadBoard <- function(id, names(all_species) <- paste0(all_species," (",common_name,")") names(all_species)[all_species=="No organism"] <- "" shiny::updateSelectizeInput(session, "selected_organism", choices = all_species, server = TRUE) - }) - - output$proteomics_subtype_ui <- shiny::renderUI({ - if (upload_datatype() == "proteomics") { - shiny::selectInput( - ns("proteomics_type"), - label = "Proteomics type:", - choices = c("MS", "Olink NPX"), - selected = "MS", - width = "150px" - ) - } else { - NULL - } + shiny::updateSelectizeInput(session, "selected_organism_public", choices = all_species, server = TRUE) }) is.olink <- shiny::reactive({ @@ -127,6 +115,21 @@ UploadBoard <- function(id, return(FALSE) } }) + + observeEvent(input$start_search, { + ID <- public_dataset_id() + if (ID != "") { + valid.ID <- playbase::is.GEO.id.valid(ID) + if (!valid.ID) { + msg <- paste0(ID, " seems not valid. Please use a valid dataset ID.") + shinyalert::shinyalert(text = msg, type = "error") + } else { + new_upload(new_upload() + 1) + } + } else { + shinyalert::shinyalert(text = "Please enter a dataset ID", type = "error") + } + }) ## ============================================================================ ## ================== NEW DATA UPLOAD ========================================= @@ -137,10 +140,10 @@ UploadBoard <- function(id, uploaded_method <- NA shiny::observeEvent(input$upload_files_btn, - { - shinyjs::click(id = "upload_files") - }, - ignoreNULL = TRUE + { + shinyjs::click(id = "upload_files") + }, + ignoreNULL = TRUE ) shiny::observeEvent(uploaded_pgx(), { @@ -251,7 +254,7 @@ UploadBoard <- function(id, ## -------------------------------------------------------- df0 <- uploaded$counts.csv if (is.null(df0)) return(NULL) - + checked_for_log(FALSE) res <- playbase::pgx.checkINPUT(df0, "COUNTS") write_check_output(res$checks, "COUNTS", raw_dir()) @@ -280,7 +283,7 @@ UploadBoard <- function(id, } return(list(res = res, olink = olink)) - + } ) @@ -306,7 +309,6 @@ UploadBoard <- function(id, isConfirmed <- input$logCorrectCounts if (is.null(isConfirmed)) isConfirmed = FALSE - ## RESTORE AVERAGE RANK PLOT. if (olink) { res$checks[["e29"]] <- NULL check.e29 = TRUE @@ -370,7 +372,7 @@ UploadBoard <- function(id, if (is.null(checked)) { uploaded[["last_uploaded"]] <- setdiff(uploaded[["last_uploaded"]], "counts.csv") } - + if (check.e29) { if (isConfirmed) isConfirmed = TRUE if (is.null(isConfirmed)) isConfirmed = FALSE @@ -393,6 +395,7 @@ UploadBoard <- function(id, { ## get uploaded counts df0 <- uploaded$samples.csv + if (is.null(df0)) { return(list(status = "Missing samples.csv", matrix = NULL)) } ## Single matrix counts check @@ -452,11 +455,11 @@ UploadBoard <- function(id, uploaded[["contrasts.csv"]] <<- NULL } - list(status = status, SAMPLES = res_samples, COUNTS = res_counts) + LL <- list(status = status, SAMPLES = res_samples, COUNTS = res_counts) + return(LL) } ) - ## -------------------------------------------------------- ## Check contrast matrix ## -------------------------------------------------------- @@ -467,9 +470,7 @@ UploadBoard <- function(id, { ## get uploaded counts df0 <- uploaded$contrasts.csv - if (is.null(df0)) { - return(list(status = "Missing contrasts.csv", matrix = NULL)) - } + if (is.null(df0)) return(list(status = "Missing contrasts.csv", matrix = NULL)) ## --------- Single matrix counts check---------- res <- playbase::pgx.checkINPUT(df0, "CONTRASTS") @@ -536,6 +537,7 @@ UploadBoard <- function(id, ## Dynamic render of appropriate wizard output$upload_wizard <- shiny::renderUI({ + counts_ui <- wizardR::wizard_step( step_title = tspan("Step 1: Upload counts", js = FALSE), step_id = "step_counts", @@ -550,10 +552,10 @@ UploadBoard <- function(id, step_id = "step_samples", server = TRUE, upload_table_preview_samples_ui( - ns("samples_preview") + ns("samples_preview") ) ) - + contrasts_ui <- wizardR::wizard_step( step_title = "Step 3: Create comparisons", step_id = "step_comparisons", @@ -721,6 +723,20 @@ UploadBoard <- function(id, upload_organism(input$selected_organism) }) + observeEvent(input$selected_datatype_public, { + upload_datatype(input$selected_datatype_public) + updateSelectInput(session, "selected_datatype", selected = input$selected_datatype_public) + }) + + observeEvent(input$selected_organism_public, { + upload_organism(input$selected_organism_public) + updateSelectInput(session, "selected_organism", selected = input$selected_organism_public) + }) + + observeEvent(input$dataset_identifier, { + public_dataset_id(input$dataset_identifier) + }) + observeEvent(input$start_upload, { recompute_pgx(NULL) ## need to reset ??? }) @@ -1170,7 +1186,6 @@ UploadBoard <- function(id, } ) - ## ===================================================================== ## ======================== MODULES SERVERS ============================ ## ===================================================================== @@ -1190,7 +1205,8 @@ UploadBoard <- function(id, info.text = "This is the uploaded counts data.", caption = "This is the uploaded counts data.", upload_datatype = upload_datatype, - is.olink = is.olink + is.olink = is.olink, + public_dataset_id = public_dataset_id ## accession ID ) upload_table_preview_samples_server( @@ -1206,7 +1222,8 @@ UploadBoard <- function(id, title = "Uploaded Samples", info.text = "This is the uploaded samples data.", caption = "This is the uploaded samples data.", - upload_datatype = upload_datatype + upload_datatype = upload_datatype, + public_dataset_id = public_dataset_id ## accession ID ) modified_ct <- upload_table_preview_contrasts_server( @@ -1313,8 +1330,6 @@ UploadBoard <- function(id, probetype = probetype ) - - ## ------------------------------------------------ ## Board return object ## ------------------------------------------------ diff --git a/components/board.upload/R/upload_ui.R b/components/board.upload/R/upload_ui.R index 6047bba23..fcb0fc3c5 100644 --- a/components/board.upload/R/upload_ui.R +++ b/components/board.upload/R/upload_ui.R @@ -12,46 +12,114 @@ UploadUI <- function(id) { bslib::layout_columns( fill = TRUE, div( - style = "display: flex; flex-direction: column; align-items: center; gap: 20px; margin-bottom: 150px; margin-top: 120px;", - div( - style = "width: 60%;", - bs_alert("To upload your own data, you should prepare at least two CSV files: an counts.csv file (containing your experiment data) and a samples.csv file (containing your sample information). A third contrasts.csv file (describing your comparisons) is optional. Read more about data preparation here.", closable = FALSE, translate = TRUE, html = TRUE) - ), - br(), - div( - p("Data type:", style = "text-align: left; margin: 0 0 2px 0; font-weight: bold;"), - shiny::selectInput( - ns("selected_datatype"), NULL, - choices = c( - "RNA-seq", - "mRNA microarray", - "proteomics", - "scRNA-seq", - "metabolomics (beta)" = "metabolomics", - "multi-omics (beta)" = "multi-omics" - ), - selected = DEFAULTS$datatype, - width = "400px" + style = "margin-top: 40px;", + tabsetPanel( + id = ns("upload_tabs"), + type = "tabs", + # Upload your own data tab + tabPanel( + "Upload your data", + value = "upload", + div( + style = "display: flex; flex-direction: column; align-items: center; gap: 20px; margin-bottom: 150px; margin-top: 40px;", + div( + style = "width: 60%;", + bs_alert("To upload your own data, you should prepare at least two CSV files: an counts.csv file (containing your experiment data) and a samples.csv file (containing your sample information). A third contrasts.csv file (describing your comparisons) is optional. Read more about data preparation here.", closable = FALSE, translate = TRUE, html = TRUE) + ), + br(), + div( + p("Data type:", style = "text-align: left; margin: 0 0 2px 0; font-weight: bold;"), + shiny::selectInput( + ns("selected_datatype"), NULL, + choices = c( + "RNA-seq", + "mRNA microarray", + "proteomics", + "scRNA-seq", + "metabolomics (beta)" = "metabolomics", + "multi-omics (beta)" = "multi-omics" + ), + selected = DEFAULTS$datatype, + width = "400px" + ), + shiny::uiOutput(ns("proteomics_subtype_ui")) + ), + div( + p("Organism:", style = "text-align: left; margin: 0 0 2px 0; font-weight: bold;"), + shiny::selectInput( + inputId = ns("selected_organism"), + label = NULL, + choices = NULL, + multiple = FALSE, + width = "400px" + ) + ), + br(), + shiny::actionButton( + ns("start_upload"), + "Start upload", + class = "btn-primary" + ), + br() + ) ), - shiny::uiOutput(ns("proteomics_subtype_ui")) - ), - div( - p("Organism:", style = "text-align: left; margin: 0 0 2px 0; font-weight: bold;"), - shiny::selectInput( - inputId = ns("selected_organism"), - label = NULL, - choices = NULL, - multiple = FALSE, - width = "400px" + + # Retrieve public datasets tab + tabPanel( + "Retrieve public datasets", + value = "public", + div( + style = "display: flex; flex-direction: column; align-items: center; gap: 20px; margin-bottom: 150px; margin-top: 40px;", + div( + style = "width: 60%;", + bs_alert("The 'Retrieve public data' functionality in OPG allows to query large repositories of publically available data to retrieve a specific dataset. You will need the dataset's unique identifier, such as the GEO ID. At the moment, GEO, recount3, and ArrayExpress repositories are queried.", closable = FALSE, translate = TRUE, html = TRUE) + ), + br(), + div( + p("Data type:", style = "text-align: left; margin: 0 0 2px 0; font-weight: bold;"), + shiny::selectInput( + ns("selected_datatype_public"), NULL, + choices = c( + "RNA-seq", + "mRNA microarray" + ), + selected = "RNA-seq", + width = "400px" + ) + ), + div( + p("Organism:", style = "text-align: left; margin: 0 0 2px 0; font-weight: bold;"), + shiny::selectInput( + inputId = ns("selected_organism_public"), + label = NULL, + choices = NULL, + multiple = FALSE, + width = "400px" + ) + ), + div( + p("Dataset identifier:", style = "text-align: left; margin: 0 0 2px 0; font-weight: bold;"), + shiny::textInput( + ns("dataset_identifier"), + label = NULL, + placeholder = "e.g., GSE12345, E-GEOD-12345", + width = "400px" + ), + div( + style = "font-size: 0.85em; color: #666; margin-top: 5px;", + "Supported: GEO (GSE), ArrayExpress (E-), recount3 datasets" + ) + ), + br(), + shiny::actionButton( + ns("start_search"), + "Retrieve dataset", + class = "btn-primary" + ), + br() + ) ) - ), - br(), - shiny::actionButton( - ns("start_upload"), - "Start upload", - class = "btn-primary" - ), - br() + ) ) ) ) diff --git a/components/modules/WelcomeBoard.R b/components/modules/WelcomeBoard.R index 7dd56ee9d..cd8d8ba48 100644 --- a/components/modules/WelcomeBoard.R +++ b/components/modules/WelcomeBoard.R @@ -169,6 +169,8 @@ WelcomeBoard <- function(id, auth, load_example, new_upload) { input$btn_upload_new }, { + bigdash.openSettings(lock = TRUE) + bigdash.openSidebar() bigdash.selectTab(session, selected = "upload-tab") } ) diff --git a/scss/components/_progress.scss b/scss/components/_progress.scss index f0b9ae0f1..49f1ca82a 100644 --- a/scss/components/_progress.scss +++ b/scss/components/_progress.scss @@ -34,4 +34,47 @@ html { display: block; } + #custom-progress-modal { + position: fixed; + top: 50% !important; + left: 50% !important; + transform: translate(-50%, -50%); + background-color: #ffffff; + color: black; + padding: 30px 50px; + font-size: 20px; + font-weight: bold; + border-radius: 10px; + z-index: 1050; + text-align: center; + } + + #custom-progress-bar { + height: 15px; + background-color: #007bff; + width: 40%; + transition: width 0.3s ease; + color: white; + font-weight: bold; + line-height: 25px; + animation: pulse-blue 2s infinite; + transform-origin: center; + } + + @keyframes pulse-blue { + 0% { box-shadow: 0 0 8px 2px #007bff; + transform: scale(1.2); } + 50% { box-shadow: 0 0 18px 8px #3399ff; + transform: scale(1.4); } + 100% { box-shadow: 0 0 8px 2px #007bff; + transform: scale(1); } + } + + #custom-progress-container { + width: 100%; + background-color: #e9ecef; + border-radius: 0.25rem; + overflow: hidden; + margin-top: 15px; + } } \ No newline at end of file