Skip to content

Commit

Permalink
add extra viz to adress #1. Rework API.
Browse files Browse the repository at this point in the history
  • Loading branch information
DivadNojnarg committed Feb 18, 2022
1 parent 8c88cce commit a2c1c28
Show file tree
Hide file tree
Showing 14 changed files with 383 additions and 67 deletions.
9 changes: 8 additions & 1 deletion NAMESPACE
Original file line number Diff line number Diff line change
@@ -1,22 +1,29 @@
# Generated by roxygen2: do not edit by hand

export("%>%")
export(create_app_daily_usage)
export(create_app_daily_usage_chart)
export(create_app_ranking)
export(create_app_ranking_table)
export(create_apps_consumer_ranking)
export(create_apps_consumer_ranking_chart)
export(create_calendar_chart)
export(create_cumulated_duration_per_user)
export(create_cumulated_hits_per_user)
export(create_dev_project_overview)
export(create_dev_ranking)
export(create_dev_ranking_chart)
export(create_pie_chart)
export(create_rsc_client)
export(create_user_daily_consumption_chart)
export(generate_table)
export(get_app_daily_usage)
export(get_max_rsc_apps_usage)
export(get_rsc_app_dates)
export(get_rsc_apps_usage)
export(get_rsc_developer_apps_count)
export(get_rsc_developer_apps_list)
export(get_user_daily_consumption)
export(merge_rsc_data)
export(process_rsc_content)
export(process_rsc_user)
export(sort_content_by_access)
Expand Down
109 changes: 79 additions & 30 deletions R/helpers-charts.R
Original file line number Diff line number Diff line change
@@ -1,51 +1,80 @@
#' Daily app usage chart
#' Generic calendar chart generator
#'
#' Leverages echarts4r.
#' See \url{https://echarts4r.john-coene.com/articles/chart_types.html#calendar-1}.
#'.
#' @param apps_usage Second element returned by \link{create_app_ranking}.
#' @param selected_app Selected app name (string). You'll need a selectInput for instance.
#' wrapped by \link[shiny]{reactive}.
#' @return A calendar chart displaying daily app usage.
#' @param data Calendar chart data.
#' @param max Maximum value.
#' @param range Date range.
#' @param title Chart title.
#'
#' @return An echarts4r calendar chart
#' @export
#' @importFrom shiny reactive
#' @import echarts4r
#' @importFrom rlang .data
create_app_daily_usage <- function(apps_usage, selected_app) {
create_calendar_chart <- function(data, max, range, title) {

Date <- Freq <- NULL

# Join all data
targeted_rsc_apps_usage <- reactive({
apps_usage %>%
dplyr::filter(.data$app_name == !!selected_app())
})

# Calendar chart
renderEcharts4r({
tmp_app <- targeted_rsc_apps_usage()

calendar_data <- tmp_app[ , "calendar_data"] %>%
tidyr::unnest(cols = c(calendar_data))
max_usage <- max(calendar_data$Freq)
year_range <- c(min(calendar_data$Date), max(calendar_data$Date))

calendar_data %>%
data %>%
e_charts(Date, width = "1200px") %>%
e_calendar(range = year_range) %>%
e_calendar(range = range) %>%
e_effect_scatter(Freq, coord_system = "calendar") %>%
e_visual_map(
max = max_usage,
max = max,
inRange = list(
color = c('#e0f3f8', '#abd9e9', '#74add1', '#4575b4', '#313695')
)
) %>%
e_title(tmp_app$app_name) %>%
e_tooltip()
e_title(title) %>%
e_tooltip() %>%
e_legend(FALSE)
})
}



#' Daily app usage chart
#'
#' Leverages echarts4r.
#' See \url{https://echarts4r.john-coene.com/articles/chart_types.html#calendar-1}.
#'.
#' @param app_usage Returned by \link{get_app_daily_usage}.
#' @return A calendar chart displaying daily app usage.
#' @export
create_app_daily_usage_chart <- function(app_usage) {
create_calendar_chart(
app_usage,
max(app_usage$Freq),
c(min(app_usage$Date), max(app_usage$Date)),
app_usage$app_name
)
}




#' Daily app consumption for selected user
#'
#' @param usage Get from \link{get_user_daily_consumption}.
#'
#' @return An echarts4r calendar chart
#' @export
create_user_daily_consumption_chart <- function(usage) {

data <- usage[[1]]
selected_user <- usage[[2]]

max_usage <- max(data$Freq)
year_range <- c(min(data$Date), max(data$Date))

create_calendar_chart(
data,
max_usage,
year_range,
sprintf("%s overall consumption", selected_user)
)
}



#' Create cumulated app duration/user
#'
#' Bar chart
Expand Down Expand Up @@ -212,6 +241,26 @@ create_dev_project_overview <- function(ranking, client, apps_usage, selected_de



#' Create apps consumer ranking bar chart
#'
#' @param ranking Data obtained from \link{create_apps_consumer_ranking}.
#'
#' @return A bar chart with consumer sorted by descending number of total views.
#' @export
create_apps_consumer_ranking_chart <- function(ranking) {

username <- NULL

ranking %>%
e_charts(username) %>%
e_bar(n) %>%
e_flip_coords() %>%
e_axis_labels(x = "Number of hits", y = "End user") %>%
e_tooltip() %>%
e_legend(FALSE)
}



#' Create standard pie chart
#'
Expand Down
124 changes: 108 additions & 16 deletions R/helpers-data.R
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ get_max_rsc_apps_usage <- function(logs) {
#' Process RSC user
#'
#' Select relevant information for RSC users data. See
#' \link{create_app_ranking}.
#' \link{merge_rsc_data}.
#'
#' @param users Get from \link[connectapi]{get_users}.
#'
Expand All @@ -155,7 +155,7 @@ process_rsc_user <- function(users) {
#' Process RSC content
#'
#' Select relevant information for RSC content data. See
#' \link{create_app_ranking}.
#' \link{merge_rsc_data}.
#'
#' @param content Get from \link[connectapi]{get_content}.
#'
Expand All @@ -175,20 +175,20 @@ process_rsc_content <- function(content) {
}


#' Process app data for ranking table
#' Merge RStudio Connect data together
#'
#' See \link{create_app_ranking_table}.
#' See \link{create_app_ranking}.
#'
#' @param content Get from \link[connectapi]{get_content}.
#' @param users Get from \link[connectapi]{get_users}.
#' @param apps Get from \link[connectapi]{get_usage_shiny}.
#'
#' @return A list containing: `[[1]]` merged data between app usage and users data.
#' `[[2]]`: data to be digested by \link{create_app_ranking_table}.
#' @return A list of 3 tibbles. `[[1]]`: light RSC content data (less columns);
#' `[[2]]`: light RSC users data (less columns); `[[3]]`: merged apps_usage data.
#' @export
#' @import dplyr
#' @importFrom rlang .data
create_app_ranking <- function(content, users, apps) {
merge_rsc_data <- function(content, users, apps) {
rsc_content_light <- process_rsc_content(content)
rsc_users_light <- process_rsc_user(users)

Expand All @@ -199,24 +199,116 @@ create_app_ranking <- function(content, users, apps) {
left_join(rsc_users_light, by = "user_guid") %>%
mutate(duration = .data$ended - .data$started) %>%
select(-.data$content_guid, -.data$user_guid, -.data$data_version) %>%
filter(!is.na(.data$app_name))
filter(!is.na(.data$app_name)) %>%
tidyr::replace_na(list(user_guid = "Unknown"))

list(
rsc_content_light = rsc_content_light,
rsc_users_light = rsc_users_light,
apps_usage_merged = apps_usage_merged
)
}



#' Daily app usage
#'
#' Used by \link{create_app_daily_usage_chart}
#'.
#' @param apps_usage Second element returned by \link{create_app_ranking}.
#' @param selected_app Selected app name (string). You'll need a selectInput for instance.
#' wrapped by \link[shiny]{reactive}.
#' @return Calendar data for daily app usage.
#' @export
#' @importFrom shiny reactive
#' @import dplyr
#' @importFrom rlang .data
get_app_daily_usage <- function(apps_usage, selected_app) {
apps_usage %>%
filter(.data$app_name == selected_app()) %>%
select(.data$calendar_data) %>%
tidyr::unnest(cols = c(.data$calendar_data))
}



#' Get daily shiny app usage for a given user
#'
#' @inheritParams merge_rsc_data
#' @param selected_user User to select.
#' You'll need a selectInput wrapped by \link[shiny]{reactive}.
#'
#' @return 2 columns tibble containing daily app consuption for given user.
#' @export
#' @import dplyr
#' @importFrom rlang .data
get_user_daily_consumption <- function(content, users, apps, selected_user) {
rsc_data_merged <- merge_rsc_data(content, users, apps)

res <- rsc_data_merged[[3]] %>%
filter(.data$username == selected_user()) %>%
mutate(floored_started = lubridate::floor_date(.data$started, "day")) %>%
group_by(.data$floored_started) %>%
summarize(n = n()) %>%
select(Date = .data$floored_started, Freq = .data$n)

list(data = res, user = selected_user())
}


#' Process app data for ranking table
#'
#' See \link{create_app_ranking_table}.
#'
#' @inheritParams merge_rsc_data
#'
#' @return A list containing: `[[1]]` merged data between app usage and users data.
#' `[[2]]`: data to be digested by \link{create_app_ranking_table}.
#' @export
#' @import dplyr
#' @importFrom rlang .data
create_app_ranking <- function(content, users, apps) {

# Some users are not logged and they appear as NAs. Replace
# By unknown to avoid to mess other results.
apps_usage_merged$username <- apps_usage_merged$username %>%
tidyr::replace_na("Unknown")
rsc_data_merged <- merge_rsc_data(content, users, apps)

processed_rsc_apps_usage <- apps_usage_merged %>%
processed_rsc_apps_usage <- rsc_data_merged[[3]] %>%
get_rsc_apps_usage() %>%
left_join(
rsc_content_light %>%
rsc_data_merged[[1]] %>%
mutate(user_guid = .data$owner_guid),
by = "app_name"
) %>%
left_join(rsc_users_light, by = "user_guid") %>%
left_join(rsc_data_merged[[2]], by = "user_guid") %>%
select(-contains("_guid"))

list(apps_usage_merged, processed_rsc_apps_usage)
list(rsc_data_merged[[3]], processed_rsc_apps_usage)
}



#' Create Shiny apps consumer ranking
#'
#' Sort consumers by number of views.
#'
#' @param apps Get from \link[connectapi]{get_usage_shiny}.
#' @param users Get from \link[connectapi]{get_users}.
#' @param threshold Minimum number of views threshold. You'll need a numericInput
#' wrapped by \link[shiny]{reactive}.
#'
#' @return A 3 columns tibble with apps consumer sorted by number of view. The role
#' columns allows further analysis.
#' @export
#' @import dplyr
#' @importFrom rlang .data
create_apps_consumer_ranking <- function(apps, users, threshold) {
apps %>%
group_by(.data$user_guid) %>%
summarise(n = n()) %>% # prefer summarize over sort to remove grouping
arrange(n) %>%
filter(n > threshold()) %>%
left_join(users %>% mutate(user_guid = .data$guid), by = "user_guid") %>%
select(.data$username, .data$n, .data$user_role) %>%
tidyr::replace_na(list(username = "Unknown", user_role = "External"))
}


Expand Down
Loading

0 comments on commit a2c1c28

Please sign in to comment.