| @@ -0,0 +1 @@ | |||
| ^README\.Rmd$ | |||
| @@ -0,0 +1,5 @@ | |||
| .Rproj.user | |||
| .Rhistory | |||
| .RData | |||
| .DS_Store | |||
| */~$* | |||
| @@ -0,0 +1,20 @@ | |||
| --- | |||
| output: github_document | |||
| --- | |||
| <!-- README.md is generated from README.Rmd. Please edit that file --> | |||
| ```{r setup, include = FALSE} | |||
| knitr::opts_chunk$set( | |||
| collapse = TRUE, | |||
| comment = "#>" | |||
| ) | |||
| ``` | |||
| # tinder4cancer | |||
| ## Dependencies | |||
| ```{r} | |||
| devtools::install_github("nstrayer/shinysense") | |||
| ``` | |||
| @@ -0,0 +1,186 @@ | |||
| library(shinysense) | |||
| library(htmlwidgets) | |||
| library(shiny) | |||
| library(dplyr) | |||
| library(shinyjs) | |||
| questions <- readxl::read_xlsx(here::here("docs/questions.xlsx")) %>% | |||
| arrange(order) | |||
| question_itergen <- function(questions) { | |||
| force(questions) | |||
| i <- 0L | |||
| ids <- arrange(questions, order) %>% pull(id) | |||
| function() { | |||
| i <<- i + 1 | |||
| if (i > length(ids)) return(NULL) | |||
| list( | |||
| id = ids[[i]], | |||
| question = filter(questions, id == ids[[i]]) | |||
| ) | |||
| } | |||
| } | |||
| next_question <- question_itergen(questions) | |||
| phone_container <- function(...) { | |||
| div( | |||
| class = "phone-container", | |||
| div( | |||
| class = "marvel-device iphone8plus black", | |||
| div(class = "top-bar"), | |||
| div(class = "sleep"), | |||
| div(class = "volume"), | |||
| div(class = "camera"), | |||
| div(class = "sensor"), | |||
| div(class = "speaker"), | |||
| div(class = "screen", ...), | |||
| div(class = "home"), | |||
| div(class = "bottom-bar") | |||
| ) | |||
| ) | |||
| } | |||
| ui <- fixedPage( | |||
| includeCSS("devices.min.css"), | |||
| includeCSS("t4c.css"), | |||
| includeCSS("animate.css"), | |||
| shinyjs::useShinyjs(), | |||
| tags$link(rel = "stylesheet", type = "text/css", href = "https://fonts.googleapis.com/css?family=IBM+Plex+Sans:100,100i,200,200i,300,300i,400,400i,500,500i,600,600i,700,700i"), | |||
| # h1("A Good Name and Logo"), | |||
| # p("This is a simple demo app..."), | |||
| # hr(), | |||
| p(), | |||
| phone_container( | |||
| div(class = "overlay splash animated", id = "splash-overlay"), | |||
| div( | |||
| id = "app-main", | |||
| class = "app-main animated", | |||
| h1("App Title", class = "app-title"), | |||
| p("Help Text", class = "help-text"), | |||
| shinyswiprUI( | |||
| "card_swipe_ui", | |||
| div(class = "swiperCard-header", | |||
| h4(class = "card-title", | |||
| textOutput("question_category") | |||
| # "Card Title", | |||
| ) | |||
| ), | |||
| div(class = "swiperCard-body", | |||
| # h4("Question title"), | |||
| h4(textOutput("question_topic")), | |||
| p(textOutput("question_text")) | |||
| ) | |||
| ), | |||
| div( | |||
| class = "bottom-help", | |||
| div(class = "bottom-help-left", img(src = "/images/swipe-left.svg", width = "50px"), p("Bad")), | |||
| div(class = "bottom-help-right", img(src = "/images/swipe-right.svg", width = "50px"), p("Okay")), | |||
| div(class = "bottom-help-middle", span("Swipe Card", class = "bottom-help-middle-text")) | |||
| ) | |||
| ) | |||
| ), | |||
| hr(), | |||
| actionButton("toggle_splash", "Toggle Splash"), | |||
| h4("Answer History"), | |||
| dataTableOutput("results_table") | |||
| ) | |||
| server <- function(input, output, session) { | |||
| card_swipe <- callModule(shinyswipr, "card_swipe_ui") | |||
| question_ids <- arrange(questions, order) %>% pull(id) | |||
| # Init outputs | |||
| output$question_text <- renderText({ | |||
| if (!app_data$complete) { | |||
| question()$`Question Text` | |||
| } else { | |||
| "No more questions at this time. Hang on while we crunch the numbers..." | |||
| } | |||
| }) | |||
| output$question_category <- renderText({ | |||
| if (!app_data$complete) { | |||
| question()$Category | |||
| } else { | |||
| "Thank You!" | |||
| } | |||
| }) | |||
| output$question_topic <- renderText({ | |||
| if (!app_data$complete) { | |||
| question()$Topic | |||
| } else { | |||
| "All Done!" | |||
| } | |||
| }) | |||
| output$results_table <- renderDataTable({ | |||
| app_data$results | |||
| }) | |||
| app_data <- reactiveValues( | |||
| iter = 1L, | |||
| results = data_frame(question_id = integer(), swipe = character()), | |||
| complete = FALSE, | |||
| splash = FALSE | |||
| ) | |||
| question <- reactive({ | |||
| if (app_data$iter > length(question_ids)) return(NULL) | |||
| questions %>% | |||
| filter(id == question_ids[[app_data$iter]]) | |||
| }) | |||
| observe({ | |||
| cat("iter:", app_data$iter, "\n") | |||
| cat("ques:", question()$`Question Text`, "\n") | |||
| print(app_data$results) | |||
| }) | |||
| # on swipe | |||
| observeEvent(card_swipe(), { | |||
| if (app_data$complete) { | |||
| cat("\nNothing to do.") | |||
| return() | |||
| } | |||
| # save swipe event | |||
| app_data$results <- bind_rows( | |||
| data_frame( | |||
| question_id = question()$id, | |||
| swipe = card_swipe() | |||
| ), | |||
| app_data$results | |||
| ) | |||
| # update outputs | |||
| app_data$iter <- app_data$iter + 1L | |||
| next_q <- question() | |||
| if (!is.null(next_q)) { | |||
| # output$question_text <- renderText({next_q$`Question Text`}) | |||
| } else { | |||
| # output$question_text <- renderText("No more questions.") | |||
| app_data$complete <- TRUE | |||
| } | |||
| # update results table | |||
| # output$results_table <- renderDataTable({app_data$results}) | |||
| }) | |||
| observeEvent(input$toggle_splash, { | |||
| app_data$splash <- !app_data$splash | |||
| if (app_data$splash) { | |||
| shinyjs::removeClass("splash-overlay", "slideInLeft") | |||
| shinyjs::removeClass("app-main", "slideOutRight") | |||
| shinyjs::addClass("app-main", "slideInRight") | |||
| shinyjs::addClass("splash-overlay", "slideOutLeft") | |||
| } else { | |||
| shinyjs::removeClass("splash-overlay", "slideOutLeft") | |||
| shinyjs::removeClass("app-main", "slideInRight") | |||
| shinyjs::addClass("app-main", "slideOutRight") | |||
| shinyjs::addClass("splash-overlay", "slideInLeft") | |||
| } | |||
| }) | |||
| } | |||
| shinyApp(ui = ui, server = server) | |||
| @@ -0,0 +1,118 @@ | |||
| #card_swipe_ui { | |||
| margin-top: 2em; | |||
| width: 90%; | |||
| } | |||
| .phone-container { | |||
| width: 100% | |||
| } | |||
| .marvel-device { | |||
| margin: 0 auto; | |||
| display: inherit; | |||
| } | |||
| .swiperCard { | |||
| box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2); | |||
| padding: 0px; | |||
| border: 1px solid #ccc; | |||
| border-radius: 0px 0px 5px 5px; | |||
| max-width: 800px; | |||
| margin: 0 auto; | |||
| margin-top: 0px; | |||
| } | |||
| .swiperCard-header { | |||
| } | |||
| .swiperCard-body{ | |||
| margin: 8px; | |||
| } | |||
| .app-main{ | |||
| width: 100%; | |||
| height: 100%; | |||
| } | |||
| .card-title { | |||
| color: white; | |||
| background: #00589a; | |||
| padding: 15px 10px; | |||
| height: 50px; | |||
| margin: 0px; | |||
| font-size: 1.5em; | |||
| margin-bottom: 16px; | |||
| } | |||
| .app-title { | |||
| background: #58b0e3; | |||
| color: white; | |||
| padding: 10px; | |||
| margin-top: 0; | |||
| font-weight: 200; | |||
| font-size: 2em; | |||
| box-shadow: #bec3c3 0px 2px 3px; | |||
| } | |||
| .help-text { | |||
| padding-left: 15px; | |||
| text-align: center; | |||
| padding-top: 30px; | |||
| color: #bec3c3; | |||
| font-weight: 400; | |||
| font-size: 1.25em; | |||
| } | |||
| .screen { | |||
| font-family: IBM Plex Sans; | |||
| } | |||
| .bottom-help { | |||
| display: block; | |||
| position: absolute; | |||
| bottom: 25px; | |||
| width: 90%; | |||
| text-align: center; | |||
| margin-left: 5%; | |||
| color: #bec3c3; | |||
| z-index: -100; | |||
| } | |||
| .bottom-help-left { | |||
| float: left; | |||
| display: inline-block; | |||
| width: 15%; | |||
| } | |||
| .bottom-help-right { | |||
| float: right; | |||
| display: inline-block; | |||
| width: 15%; | |||
| } | |||
| .bottom-help-middle { | |||
| max-width: 70%; | |||
| margin: 0 auto; | |||
| height: 50px; | |||
| } | |||
| .bottom-help-middle-text { | |||
| position: relative; | |||
| top: 60%; | |||
| } | |||
| .bottom-help p { | |||
| margin: 0px; | |||
| } | |||
| .overlay { | |||
| position: absolute; | |||
| z-index: 10000; | |||
| width: 100%; | |||
| height: 100%; | |||
| padding: 15px; | |||
| } | |||
| .overlay.splash { | |||
| background: #00589a; | |||
| color: white; | |||
| vertical-align: middle; | |||
| text-align: center; | |||
| background-image: url("/images/splash-bg.png"); | |||
| background-size: cover; | |||
| } | |||
| @@ -0,0 +1,3 @@ | |||
| <?xml version="1.0" encoding="UTF-8" standalone="no"?> | |||
| <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> | |||
| <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid meet" viewBox="0 0 75 75" width="75" height="75"><defs><path d="M31.59 43.05C21.44 32.9 15.81 27.27 14.68 26.14C12.81 24.27 10.64 23.96 8.22 26.38C5.8 28.8 6.11 30.97 7.98 32.84C9.65 34.51 18 42.86 33.04 57.9" id="bl56seV47"></path><path d="M46.49 33.59C42.84 29.94 40.81 27.91 40.41 27.5C37.84 24.93 35.58 23.89 33.09 25.95C30.97 27.69 30.79 29.42 30.79 29.42" id="k4XD6R1iEb"></path><path d="M39.4 26.5C42.2 22.56 45.11 23.35 48.25 26.11C51.39 28.88 53.07 30.42 56.79 34.14C65.78 43.13 66 53.22 66 53.22" id="cn4DO570E"></path><path d="M22.27 47.7C21.81 47.95 20.68 48.88 19.94 49.62C18.26 51.3 18.32 53.89 20.44 56.52C20.44 56.52 22.57 59.32 25.75 62.6C29.88 66.86 32.49 67.98 36.57 68.72C42.17 69.74 50.7 68.76 50.7 68.76" id="d70HHsoeaD"></path><path d="M38.92 36.98C35.54 33.6 33.66 31.72 33.28 31.34C30.71 28.77 27.71 27.16 25.06 29.81C22.81 32.06 22.3 33.74 22.3 33.74" id="a3WZ9H751S"></path><path d="M61.64 14.81C55.65 9.23 47.63 5.81 38.8 5.81C29.97 5.81 21.95 9.23 15.96 14.81" id="cOYR3g5tN"></path><path d="M21.23 15.2L15.64 15.2L15.64 9.61" id="a1QiD4xZyl"></path></defs><g><g><g><g><use xlink:href="#bl56seV47" opacity="1" fill="#000000" fill-opacity="0"></use><g><use xlink:href="#bl56seV47" opacity="1" fill-opacity="0" stroke="#1a1a1a" stroke-width="2" stroke-opacity="1"></use></g></g><g><use xlink:href="#k4XD6R1iEb" opacity="1" fill="#000000" fill-opacity="0"></use><g><use xlink:href="#k4XD6R1iEb" opacity="1" fill-opacity="0" stroke="#1a1a1a" stroke-width="2" stroke-opacity="1"></use></g></g><g><use xlink:href="#cn4DO570E" opacity="1" fill="#000000" fill-opacity="0"></use><g><use xlink:href="#cn4DO570E" opacity="1" fill-opacity="0" stroke="#1a1a1a" stroke-width="2" stroke-opacity="1"></use></g></g><g><use xlink:href="#d70HHsoeaD" opacity="1" fill="#000000" fill-opacity="0"></use><g><use xlink:href="#d70HHsoeaD" opacity="1" fill-opacity="0" stroke="#1a1a1a" stroke-width="2" stroke-opacity="1"></use></g></g><g><use xlink:href="#a3WZ9H751S" opacity="1" fill="#000000" fill-opacity="0"></use><g><use xlink:href="#a3WZ9H751S" opacity="1" fill-opacity="0" stroke="#1a1a1a" stroke-width="2" stroke-opacity="1"></use></g></g><g><use xlink:href="#cOYR3g5tN" opacity="1" fill="#000000" fill-opacity="0"></use><g><use xlink:href="#cOYR3g5tN" opacity="1" fill-opacity="0" stroke="#4dcbbf" stroke-width="2" stroke-opacity="1"></use></g></g><g><use xlink:href="#a1QiD4xZyl" opacity="1" fill="#000000" fill-opacity="0"></use><g><use xlink:href="#a1QiD4xZyl" opacity="1" fill-opacity="0" stroke="#4dcbbf" stroke-width="2" stroke-opacity="1"></use></g></g></g></g></g></svg> | |||
| @@ -0,0 +1,3 @@ | |||
| <?xml version="1.0" encoding="UTF-8" standalone="no"?> | |||
| <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> | |||
| <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid meet" viewBox="0 0 75 75" width="75" height="75"><defs><path d="M33.13 36.74C43.28 26.59 48.92 20.95 50.05 19.82C51.92 17.95 52.23 15.78 49.81 13.36C47.39 10.95 45.22 11.25 43.35 13.12C41.68 14.79 33.33 23.14 18.29 38.18" id="k3hu8bRdL5"></path><path d="M42.6 51.63C46.25 47.98 48.28 45.96 48.68 45.55C51.25 42.98 52.3 40.73 50.24 38.23C48.49 36.12 46.77 35.93 46.77 35.93" id="d37oXdC3N2"></path><path d="M49.69 44.54C53.62 47.35 52.84 50.26 50.07 53.4C47.31 56.54 45.77 58.21 42.04 61.93C33.06 70.92 22.96 71.15 22.96 71.15" id="edFQlCBJn"></path><path d="M28.49 27.41C28.24 26.95 27.31 25.82 26.57 25.08C24.89 23.4 22.3 23.47 19.67 25.59C19.67 25.59 16.87 27.72 13.59 30.9C9.32 35.02 8.2 37.63 7.46 41.71C6.45 47.31 7.43 55.84 7.43 55.84" id="bdzY5Xr2X"></path><path d="M39.21 44.06C42.59 40.68 44.47 38.8 44.84 38.43C47.42 35.85 49.03 32.85 46.38 30.2C44.13 27.95 42.45 27.44 42.45 27.44" id="c7gPdtof1N"></path><path d="M20.8 12.85C26.79 7.27 34.81 3.85 43.64 3.85C52.47 3.85 60.49 7.27 66.48 12.85" id="eYI8A6gZ8"></path><path d="M61.21 13.24L66.8 13.24L66.8 7.65" id="a3aRPGNoVM"></path></defs><g><g><g><g><use xlink:href="#k3hu8bRdL5" opacity="1" fill="#000000" fill-opacity="0"></use><g><use xlink:href="#k3hu8bRdL5" opacity="1" fill-opacity="0" stroke="#1a1a1a" stroke-width="2" stroke-opacity="1"></use></g></g><g><use xlink:href="#d37oXdC3N2" opacity="1" fill="#000000" fill-opacity="0"></use><g><use xlink:href="#d37oXdC3N2" opacity="1" fill-opacity="0" stroke="#1a1a1a" stroke-width="2" stroke-opacity="1"></use></g></g><g><use xlink:href="#edFQlCBJn" opacity="1" fill="#000000" fill-opacity="0"></use><g><use xlink:href="#edFQlCBJn" opacity="1" fill-opacity="0" stroke="#1a1a1a" stroke-width="2" stroke-opacity="1"></use></g></g><g><use xlink:href="#bdzY5Xr2X" opacity="1" fill="#000000" fill-opacity="0"></use><g><use xlink:href="#bdzY5Xr2X" opacity="1" fill-opacity="0" stroke="#1a1a1a" stroke-width="2" stroke-opacity="1"></use></g></g><g><use xlink:href="#c7gPdtof1N" opacity="1" fill="#000000" fill-opacity="0"></use><g><use xlink:href="#c7gPdtof1N" opacity="1" fill-opacity="0" stroke="#1a1a1a" stroke-width="2" stroke-opacity="1"></use></g></g><g><use xlink:href="#eYI8A6gZ8" opacity="1" fill="#000000" fill-opacity="0"></use><g><use xlink:href="#eYI8A6gZ8" opacity="1" fill-opacity="0" stroke="#4dcbbf" stroke-width="2" stroke-opacity="1"></use></g></g><g><use xlink:href="#a3aRPGNoVM" opacity="1" fill="#000000" fill-opacity="0"></use><g><use xlink:href="#a3aRPGNoVM" opacity="1" fill-opacity="0" stroke="#4dcbbf" stroke-width="2" stroke-opacity="1"></use></g></g></g></g></g></svg> | |||
| @@ -0,0 +1,21 @@ | |||
| Version: 1.0 | |||
| RestoreWorkspace: No | |||
| SaveWorkspace: No | |||
| AlwaysSaveHistory: Default | |||
| EnableCodeIndexing: Yes | |||
| UseSpacesForTab: Yes | |||
| NumSpacesForTab: 2 | |||
| Encoding: UTF-8 | |||
| RnwWeave: Sweave | |||
| LaTeX: pdfLaTeX | |||
| AutoAppendNewline: Yes | |||
| StripTrailingWhitespace: Yes | |||
| BuildType: Package | |||
| PackageUseDevtools: Yes | |||
| PackageInstallArgs: --no-multiarch --with-keep.source | |||
| PackageRoxygenize: rd,collate,namespace | |||