├── LICENSE ├── .gitignore ├── BioC2020_workshops.xlsx ├── BioC2020_talks_posters.xlsx ├── assessr.Rproj ├── LICENSE.md ├── tour_info.txt ├── README.md └── app.R /LICENSE: -------------------------------------------------------------------------------- 1 | YEAR: 2020 2 | COPYRIGHT HOLDER: Federico Marini 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .Rproj.user 2 | .Rhistory 3 | .RData 4 | .Ruserdata 5 | -------------------------------------------------------------------------------- /BioC2020_workshops.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bioconductor/assessr/devel/BioC2020_workshops.xlsx -------------------------------------------------------------------------------- /BioC2020_talks_posters.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bioconductor/assessr/devel/BioC2020_talks_posters.xlsx -------------------------------------------------------------------------------- /assessr.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | 3 | RestoreWorkspace: Default 4 | SaveWorkspace: Default 5 | AlwaysSaveHistory: Default 6 | 7 | EnableCodeIndexing: Yes 8 | UseSpacesForTab: Yes 9 | NumSpacesForTab: 2 10 | Encoding: UTF-8 11 | 12 | RnwWeave: Sweave 13 | LaTeX: pdfLaTeX 14 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # MIT License 2 | 3 | Copyright (c) 2020 Federico Marini 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /tour_info.txt: -------------------------------------------------------------------------------- 1 | element;intro 2 | #Welcome;Welcome to the interactive tour for assessr! 3 | #DT_abstracts;The main part is occupied here by the main DataTable, where all contributions are displayed. 4 | #submissionType + .selectize-control; Selecting the type of submission, you can choose if you are going to review Workshops or Talks and other contributions type (posters, shiny demos) 5 | #reviewer + .selectize-control; Use this selector to filter only the abstract which are assigned to you. Remember that you must review all the submissions assigned to you for all contribution types, but if you want, you can review also other submissions 6 | #cols_abstract + .selectize-control; Clicking on the elements in this selectize widget, you can edit its looks, by adding/removing/sorting the columns you display - you might want to use a minimal configuration, for example. 7 | #DT_abstracts;If you changed something in the previous widget, see how the aspect of the DT changes. 8 | #DT_abstracts;You can drill down the content of each abstract by clicking on any row of the DT table. Please do so before proceeding. 9 | #session_abstract;See how the content of each contribution are beautified and displayed in the right column of the app 10 | #launch_gform;Importantly: once you are ready to evaluate the contributed session, here's a comfy link for you to evaluate it in the Google Form for this. 11 | #launch_gform;If you click on this, this has a nice side effect: the Id of the contributed session is copied directly to the clipboard, so you can paste it in the Form 12 | #session_abstract;That's pretty much it. Please remember to evaluate all the contributed sessions you are assigned to, and of course to fill in the complete set of info in the evaluation form. 13 | #Thanks;Thank you for taking the tour of assessr! 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | # assessr 5 | 6 | 7 | 8 | 9 | 10 | The `assessr` app can be used to display the contributed poster/talk/workshop sessions submitted for the [Bioconductor 2020](https://bioc2020.bioconductor.org/) conference. 11 | 12 | # Prerequisites 13 | 14 | ## Input file(s) 15 | 16 | Excel files with columns: "Id", "Title", "Description", "Session format", "Track", "Keywords (1-3)", "Link", "First time presenting this?", "Speaker Notes", "Reviewer1", "Reviewer2", "Reviewer3" 17 | 18 | Currently, files `BioC2020_workshops.xlsx` and `BioC2020_talks_posters.xlsx` are used. They contain data about workshops and talks/posters, respectively. 19 | 20 | ## Reviewer's working with the app 21 | 22 | - Select you name in the "Reviewer name" drop-down menu to see all posters assignned to you. 23 | - Click on each poster - the rightmost panel will display the full information about the submission, and the link to a Google form where one can enter evaluations. 24 | 25 | ## Output 26 | 27 | - Google forms for evaluation should be created _a priori_. Examples of forms are: [eRum 2020 - Workshop Sessions Evaluation](https://docs.google.com/forms/d/e/1FAIpQLScTMLTJ1ccfBmjdEPhZfk5CyQwqSAW5AUJyDkFxc7Q9ZW6VPQ/viewform?entry.840333480=), [eRum 2020 - Contributed Sessions Evaluation](https://docs.google.com/forms/d/e/1FAIpQLSezGbJ1JmgOwDI5BLl28gXp3YQfoFXq8GoMon3k9PZcePCF_w/viewform?entry.840333480=) 28 | - `assessr` will pre-populate the forms with the "Id|Title" string. 29 | - Complete your evaluation by submitting the form. 30 | - Return to `assessr` and complete other evaluations assigned to you. 31 | 32 | 33 | # Footnotes 34 | 35 | **Work in progress! The majority of things are hard-coded and need to be manually adjusted.** 36 | -------------------------------------------------------------------------------- /app.R: -------------------------------------------------------------------------------- 1 | library(shiny) 2 | library(shinydashboard) 3 | library(clipr) 4 | library(rintrojs) 5 | library(dplyr) 6 | 7 | # URL(s) to Google Form(s) for Evaluation 8 | # workshop_form <- function(id) { 9 | # paste0("https://docs.google.com/forms/d/e/1FAIpQLScTMLTJ1ccfBmjdEPhZfk5CyQwqSAW5AUJyDkFxc7Q9ZW6VPQ/viewform?usp=pp_url&entry.840333480=", 10 | # id) 11 | # } 12 | # contribution_form <- function(id) { 13 | # paste0("https://docs.google.com/forms/d/e/1FAIpQLSezGbJ1JmgOwDI5BLl28gXp3YQfoFXq8GoMon3k9PZcePCF_w/viewform?usp=pp_url&entry.840333480=", 14 | # id) 15 | # } 16 | 17 | # To pre-populate an element in the evaluation form, drill down to this element 18 | # using Chrome developer tools and get element id as, e.g., name="entry.1845598857" 19 | workshop_form <- function(id) { 20 | paste0("https://docs.google.com/forms/d/e/1FAIpQLSc4iDxze_Xm8cnYuVuMDnR6rVI7kj7gjL8f5ow4hd2zDJk-mw/viewform?usp=pp_url&entry.1845598857=", id) 21 | } 22 | 23 | # Open link in a new window 24 | window_open <- function(form_link) { 25 | paste0("window.open('", form_link, "', '_blank')") 26 | } 27 | # Open link to evaluation table for a given type of evaluation, if multiple 28 | window_open_eval <- function(id, type) { 29 | if (type == "workshop") { 30 | link <- workshop_form(id) 31 | } else if (type == "contribution") { 32 | link <- contribution_form(id) 33 | } 34 | window_open(link) 35 | } 36 | 37 | 38 | # Excel file(s) with session information 39 | workshop_path <- "./Bioc2020 talks and posters review.xlsx" 40 | # contribution_path <- "./BioC2020_talks_posters.xlsx" 41 | # 42 | workshop_table <- readxl::read_excel(workshop_path) 43 | # contribution_table_raw <- readxl::read_excel(contribution_path) 44 | # contribution_table <- contribution_table_raw[!is.na(contribution_table_raw$Id),] 45 | 46 | # Alternatively, read directly from a GSheet that has been shared for view 47 | # library(gsheet) # install.packages("gsheet") 48 | # workshop_table <- gsheet2tbl("https://docs.google.com/spreadsheets/d/1kaYuJKlt7sNSiLumQYnZau5TgTx9W9SkSQsQa8xBCLM/edit?usp=sharing") 49 | # # Remove duplicate submissions, ignoring Timestamp 50 | # workshop_table <- workshop_table[!duplicated(workshop_table[, colnames(workshop_table) != "Timestamp"]), ] 51 | 52 | # Get unique reviewer's names 53 | reviewers_names <- workshop_table %>% dplyr::select(starts_with("Reviewer")) %>% unlist %>% unique() 54 | reviewers_names <- reviewers_names[!is.na(reviewers_names)] # Remove NA reviwers 55 | 56 | # Currently, all columns need to be manually recoded 57 | # colnames(workshop_table) 58 | # Which columns to display 59 | preselected_cols <- c("Name of presenter", 60 | "Affiliation of presenter", 61 | "Title of talk / poster", 62 | "What are you proposing to present?") 63 | # Compact table to display 64 | abstract_table_compact <- workshop_table[, preselected_cols] 65 | 66 | # UI definition ----------------------------------------------------------- 67 | assessr_ui <- shinydashboard::dashboardPage( 68 | skin = "black", 69 | rintrojs::introjsUI(), 70 | # header definition ------------------------------------------------------- 71 | header = shinydashboard::dashboardHeader( 72 | title = "assessr - BioC2020", 73 | titleWidth = 350 74 | ), 75 | 76 | # sidebar definition ------------------------------------------------------ 77 | sidebar = shinydashboard::dashboardSidebar( 78 | width = 250, 79 | shinydashboard::menuItem( 80 | text = "Sessions Settings", icon = icon("cog"), 81 | startExpanded = TRUE, 82 | selectInput( 83 | inputId = "submissionType", 84 | label = "Type of contribution", 85 | # choices = c("Workshops" = "workshop", "Talks and other sessions" = "contribution"), 86 | choices = c("Abstracts" = "workshop"), 87 | selected = "Abstracts", 88 | multiple = FALSE 89 | ), 90 | selectInput( 91 | inputId = "cols_abstract", 92 | label = "Columns to display", 93 | choices = colnames(workshop_table), 94 | selected = preselected_cols, 95 | multiple = TRUE 96 | ), 97 | selectInput( 98 | inputId = "reviewer", 99 | label = "Reviewer name", 100 | choices = c("All", reviewers_names), 101 | selected = "All", 102 | multiple = FALSE 103 | ), 104 | 105 | actionButton( 106 | inputId = "tour_assessr", 107 | icon = icon("question-circle"), 108 | label = "How does assessr work?", 109 | class = "btn-info" 110 | ), 111 | HTML("") 112 | ) 113 | ), 114 | 115 | # body definition --------------------------------------------------------- 116 | body = shinydashboard::dashboardBody( 117 | id = "main-app", 118 | 119 | fluidRow( 120 | column( 121 | width = 6, 122 | DT::dataTableOutput("DT_abstracts") 123 | ), 124 | column( 125 | width = 6, 126 | hr(), 127 | uiOutput("session_abstract") 128 | ) 129 | ) 130 | ) 131 | ) 132 | 133 | # Server definition ------------------------------------------------------- 134 | assessr_server <- function(input, output, session) { 135 | abstract_table <- reactive({ 136 | message("input$submissionType: ", input$submissionType) 137 | if (input$submissionType == "workshop") { 138 | abstract_t <- workshop_table 139 | } else if (input$submissionType == "contribution") { 140 | abstract_t <- contribution_table 141 | } 142 | abstract_t 143 | }) 144 | 145 | current_dt <- reactive({ 146 | message("input$reviewer: ", input$reviewer) 147 | # ToDo: Automate reviewers column selection 148 | mydt <- abstract_table()[abstract_table()$`Reviewer 1` %in% input$reviewer | 149 | abstract_table()$`Reviewer 2` %in% input$reviewer | 150 | abstract_table()$`Reviewer 3` %in% input$reviewer | 151 | abstract_table()$`Reviewer 4` %in% input$reviewer | 152 | abstract_table()$`Reviewer 5` %in% input$reviewer | 153 | abstract_table()$`Reviewer 6` %in% input$reviewer | 154 | abstract_table()$`Reviewer 7` %in% input$reviewer | 155 | abstract_table()$`Reviewer 8` %in% input$reviewer | 156 | abstract_table()$`Reviewer 9` %in% input$reviewer | 157 | abstract_table()$`Reviewer 10` %in% input$reviewer | 158 | abstract_table()$`Reviewer 11` %in% input$reviewer | 159 | abstract_table()$`Reviewer 12` %in% input$reviewer | 160 | "All" %in% input$reviewer, 161 | union(input$cols_abstract, "Timestamp")] 162 | return(mydt) 163 | }) 164 | 165 | output$session_abstract <- renderUI({ 166 | s <- input$DT_abstracts_rows_selected 167 | if(length(s) == 0) 168 | return(h3("Select an abstract from the table to display the full info")) 169 | 170 | search_id <- current_dt()[s, ]$Timestamp 171 | this_submission <- abstract_table()[abstract_table()$Timestamp == search_id, ] 172 | this_id <- this_submission$Timestamp 173 | this_title <- this_submission$`Title of talk / poster` 174 | this_authors <- this_submission$`List of authors` 175 | this_abstract <- this_submission$`Abstract (up to 300 words)` 176 | this_format <- this_submission$`What are you proposing to present?` 177 | this_keywords <- this_submission$`Keywords (up to 5, comma-separated)` 178 | this_link <- this_submission$`If you are presenting an R/Bioconductor package, please provide a URL to the package.` 179 | 180 | # form_id: 181 | s <- input$DT_abstracts_rows_selected 182 | if(length(s) == 0) 183 | return(NULL) 184 | 185 | this_submission <- current_dt()[s, ] 186 | this_author <- this_submission$`Name of presenter` 187 | this_title <- this_submission$`Title of talk / poster` 188 | 189 | form_id <- gsub( "'", "", paste(this_author, this_title, sep = "|")) 190 | 191 | message("type: ", input$submissionType) 192 | message("form_id(): ", form_id) 193 | 194 | return( 195 | tagList( 196 | h3("Title: "), 197 | tags$b(h2(this_title)), 198 | h4("Contribution identifier: "), 199 | tags$p(paste(this_author, this_title, sep = "|")), 200 | h3("Abstract: "), 201 | tags$p(this_abstract), 202 | h3("Format:"), 203 | p(this_format), 204 | h3("Keywords:"), 205 | tags$b(this_keywords), 206 | h3("Link:"), 207 | p(this_link), 208 | 209 | shiny::actionButton( 210 | inputId = "launch_gform", label = "Open the Google Form to insert your evaluation", 211 | icon = icon("database"), 212 | onclick =window_open_eval(form_id, input$submissionType), 213 | class = "btn-success" 214 | ) 215 | ) 216 | ) 217 | }) 218 | 219 | output$DT_abstracts <- DT::renderDataTable({ 220 | DT::datatable( 221 | current_dt(), 222 | style = "bootstrap", 223 | rownames = FALSE, 224 | filter = "top", 225 | selection = list(mode = "single"), 226 | options = list( 227 | scrollX = TRUE, 228 | pageLength = 5, 229 | lengthMenu = c(5, 10, 25, 50, 100, nrow(current_dt())) 230 | ) 231 | ) 232 | }) 233 | 234 | observeEvent(input$tour_assessr, { 235 | tour <- read.delim("tour_info.txt", 236 | sep = ";", stringsAsFactors = FALSE, 237 | row.names = NULL, quote = "") 238 | rintrojs::introjs(session, options = list(steps = tour)) 239 | }) 240 | 241 | } 242 | 243 | shinyApp(ui = assessr_ui, server = assessr_server) 244 | 245 | --------------------------------------------------------------------------------