-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from nhsbsa-data-analytics/improvements
Improvements + deletion of some files
- Loading branch information
Showing
10 changed files
with
154 additions
and
130 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
linters: with_defaults(line_length_linter(90)) | ||
linters: linters_with_defaults (line_length_linter(90)) | ||
exclude: "# Exclude Linting" | ||
exclude_start: "# Begin Exclude Linting" | ||
exclude_end: "# End Exclude Linting" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,10 @@ | ||
|
||
#' Add user tracking | ||
#' | ||
#' Log session ID, username (only for Private apps), session start, end and | ||
#' duration to a Google sheet. | ||
#' | ||
#' @param google_email Email used for Google account username. | ||
#' @param sheet_id Google sheet ID. | ||
#' @param columns Which columns to record, from id, username, login, logout and | ||
#' duration. By default all will be recorded. | ||
#' @param session Shiny session object. | ||
#' | ||
#' @return Nothing; used for side effect. | ||
|
@@ -18,53 +17,117 @@ | |
#' ui <- fluidPage() | ||
#' server <- function(input, output, session) { | ||
#' shinyusertracking::set_user_tracking( | ||
#' "[email protected]", | ||
#' "1234567890987654321", | ||
#' c("login", "logout", "duration"), | ||
#' session | ||
#' ) | ||
#' } | ||
#' | ||
#' shinyApp(ui, server) | ||
#' } | ||
#' | ||
set_user_tracking <- function(google_email, sheet_id, session) { | ||
if (sheet_id == "") { | ||
return(invisible()) | ||
set_user_tracking <- function(columns = NULL, session) { | ||
known_cols <- c( | ||
"id", | ||
"username", | ||
"login", | ||
"logout", | ||
"duration" | ||
) | ||
|
||
if (is.null(columns)) { | ||
columns <- known_cols | ||
} else { | ||
stopifnot({ | ||
columns %in% known_cols | ||
}) | ||
} | ||
|
||
eval_lines(".google-sheets-credentials") | ||
|
||
google_email <- NULL | ||
sheet_id <- NULL | ||
|
||
try({ | ||
google_email <- get("GOOGLE_SHEET_USER") | ||
}) | ||
try({ | ||
sheet_id <- get("GOOGLE_SHEET_ID") | ||
}) | ||
|
||
if (is.null(google_email) || is.null(sheet_id)) { | ||
warning( | ||
"Credentials missing for shinyusertracking::set_user_tracking", | ||
call. = FALSE | ||
) | ||
return() | ||
} | ||
|
||
googlesheets4::gs4_auth( | ||
email = google_email, | ||
cache = ".secret/" | ||
) | ||
|
||
shiny::isolate({ | ||
userdata <<- userdata <- data.frame( # Exclude Linting | ||
id = session$token, | ||
username = ifelse(is.null(session$user), "unknown", session$user), | ||
login = Sys.time(), | ||
logout = lubridate::NA_POSIXct_, | ||
duration = NA_character_ | ||
) | ||
}) | ||
session$userData$tracking <- data.frame( | ||
id = session$token, | ||
username = ifelse(is.null(session$user), "unknown", session$user), | ||
login = Sys.time(), | ||
logout = lubridate::NA_POSIXct_, | ||
duration = NA_character_ | ||
) | ||
|
||
session$onSessionEnded(function() { | ||
shiny::isolate({ | ||
userdata[userdata$id == session$token, "logout"] <- Sys.time() | ||
userdata[userdata$id == session$token, "duration"] <- as.character( | ||
hms::hms( | ||
round( | ||
lubridate::as.period( | ||
userdata[userdata$id == session$token, "logout"] - | ||
userdata[userdata$id == session$token, "login"], | ||
"seconds" | ||
) | ||
) | ||
) | ||
) | ||
session$userData$tracking$logout <- Sys.time() | ||
|
||
googlesheets4::sheet_append(sheet_id, userdata) | ||
}) | ||
duration <- difftime( | ||
session$userData$tracking$logout, | ||
session$userData$tracking$login, | ||
units = "secs" | ||
) | ||
duration <- abs(as.numeric(duration)) | ||
duration <- sprintf( | ||
"%02d:%02d:%02d", # hh:mm:ss | ||
duration %/% 3600, # whole hours (could be > 24) | ||
duration %% 3600 %/% 60, # whole minutes left | ||
duration %% 60 %/% 1 + round(duration %% 60 %% 1) # rounded seconds left | ||
) | ||
|
||
session$userData$tracking$duration <- as.character(duration) | ||
|
||
googlesheets4::sheet_append( | ||
sheet_id, | ||
subset(session$userData$tracking, select = columns) | ||
) | ||
}) | ||
} | ||
|
||
|
||
#' Evaluate each line of plain text file | ||
#' | ||
#' Reads a plain text file line by line, evaluating each line. Useful for | ||
#' creating variables dynamically, e.g. reading in parameters. | ||
#' | ||
#' @param filepath Filepath as a String. | ||
#' @param envir Environment to evaluate in. Default is calling environment. | ||
#' | ||
#' @return Nothing | ||
#' | ||
#' @examples | ||
#' \dontrun{ | ||
#' filepath <- tempfile() | ||
#' writeLines( | ||
#' text = "LEFT = \"right\"", | ||
#' con = filepath | ||
#' ) | ||
#' eval_lines(filepath) | ||
#' print(LEFT) | ||
#' unlink(filepath) # delete temporary file | ||
#' rm(left) # remove example variable | ||
#' } | ||
eval_lines <- function(filepath, envir = parent.frame()) { | ||
con <- file(filepath, open = "r") | ||
on.exit(close(con)) | ||
|
||
invisible() | ||
while (length(line <- readLines(con, n = 1, warn = FALSE)) > 0) { | ||
eval(parse(text = line), envir = envir) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,7 +2,6 @@ | |
# shinyusertracking | ||
|
||
<!-- badges: start --> | ||
[![Codecov test coverage](https://codecov.io/gh/MarkMc1089/shinyusertracking/branch/master/graph/badge.svg)](https://app.codecov.io/gh/MarkMc1089/shinyusertracking?branch=master) | ||
[![R-CMD-check](https://github.com/MarkMc1089/shinyusertracking/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/MarkMc1089/shinyusertracking/actions/workflows/R-CMD-check.yaml) | ||
<!-- badges: end --> | ||
|
||
|
@@ -19,7 +18,7 @@ devtools::install_github("nhsbsa-data-analytics/shinyusertracking") | |
|
||
## Example | ||
|
||
Just add the function at the top of your `server` code. You will need to provide the ID of a Google Sheet and the username (email) of the Google account it is in. | ||
Just add the function at the top of your `server` code. You will need to provide the ID of a Google Sheet and the username (email) of the Google account it is in. | ||
|
||
``` r | ||
library(shiny) | ||
|
@@ -28,11 +27,26 @@ ui <- fluidPage() | |
|
||
server <- function(input, output, session) { | ||
shinyusertracking::set_user_tracking( | ||
"[email protected]", | ||
"1234567890987654321", | ||
session | ||
) | ||
} | ||
|
||
shinyApp(ui, server) | ||
``` | ||
|
||
Optionally, you can choose to log specific columns only. | ||
|
||
Column|Description | ||
:---:|:---: | ||
id|The Shiny session ID | ||
username|The username of user, if available (`null` if app is public) | ||
login|Timestamp of session start | ||
logout|Timestamp of session end | ||
duration|Duration of session in `hh:mm:ss` format | ||
|
||
``` r | ||
shinyusertracking::set_user_tracking( | ||
columns = c("login", "logout", "duration"), | ||
session | ||
) | ||
``` |
This file was deleted.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.