diff --git a/DESCRIPTION b/DESCRIPTION index 0010a9e..7e093a7 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: requal Title: Shiny Application for Computer-Assisted Qualitative Data Analysis -Version: 0.5.3 +Version: 0.5.4 Authors@R: c( person(given = "Radim", diff --git a/R/app_ui.R b/R/app_ui.R index eaa870b..b90fa77 100644 --- a/R/app_ui.R +++ b/R/app_ui.R @@ -18,7 +18,7 @@ app_ui <- function(request) { tags$li(mod_user_ui("user_ui_1")) %>% tagAppendAttributes(class = "dropdown"), controlbarIcon = icon("ellipsis-v", id = "launchpad_icon"), - dropdownBlock( + dropdownBlock2( id = "btn-memo", badgeStatus = NULL, icon = shiny::icon("sticky-note-o", verify_fa = FALSE), diff --git a/R/db_logging.R b/R/db_logging.R index 399e5ea..8ee6d97 100644 --- a/R/db_logging.R +++ b/R/db_logging.R @@ -125,3 +125,23 @@ log_delete_category_code_record <- function(con, project_id, df){ data = df) } +log_add_memo_record <- function(con, project_id, df){ + log_action(con, + project_id = project_id, + action = "Add memo", + data = df) +} + +log_update_memo_record <- function(con, project_id, df){ + log_action(con, + project_id = project_id, + action = "Update memo", + data = df) +} + +log_delete_memo_record <- function(con, project_id, memo_id){ + log_action(con, + project_id, + action = "Delete memo", + data = list(memo_id = memo_id)) +} diff --git a/R/mod_memo.R b/R/mod_memo.R index 101c9fd..b299ef7 100644 --- a/R/mod_memo.R +++ b/R/mod_memo.R @@ -9,10 +9,12 @@ #' @importFrom shiny NS tagList mod_memo_ui <- function(id) { ns <- NS(id) - - - uiOutput(ns("memo")) - +div( + tags$b("Memos"), + uiOutput(ns("new_memo_btn")) %>% tagAppendAttributes(style="display: inline-block; float: right"), + hr(), + DT::dataTableOutput(ns("memo")) +) %>% tagAppendAttributes(class = "scrollable80") } @@ -26,21 +28,27 @@ mod_memo_server <- function(id, project) { memo_list <- reactiveVal() observeEvent(project()$active_project, { memo_list(list_memo_records(project)) + output$new_memo_btn <- renderUI({ + actionButton(ns("new_memo"), "New memo") + }) }) - output$memo <- renderUI({ + + output$memo <- DT::renderDataTable({ - if (isTruthy(project()$active_project)) { - tagList( - tags$b("Memos"), - actionButton(ns("new_memo"), "New memo", style="display: inline-block; float: right"), - hr(), - render_memos(id, memo_list()) - ) - } else { - "No active project." - } + DT::datatable(req(memo_list()) %>% + dplyr::arrange(desc(memo_id)) %>% + dplyr::mutate(memo_name = memo_link(memo_id, memo_name)) %>% + dplyr::select(memo_name), options = memo_table_options(), + class = "compact", + escape = FALSE, + rownames = FALSE, + colnames = NULL, + selection = "none") + + + }) @@ -53,15 +61,16 @@ mod_memo_server <- function(id, project) { title = "New memo", textAreaInput(ns("memo_text"), "Text", - value = "", width = "100%" - ), + value = "", width = "100%", height = "100%", + placeholder = "First 50 characters of the first line will become a searchable title..." + ) %>% tagAppendAttributes(style = "height: 50vh"), footer = tagList( modalButton("Cancel"), actionButton(ns("save_close"), "Save & Close") ) - ) + ) ) }) @@ -87,8 +96,9 @@ mod_memo_server <- function(id, project) { textAreaInput(ns("displayed_memo_text"), "Text", value = read_memo_db(project, input$selected_memo), - width = "100%" - ), + width = "100%", height = "100%", + placeholder = "First 50 characters of the first line will become a searchable title..." + ) %>% tagAppendAttributes(style = "height: 50vh"), footer = tagList( modalButton("Close"), @@ -96,7 +106,7 @@ mod_memo_server <- function(id, project) { actionButton(ns("delete_memo"), "Delete", class = "btn-danger") ) - ) + ) ) }) diff --git a/R/mod_memo_utils_memo.R b/R/mod_memo_utils_memo.R index ce580da..03693c0 100644 --- a/R/mod_memo_utils_memo.R +++ b/R/mod_memo_utils_memo.R @@ -15,8 +15,9 @@ list_memo_records <- function(project) { memo_id, memo_name = text ) %>% - dplyr::mutate(memo_name = substr(memo_name, 1, 25)) %>% - dplyr::collect() + dplyr::collect() %>% + dplyr::mutate(memo_name = substr(stringr::str_extract(memo_name, "\\A.*"), 1, 50)) + return(memos_df) } @@ -33,6 +34,14 @@ add_memo_record <- function(project, text) { text = text) res <- DBI::dbWriteTable(con, "memos", memo_df, append = TRUE) + if(res){ + memo_id <- dplyr::tbl(con, "memos") %>% + dplyr::filter(.data$project_id == !!memo_df$project_id, + .data$text == !!memo_df$text) %>% + dplyr::pull(memo_id) + log_add_memo_record(con, memo_df$project_id, memo_df %>% + dplyr::mutate(memo_id = memo_id)) + } } # render memos ----- @@ -84,6 +93,10 @@ update_memo_record <- function(project, memo_id, memo_text) { res <- DBI::dbSendStatement(con, update_memo_sql) DBI::dbClearResult(res) + project_id <- project()$active_project + log_update_memo_record(con, project_id, + data.frame(memo_id = memo_id, text = memo_text)) + } # delete memo record ----- @@ -101,4 +114,55 @@ delete_memo_record <- function(project, memo_id) { res <- DBI::dbSendStatement(con, delete_memo_sql) DBI::dbClearResult(res) -} \ No newline at end of file + log_delete_memo_record(con, project()$active_project, memo_id) + +} + + +# dropdown2 function ---- + +dropdownBlock2 <- function (..., id, icon = NULL, title = NULL, badgeStatus = "danger") +{ + if (!is.null(badgeStatus)) + validateStatus(badgeStatus) + items <- c(list(...)) + dropdownClass <- paste0("dropdown") + numItems <- length(items) + if (is.null(badgeStatus)) { + badge <- NULL + } + else { + badge <- dashboardLabel(status = badgeStatus, numItems) + } + shiny::tags$li(class = dropdownClass, id = id, shiny::tags$a(href = "#", + class = "dropdown-toggle", + `data-toggle` = "dropdown", + icon, + title, + badge), + shiny::tags$ul(class = "dropdown-menu", + style = "left: 0; right: auto; max-height: 80vh", + shiny::tags$li(shiny::tags$ul(class = "menu", + shiny::tags$div(style = "margin-left: auto; margin-right: 0; width: 80%;", + items))))) +} + +# memo table styling ---- + + +memo_table_options <- function() { + list( + dom = 'lfrtp', + #Bfrtip + pageLength = 20, + searching = TRUE, + lengthChange = FALSE + ) +} + +# create memo as link ---- +memo_link <- function(id, text) { + js_fun <- "Shiny.setInputValue('memo_ui_1-selected_memo', this.name, {priority: 'event'});" + quote_sign <- '"' + paste0('', text, '') +}