inst/shinyapp/server.R

# Define server logic to read selected file ----
server <- function(input, output, session) {
  # parse url to direct tab
  observe({
    query <- parseQueryString(session$clientData$url_search)

    if (!is.null(query[['tab']])) {
      updateTabItems(session, "tabs", query[['tab']])
    }
  })

  # reactive file location to make interactivity easier
  rv <- reactiveValues()
  rv$matrixloc <- NULL
  rv$metaloc <- NULL
  rv$step <- 0
  rv$clustifym <- "clustifyr not yet run"
  rv$lastgeo <- "GSE151974" #GSE113049"
  rv$ref <- NULL
  rv$ref_visited <- 0
  rv$ref_link <- NULL
  rv$res_visited <- 0
  rv$obj <- NULL
  rv$links2 <- data.frame()

  # hide some elements
  hide("header")
  hide("sepMat")
  hide("sepMeta")
  hide("dispMat")
  hide("dispMeta")
  hide("matrixPopup")
  hide("metadataPopup")

  # waiter checkpoints
  w1 <- Waiter$new(
    id = "contents1",
    html = tagList(
      spin_flower(),
      h4("Matrix loading..."),
      h4("")
    )
  )

  w2 <- Waiter$new(
    id = "contents2",
    html = tagList(
      spin_flower(),
      h4("Metadata loading..."),
      h4("")
    )
  )

  w3 <- Waiter$new(
    id = "reference",
    html = tagList(
      spin_flower(),
      h4("Reference building..."),
      h4("")
    )
  )

  w4 <- Waiter$new(
    id = "clustify",
    html = tagList(
      spin_flower(),
      h4("Clustifyr running..."),
      h4("")
    )
  )

  w5 <- Waiter$new(
    id = "hmap",
    html = tagList(
      spin_flower(),
      h4("Heatmap drawing..."),
      h4("")
    )
  )

  w6 <- Waiter$new(
    id = "modalgeo",
    html = tagList(
      spin_flower(),
      h4("Info fetching..."),
      h4("")
    )
  )

  w7 <- Waiter$new(
    id = "modalfiles",
    html = tagList(
      spin_flower(),
      h4("File previewing..."),
      h4("")
    )
  )

  w8 <- Waiter$new(
    id = "contents3",
    html = tagList(
      spin_flower(),
      h4("Reference loading..."),
      h4("")
    )
  )

  w9 <- Waiter$new(
    id = "someta",
    html = tagList(
      spin_flower(),
      h4("Preview loading..."),
      h4("")
    )
  )

  data1 <- reactive({
    # input$file1 will be NULL initially. After the user selects
    # and uploads a file, head of that data file by default,
    # or all rows if selected, will be shown.

    if (!is.null(input$file1) | !is.null(rv$matrixloc)) {
      if (!is.null(input$file1)) {
        rv$matrixloc <- input$file1
      }
      file <- rv$matrixloc

      if (!is.null(file)) {
        w1$show()
        message(file)
      }

      fileTypeFile1 <- tools::file_ext(file$datapath)
      req(file)
      if (str_to_lower(fileTypeFile1) == "rds") {
        df1 <- readRDS(file$datapath)
        if (any(class(df1) %in% c("SingleCellExperiment", "Seurat"))) {
          rv$obj <- df1
          df1 <- object_data(rv$obj, "data")
        }
      } else if (
        str_to_lower(fileTypeFile1) == "rdata" |
          str_to_lower(fileTypeFile1) == "rda"
      ) {
        df1 <- load_rdata(file$datapath)
        if (any(class(df1) %in% c("SingleCellExperiment", "Seurat"))) {
          rv$obj <- df1
          df1 <- object_data(df1, "data")
        }
      } else {
        df1 <- fread(file$datapath)
      }
    } else if (!is.null(rv$obj)) {
      df1 <- object_data(rv$obj, "data")
    } else {
      return(NULL)
    }

    if ((!is_local) & (object.size(df1) > 3e9)) {
      message("Potential memory issue due to file size")
      showModal(modalDialog(
        h2("File size over 3Gb, online version may be unstable"),
        easyClose = TRUE,
        fade = FALSE,
        footer = NULL
      ))
    }

    df1 <- df1 %>% as.data.frame()
    if (!has_rownames(df1) & length(unique(df1[, 1])) == nrow(df1)) {
      rownames(df1) <- df1[, 1]
      df1[, 1] <- NULL
    }

    w1$hide()
    df1
  })

  data2 <- reactive({
    if (!is.null(input$file2) | !is.null(rv$metaloc)) {
      if (!is.null(input$file2)) {
        rv$metaloc <- input$file2
      }
      file <- rv$metaloc

      if (!is.null(file)) {
        w2$show()
        message(file)
      }

      fileTypeFile2 <- tools::file_ext(file$datapath)
      req(file)
      if (str_to_lower(fileTypeFile2) == "rds") {
        df2 <- readRDS(file$datapath)
        if (any(class(df2) %in% c("SingleCellExperiment", "Seurat"))) {
          rv$obj <- df2
          df2 <- object_data(df2, "meta.data")
        }
      } else if (
        str_to_lower(fileTypeFile2) == "rdata" |
          str_to_lower(fileTypeFile2) == "rda"
      ) {
        df2 <- load_rdata(file$datapath)
        if (any(class(df2) %in% c("SingleCellExperiment", "Seurat"))) {
          rv$obj <- df2
          df2 <- object_data(rv$obj, "meta.data")
        }
      } else {
        df2 <- fread(file$datapath)
      }
    } else if (!is.null(rv$obj)) {
      df2 <- object_data(rv$obj, "meta.data")
    } else {
      return(NULL)
    }

    if ((!is_local) & (object.size(df2) > 3e9)) {
      message("Potential memory issue due to file size")
      showModal(modalDialog(
        h2("File size over 3Gb, online version may be unstable"),
        easyClose = TRUE,
        fade = FALSE,
        footer = NULL
      ))
    }

    df2 <- df2 %>% as.data.frame()
    if (!has_rownames(df2) & length(unique(df2[, 1])) == nrow(df2)) {
      rownames(df2) <- df2[, 1]
      df2[, 1] <- NULL
    }

    w2$hide()
    df2
  })

  data3a <- reactive({
    if (!is.null(input$file3)) {
      rv$ref <- input$file3
    }
    if (rv$ref == "built-in") {
      return(NULL)
    }
    file <- rv$ref

    if (!is.null(file)) {
      w8$show()
      message(file)
    }

    fileTypeFile3 <- tools::file_ext(file$datapath)
    req(file)

    if (str_to_lower(fileTypeFile3) == "rds") {
      df3 <- readRDS(file$datapath) %>% as.data.frame()
    } else if (
      str_to_lower(fileTypeFile3) == "rdata" |
        str_to_lower(fileTypeFile3) == "rda"
    ) {
      df3 <- load_rdata(file$datapath) %>% as.data.frame()
    } else {
      df3 <- fread(file$datapath) %>% # , header = input$header, sep = input$sepMat) %>%
        as.data.frame()
    }

    if ((!is_local) & (object.size(df3) > 3e9)) {
      message("Potential memory issue due to file size")
      showModal(modalDialog(
        h2("File size over 3Gb, online version may be unstable"),
        easyClose = TRUE,
        fade = FALSE,
        footer = NULL
      ))
    }

    if (!has_rownames(df3) & length(unique(df3[, 1])) == nrow(df3)) {
      rownames(df3) <- df3[, 1]
      df3[, 1] <- NULL
    }

    w8$hide()
    df3
  })

  output$contents1 <- DT::renderDataTable({
    if (is.null(rv$matrixloc) & is.null(rv$obj)) {
      return(df1 <- data.frame(`nodata` = rep("", 6)))
    } else {
      df1 <- data1()
    }

    # file 1
    if (input$dispMat == "head") {
      cols <- ncol(df1)
      df1 <- df1[, 1:min(cols, 5)]
      return(head(df1))
    } else {
      return(df1)
    }
  })

  output$contents2 <- DT::renderDataTable(
    {
      if (is.null(rv$metaloc) & is.null(rv$obj)) {
        return(df2 <- data.frame(`nodata` = rep("", 6)))
      } else {
        df2 <- data2()
      }

      updateSelectInput(
        session,
        "metadataCellType",
        choices = c("", colnames(df2)),
        selected = ""
      )

      # file 2
      if (input$dispMeta == "head") {
        return(head(df2))
      } else {
        return(df2)
      }
    },
    callback = DT::JS(js),
    selection = list(target = 'column', mode = "single")
  )

  output$colclicked <- renderUI({
    if (is.null(input[["column_clicked"]])) {
      "please select cluster column in drop-down menu, or click in the table"
    } else {
      input$metadataCellType
    }
  })

  observeEvent(input[["column_clicked"]], {
    updateSelectInput(
      session,
      "metadataCellType",
      selected = input[["column_clicked"]]
    )
  })

  output$ref_summary <- renderUI({
    HTML(paste0(
      "<b>",
      "cell types: ",
      ncol(data3()),
      "<br>",
      "genes: ",
      nrow(data3()),
      "<b>"
    ))
  })

  data3b <- reactive({
    w8$show()
    rv$ref <- "built-in"
    ref <- refs[[ref_dict[input$dataHubReference]]]
    rv$ref_link <- refs_meta[ref_dict[input$dataHubReference], ] %>%
      pull(sourceurl)
    w8$show()

    ref
  })

  data3 <- reactive({
    b <- data3b()
    a <- data3a()
    if (is.null(rv$ref)) {
      return(data.frame(`nodata` = rep("", 6)))
    } else if (rv$ref == "built-in") {
      df3 <- b
    } else {
      df3 <- a
    }
    df3
  })

  output$contents3 <- DT::renderDataTable({
    df3 <- data3()

    # file 3
    if (input$dispMat == "head") {
      return(head(df3))
    } else {
      return(df3)
    }
  })

  observeEvent(input$matrixPopup, {
    showModal(modalDialog(
      tags$caption("Matrix table"),
      DT::renderDataTable({
        matrixRender <- head(data1())
        DT::datatable(matrixRender)
      }),
      easyClose = TRUE
    ))
  })

  observeEvent(input$metadataPopup, {
    showModal(modalDialog(
      tags$caption("Metadata table"),
      DT::renderDataTable({
        matrixRender <- head(data2())
        DT::datatable(matrixRender)
      }),
      easyClose = TRUE
    ))
  })

  data_avg <- reactive({
    if (input$metadataCellType == "") {
      return(NULL)
    }
    w3$show()
    reference_matrix <- average_clusters(
      mat = data1(),
      metadata = data2()[[input$metadataCellType]],
      if_log = FALSE
    )
    w3$hide()
    reference_matrix
  })

  dataClustify <- reactive({
    if (input$metadataCellType == "") {
      return(NULL)
    }
    w4$show()
    benchmarkRef <- data3()

    if (!is.null(rv$obj)) {
      message("Single cell object detected")
      matrixSeuratObject <- rv$obj
      if (any(class(matrixSeuratObject) == "SingleCellExperiment")) {
        matrixSeuratObject <- as.Seurat(matrixSeuratObject)
      }
    } else {
      UMIMatrix <- data1()
      matrixSeuratObject <- CreateSeuratObject(
        counts = UMIMatrix,
        project = "Seurat object matrix",
        min.cells = 0,
        min.features = 0
      )
    }
    if (VariableFeatures(matrixSeuratObject) %>% length() == 0) {
      matrixSeuratObject <- FindVariableFeatures(
        matrixSeuratObject,
        selection.method = "vst",
        nfeatures = 2000
      )
    } else {
      message("Using variable genes in object")
    }

    metadataCol <- data2()[[input$metadataCellType]]
    # use for classification of cell types
    messages <<- capture.output(
      res <- clustify(
        input = object_data(matrixSeuratObject, "data"),
        metadata = metadataCol,
        ref_mat = benchmarkRef,
        query_genes = VariableFeatures(matrixSeuratObject),
        verbose = TRUE
      ),
      type = "message"
    )
    rv$clustifym <<- messages

    w4$hide()
    res
  })

  output$reference <- DT::renderDataTable({
    if (rv$res_visited == 1) {
      return(df1 <- data.frame(`nodata` = rep("", 6)))
    }
    reference_matrix <- data_avg()
    rownames_to_column(as.data.frame(reference_matrix), input$metadataCellType)
  })

  output$clustify <- DT::renderDataTable({
    if (rv$res_visited == 1) {
      return(df1 <- data.frame(`nodata` = rep("", 6)))
    }
    res <- dataClustify()
    rownames_to_column(as.data.frame(res), input$metadataCellType)
  })

  corToCall <- reactive({
    res <- dataClustify()
    cor_to_call(cor_mat = res, cluster_col = input$metadataCellType)
  })

  output$corToCall <- DT::renderDataTable({
    corToCall()
  })

  # Make plots such as heat maps to compare benchmarking with clustify with actual cell types

  output$hmap <- renderPlot({
    if (input$metadataCellType == "") {
      return(NULL)
    }
    tmp_mat <- dataClustify()
    # could expose as an option
    cutoff_to_display <- 0.5

    if (!is.null(tmp_mat)) {
      w5$show()
    }
    tmp_mat <- tmp_mat[, colSums(tmp_mat > 0.5) > 1]
    plot_hmap(tmp_mat)
  })

  referenceDownload <- reactive({
    avgMatrix <- data_avg()
  })

  clustifyDownload <- reactive({
    clustifyMatrix <- dataClustify()
  })

  output$downloadReference <- downloadHandler(
    filename = function() {
      paste("reference-", Sys.Date(), ".csv", sep = "")
    },
    content = function(file) {
      write.csv(referenceDownload(), file, quote = FALSE)
    }
  )
  output$downloadClustify <- downloadHandler(
    filename = function() {
      paste("clustify-", Sys.Date(), ".xlsx", sep = "")
    },
    content = function(file) {
      write.xlsx(
        list(corToCall(), clustifyDownload()),
        file,
        quote = FALSE,
        rowNames = TRUE
      )
    }
  )

  # load example data
  observeEvent(
    input$example,
    {
      message("loading prepackaged data")
      rv$matrixloc <- list(datapath = "data/example-input/matrix.csv.gz")
      rv$metaloc <- list(datapath = "data/example-input/meta-data.csv.gz")
      updateTabItems(session, "tabs", "metadataLoad")
    }
  )

  output$clustifym <- renderUI(
    HTML(paste0(c(rv$clustifym, ""), collapse = "<br/><br/>"))
  )

  # modal for GEO id
  observeEvent(
    input$geo1 | input$geo2,
    showModal(modalDialog(
      div(
        id = "modalgeo",
        textInput("geoid", "query GEO id", value = rv$lastgeo),
        actionButton("geogo", "Fetch file info", icon = icon("eye"))
      ),
      easyClose = TRUE,
      fade = FALSE,
      footer = NULL
    )),
    ignoreInit = TRUE
  )

  observeEvent(
    input$geogo,
    {
      w6$show()
      rv$lastgeo <- input$geoid
      rv$links <- list_geo(rv$lastgeo)
      message(rv$links)
      if (rv$links != "error_get") {
        rv$links2 <- rv$links %>%
          mutate(size = map(link, get_file_size)) %>%
          select(-link)
        links2 <- cbind(
          rv$links2,
          button = sapply(1:nrow(rv$links), make_button("tbl1")),
          stringsAsFactors = FALSE
        ) %>%
          data.table::data.table()
        links2 <- links2 %>%
          DT::datatable(
            options = list(
              dom = "ftp",
              searchHighlight = TRUE,
              paging = TRUE,
              pageLength = 5,
              scrollY = FALSE
            ),
            escape = ncol(links2) - 1,
            fillContainer = TRUE
          )
      } else {
        links2 <- data.frame(rv$links)
      }

      url <- str_c(
        "https://www.ncbi.nlm.nih.gov/geo/query/acc.cgi?acc=",
        input$geoid
      )
      w6$hide()
      showModal(modalDialog(
        size = "l",
        div(id = "modalfiles", DT::renderDataTable(links2)),
        easyClose = TRUE,
        fade = FALSE,
        footer = tagList(
          actionButton(
            "geopage",
            label = "Go to GEO page",
            onclick = paste0('window.open("', url, '", "_blank")'),
            icon = icon("link")
          ),
          actionButton(
            "email",
            label = "Email author for missing data",
            onclick = paste0('location.href="', prep_email(rv$lastgeo), '"'),
            icon = icon("envelope-open-text")
          ),
          actionButton(
            "sheet",
            label = "Spot check for someta",
            icon = icon("feather-alt")
          )
        )
      ))
    }
  )

  observeEvent(input[["button"]], {
    w7$show()
    splitID <- strsplit(input[["button"]], "_")[[1]]
    tbl <- splitID[2]
    row <- splitID[3]
    rv$loadinglink <<- rv$links$link[as.numeric(row)]

    # if tar, read a file list
    if (str_detect(rv$links$link[as.numeric(row)], "/GSE[0-9]+_RAW.tar")) {
      fullb <- FALSE
      previewdata <- preview_link(get_tar(rv$links$link[as.numeric(row)]))
    } else {
      fullb <- TRUE
      previewdata <- preview_link(rv$links$link[as.numeric(row)])
    }

    if (is.null(previewdata)) {
      fullb <- FALSE
      previewdata <- data.frame(unreadable = rep("", 4))
    } else {
      cols <- ncol(previewdata)
      previewdata <- previewdata[, 1:min(cols, 100)]
    }

    if (input[["activeTab"]] == "someta") {
      fullb <- FALSE
    }

    w7$hide()
    showModal(modalDialog(
      size = "l",
      div(
        id = "modalback",
        title = "preview",
        DT::renderDataTable(previewdata),
        if (fullb) {
          actionButton("full", "Start full loading", icon = icon("running"))
        } else {
          disabled(actionButton(
            "full",
            "Start full loading",
            icon = icon("running")
          ))
        },
        actionButton("back", "Back to file list", icon = icon("step-backward"))
      ),
      easyClose = TRUE,
      fade = FALSE,
      footer = NULL
    ))
  })

  observeEvent(input$full, {
    message(rv$loadinglink)
    if (input[["activeTab"]] == "matrixLoad") {
      rv$matrixloc <- list(datapath = rv$loadinglink)
    } else if (input[["activeTab"]] == "metadataLoad") {
      rv$metaloc <- list(datapath = rv$loadinglink)
    }
    removeModal()
  })

  observeEvent(input$sheet, {
    showModal(modalDialog(
      size = "l",
      div(
        id = "modalsheet",
        title = "Please fill out",
        renderUI(h2(rv$lastgeo)),
        hr(),
        strong(materialSwitch(
          "issc",
          "   is single cell data",
          value = TRUE,
          status = "success",
          right = TRUE,
          inline = FALSE,
          width = NULL
        )),
        strong(materialSwitch(
          "hasmeta",
          "   has metadata",
          value = TRUE,
          status = "success",
          right = TRUE,
          inline = FALSE,
          width = NULL
        )),
        strong(materialSwitch(
          "hascellcol",
          "   has cell type column in metadata",
          value = TRUE,
          status = "success",
          right = TRUE,
          inline = FALSE,
          width = NULL
        )),
        textInput("comment", "", placeholder = "Additional comments")
      ),
      easyClose = TRUE,
      fade = FALSE,
      footer = actionButton("submit", "Submit", icon = icon("feather-alt"))
    ))
  })
  observeEvent(input$back, {
    links2 <- cbind(
      rv$links2,
      button = sapply(1:nrow(rv$links), make_button("tbl1")),
      stringsAsFactors = FALSE
    ) %>%
      data.table::data.table()
    links2 <- links2 %>%
      DT::datatable(
        options = list(
          dom = "ftp",
          searchHighlight = TRUE,
          paging = TRUE,
          pageLength = 5,
          scrollY = FALSE
        ),
        escape = ncol(links2) - 1,
        fillContainer = TRUE
      )
    url <- str_c(
      "https://www.ncbi.nlm.nih.gov/geo/query/acc.cgi?acc=",
      input$geoid
    )
    showModal(modalDialog(
      size = "l",
      div(id = "modalfiles", DT::renderDataTable(links2)),
      easyClose = TRUE,
      fade = FALSE,
      footer = tagList(
        actionButton(
          "geopage",
          label = "Go to GEO page",
          onclick = paste0('window.open("', url, '", "_blank")'),
          icon = icon("link")
        ),
        actionButton(
          "email",
          label = "Email author for missing data",
          onclick = paste0('location.href="', prep_email(rv$lastgeo), '"'),
          icon = icon("envelope-open-text")
        ),
        actionButton(
          "sheet",
          label = "Spot check for someta",
          icon = icon("feather-alt")
        )
      )
    ))
  })

  # upload to google sheet
  observeEvent(input$submit, {
    sheet_append(
      sheetid,
      data.frame(
        id = rv$lastgeo,
        issc = input$issc,
        hasmeta = input$hasmeta,
        hascellcol = input$hascellcol,
        comment = input$comment
      )
    )
    # print(read_sheet(sheetid, 1))

    showModal(modalDialog(
      div(id = "modaldone", h2("Results uploaded, thank you!")),
      easyClose = TRUE,
      fade = FALSE,
      footer = NULL
    ))
  })

  # disable menu at load
  addCssClass(selector = "a[data-value='clustifyres']", class = "inactiveLink")
  addCssClass(selector = "ul li:eq(4)", class = "inactiveLink")

  addCssClass(selector = "a[data-value='blank']", class = "inactiveLink")
  addCssClass(selector = "ul li:eq(5)", class = "inactiveLink")

  # check if data is loaded
  observeEvent(
    (!is.null(data1())) +
      (!is.null(data2())) +
      (!is.null(data3())) +
      (!is.null(input$metadataCellType)) +
      (input$metadataCellType != ""),
    {
      if (
        (!is.null(data1())) +
          (!is.null(data2())) +
          (!is.null(data3())) +
          (!is.null(input$metadataCellType)) +
          (input$metadataCellType != "") ==
          5
      ) {
        removeCssClass(
          selector = "a[data-value='clustifyres']",
          class = "inactiveLink"
        )
        removeClass(selector = "ul li:eq(4)", class = "inactiveLink")
      }
    }
  )
  observeEvent(data1(), {
    if (!is.null(data1())) {
      addCssClass(selector = "a[data-value='matrixLoad']", class = "doneLink")
      addClass(selector = "ul li:eq(1)", class = "doneLink")
    }
  })

  observeEvent(input$metadataCellType, {
    if (input$metadataCellType != "") {
      addCssClass(selector = "a[data-value='metadataLoad']", class = "doneLink")
      addClass(selector = "ul li:eq(2)", class = "doneLink")
    }
  })

  observeEvent(input[["activeTab"]], {
    if (input[["activeTab"]] == "clusterRef") {
      rv$ref_visited <<- 1
    } else if (input[["activeTab"]] == "clustifyres") {
      if (rv$res_visited == 0) rv$res_visited <<- 1
    }
  })

  observeEvent(rv$ref_visited, {
    if (rv$ref_visited == 1 & !is.null(data3())) {
      addCssClass(selector = "a[data-value='clusterRef']", class = "doneLink")
      addClass(selector = "ul li:eq(3)", class = "doneLink")
    }
  })

  observeEvent(
    rv$res_visited,
    {
      if (rv$res_visited == 1) {
        rv$res_visited <- 2
      }
    },
    ignoreInit = FALSE
  )

  observeEvent(rv$ref_link, {
    runjs(paste0(
      "document.getElementById('ref_linkgo').onclick = function() {
           window.open('",
      rv$ref_link,
      "', '_blank');};"
    ))
  })

  output$someta <- DT::renderDataTable(
    {
      as.data.table(
        someta %>% select(-geo, -pubmed, -pubmed_id),
        rownames = FALSE
      )
    },
    filter = "top",
    selection = list(mode = "single", target = "row"),
    rownames = FALSE,
    options = list(
      autoWidth = TRUE,
      columnDefs = list(
        list(width = '200px', targets = c(0:6)),
        list(
          targets = c(3, 4, 5),
          render = JS(
            "function(data, type, row, meta) {",
            "return type === 'display' && data.length > 100 ?",
            "'<span title=\"' + data + '\">' + data.substr(0, 100) + '...</span>' : data;",
            "}"
          )
        )
      )
    )
  )

  observeEvent(input$someta_cell_clicked, {
    if (length(input$someta_cell_clicked) != 0) {
      sel <- input$someta_cell_clicked
      rv$lastgeo <- someta$id[sel$row]
      w9$show()
      rv$links <- list_geo(rv$lastgeo)
      message(rv$links)
      if (rv$links != "error_get") {
        rv$links2 <- rv$links %>%
          mutate(size = map(link, get_file_size)) %>%
          select(-link)
        links2 <- cbind(
          rv$links2,
          button = sapply(1:nrow(rv$links), make_button("tbl1")),
          stringsAsFactors = FALSE
        ) %>%
          data.table::data.table()
        links2 <- links2 %>%
          DT::datatable(
            options = list(
              dom = "ftp",
              searchHighlight = TRUE,
              paging = TRUE,
              pageLength = 5,
              scrollY = FALSE
            ),
            escape = ncol(links2) - 1,
            fillContainer = TRUE
          )
      } else {
        links2 <- data.frame(rv$links)
      }

      url <- str_c(
        "https://www.ncbi.nlm.nih.gov/geo/query/acc.cgi?acc=",
        rv$lastgeo
      )
      w9$hide()
      showModal(modalDialog(
        size = "l",
        div(id = "modalfiles", DT::renderDataTable(links2)),
        easyClose = TRUE,
        fade = FALSE,
        footer = tagList(
          actionButton(
            "geopage",
            label = "Go to GEO page",
            onclick = paste0('window.open("', url, '", "_blank")'),
            icon = icon("link")
          ),
          actionButton(
            "email",
            label = "Email author for missing data",
            onclick = paste0('location.href="', prep_email(rv$lastgeo), '"'),
            icon = icon("envelope-open-text")
          ),
          actionButton(
            "sheet",
            label = "Spot check for someta",
            icon = icon("feather-alt")
          )
        )
      ))
    }
  })
}
rnabioco/clustifyr documentation built on June 11, 2025, 5:38 a.m.