R/report_issue_module.R

Defines functions report_issue_module report_issue_module_dash_ui

Documented in report_issue_module report_issue_module_dash_ui

#' Report Issue Module UI
#'
#' @param id the module ID
#'
#' @export
#'
#' @importFrom shiny NS tags
#' @importFrom shinyFeedback useShinyFeedback
#'
#' @return "Report Issue" button to go in the top bar of a shinydashboard Shiny app.
#'
report_issue_module_dash_ui <- function(id) {
  ns <- shiny::NS(id)

  tags$li(
    class = "dropdown",
    tags$head(shinyFeedback::useShinyFeedback()),
    tags$a(
      id = ns("report_bug"),
      href = "#",
      onclick="return false;",
      tags$div(
        tags$i(
          class = "fa fa-bug"
        ),
        " Report Issue",
        style = "display: inline"
      )
    )
  )
}

#' Report Issue Module Server
#'
#' @param input the Shiny input
#' @param output the Shiny output
#' @param session the Shiny session
#' @param repo the name of the repo to create the issue in.  e.g. "tychobra/lipids_study"
#' @param gh_pat the GitHub PAT
#' @param gcs_bucket_name the Google Cloud Storage bucket name
#' @param assignees optional - character vector of GitHub usernames to assign to the GitHub
#' issue.
#'
#' @export
#'
#' @importFrom gh gh
#' @importFrom jsonlite toJSON
#' @importFrom shiny reactiveVal observeEvent showModal modalDialog modalButton actionButton textInput textAreaInput removeModal
#' @importFrom shinyjs onclick
#' @importFrom shinyFeedback showToast loadingButton resetLoadingButton
#'
#'
report_issue_module <- function(
  input,
  output,
  session,
  repo,
  gh_pat,
  gcs_bucket_name,
  assignees = NULL
) {
  ns <- session$ns

  open_modal <- shiny::reactiveVal(0)
  shinyjs::onclick(
    "report_bug", {
      open_modal(open_modal() + 1)
    }
  )


  shiny::observeEvent(open_modal(), {

    shiny::showModal(
      shiny::modalDialog(
        title = "Report Issue",
        footer = tagList(
          shiny::modalButton("Cancel"),
          shinyFeedback::loadingButton(
            ns("submit_issue"),
            "Submit",
            class = "btn btn-primary",
            style = "color: #FFF; width: 150px;"
          ) %>% shinyjs::disabled()
        ),
        shiny::textInput(
          ns("title"),
          "Title",
          width = "100%"
        ),
        shiny::textAreaInput(
          ns("description"),
          "Description",
          width = "100%",
          height = "200px"
        ),
        shiny::fileInput(
          ns("attachments"),
          "Attachments",
          multiple = TRUE
        )
      )
    )

  }, ignoreInit = TRUE)

  observeEvent(input$title, {
    hold_title <- input$title
    if (is.null(hold_title) || hold_title == "") {
      showFeedbackDanger(
        "title",
        text = "title cannot be empty"
      )
      shinyjs::disable("submit_issue")
    } else {
      hideFeedback("title")
      shinyjs::enable("submit_issue")
    }

  }, ignoreNULL = FALSE)


  observeEvent(input$submit_issue, {
    if (is.null(session$userData$user)) {
      hold_email <- "user not signed in"
    } else {
      hold_email <- session$userData$user()$email
    }

    hold_attachments <- input$attachments
    tryCatch({

      body_list <- list(
        title = input$title,
        body = paste0(
          "Created By: ", hold_email,
          "\n\n",
          input$description
        )
      )

      # use I() so that autounbox will not work (e.g. it will stay as an array even if there is only 1
      # element in the vector)
      body_list$assignees <- I(assignees)

      if (!is.null(hold_attachments)) {
        # upload attachments to Google Cloud Storage and include links to the
        # attachments in the markdown sent with the GitHub Issue
        md_links <- c()
        file_url <- paste0("gh_attachment/", uuid::UUIDgenerate())
        for (i in seq_len(nrow(hold_attachments))) {

          the_row <- hold_attachments[i, ]
          gcs_upload_res <- googleCloudStorageR::gcs_upload(
            file = the_row$datapath,
            bucket = gcs_bucket_name,
            name = file_url,
            predefinedAcl = "publicRead"
          )

          md_links[i] <- paste0("[", the_row$name, "](https://storage.googleapis.com/", gcs_bucket_name, "/", file_url, ")")
        }

        md_links_string <- paste(md_links, collapse = "\n")

        body_list$body <- paste0(body_list$body, "\n\n Attachments: \n", md_links_string)
      }


      body_json <- jsonlite::toJSON(
        body_list,
        auto_unbox = TRUE
      )

      new_issue_res <- gh::gh(
        "POST /repos/{repo}/issues",
        repo = repo,
        .token = gh_pat,
        .send_headers = c(
          Accept = "application/vnd.github.switcheroo-preview+json",
          "Content-Type" = "application/json"
        ),
        charToRaw(body_json)
      )



      shiny::removeModal()

      shinyFeedback::showToast("success", "new issue created")

    }, error = function(err) {

      shinyFeedback::resetLoadingButton("submit_issue")
      msg <- "unable to create issue"
      print(msg)
      print(err)
      shinyFeedback::showToast("error", msg)

      invisible(NULL)
    })



  })

}
emmashea22/shinyIssues documentation built on Dec. 20, 2021, 5:17 a.m.