Skip to content
Merged
Show file tree
Hide file tree
Changes from 36 commits
Commits
Show all changes
95 commits
Select commit Hold shift + click to select a range
10d6751
created animint2pages()
Faye-yufan Jul 13, 2023
b70ae59
update to post files path
Faye-yufan Jul 21, 2023
5bffa3f
GH pages is fine with nested file structure
Faye-yufan Jul 24, 2023
1a980fd
Update NAMESPACE
Faye-yufan Jul 25, 2023
7ec1334
Update DESCRIPTION
Faye-yufan Jul 26, 2023
885a1f0
Merge branch '84-move-gallery-from-blocks-to-gh-pages' of https://git…
Faye-yufan Jul 26, 2023
b660d21
use `git2r::cred_token()` for gh authentication
Faye-yufan Jul 26, 2023
cbc942c
Error in 'git2r_branch_create': 'commit' must be an S3 class git_commit
Faye-yufan Jul 26, 2023
bbdeeb6
Create test-compiler-ghpages.R
Faye-yufan Jul 27, 2023
4232198
Merge branch '84-move-gallery-from-blocks-to-gh-pages' of https://git…
Faye-yufan Jul 28, 2023
2b20045
Check if there are any commits in the repo
Faye-yufan Aug 1, 2023
07967fe
use `gert` package and HTTPS protocal
Faye-yufan Sep 1, 2023
d2497df
remove some weird spaces
Faye-yufan Sep 1, 2023
1e71068
Test: Reorder 'Collate' in DESCRIPTION to debug remote installation i…
Faye-yufan Sep 1, 2023
b6675eb
add function documentation
Faye-yufan Sep 2, 2023
1d888e3
Add error message for missing GitHub token to include detailed setup …
Faye-yufan Sep 12, 2023
e738e8f
Add test for error message
Faye-yufan Sep 12, 2023
d71f928
Merge branch 'master' of https://github.com/tdhock/animint2 into 84-m…
Faye-yufan Sep 15, 2023
99f18cc
combine whoami and gitcreds_get()
Faye-yufan Sep 17, 2023
96dc8cf
use gitcreds_get(), cuz gh_whoami() doesn't raise error
Faye-yufan Sep 17, 2023
6ccc1df
move unit test
Faye-yufan Oct 13, 2023
661b6a7
update plot.list
Faye-yufan Oct 13, 2023
e07e137
Dynamically identify the active Git branch
Faye-yufan Oct 13, 2023
e2cc27d
Add man/animint2pages.Rd and update test case
Faye-yufan Oct 13, 2023
d01b457
Update logic of identifying the active branch
Faye-yufan Oct 13, 2023
a694218
source option saved to plot.json and displayed below viz
tdhock Oct 27, 2023
7d26efb
bugfix when git_branch returns character
tdhock Oct 27, 2023
c1a4fa9
add viz url into README.md
Faye-yufan Oct 28, 2023
15a7067
raise error if input `github_repo` contains "/" forward slash
Faye-yufan Oct 28, 2023
0fb6fc9
stop if required_opts not present
tdhock Oct 28, 2023
54355b9
version++
tdhock Oct 28, 2023
2c04fbf
fix typo
tdhock Oct 28, 2023
9395b1c
provide header engine
tdhock Oct 28, 2023
26e6713
ignore readme_website
tdhock Oct 28, 2023
a4f66e3
reformat tryCatch, 1 line string for easier translation
tdhock Nov 1, 2023
a123196
replace `git2r::commits` with `gert::git_log`
Faye-yufan Nov 1, 2023
f41c1bf
delete animint2gist, and run `roxygen2::roxygenise()`
Faye-yufan Nov 1, 2023
0f469f5
Merge branch '84-move-gallery-from-blocks-to-gh-pages' of https://git…
Faye-yufan Nov 1, 2023
24f37f8
add update_gallery fun
tdhock Nov 1, 2023
7d90528
Merge branch '84-move-gallery-from-blocks-to-gh-pages' of github.com:…
tdhock Nov 1, 2023
4bd9344
get_repo_row->get_pages_info
tdhock Nov 1, 2023
2d305ee
link gallery
tdhock Nov 1, 2023
e474342
Merge branch 'master' into 84-move-gallery-from-blocks-to-gh-pages
tdhock Nov 1, 2023
717cab6
fix pages tests
tdhock Nov 2, 2023
438763e
Merge branch '84-move-gallery-from-blocks-to-gh-pages' of github.com:…
tdhock Nov 2, 2023
4701098
line breaks in docs
tdhock Nov 2, 2023
500392e
rm commented code with empty href to fix CRAN check warning about ins…
tdhock Nov 2, 2023
274e199
rm plot arg from docs
tdhock Nov 2, 2023
439be01
rm ghpages test on CRAN
tdhock Nov 2, 2023
631ccb2
do not include vignette on CRAN to save disk space
tdhock Nov 2, 2023
8ef8577
remove aes_q NULL test which was failing on CRAN
tdhock Nov 2, 2023
ac41dfe
\itemize->\describe
tdhock Nov 2, 2023
8ff04ca
rm gist test
tdhock Nov 2, 2023
610cab3
do not include VignetteBuilder on CRAN
tdhock Nov 2, 2023
25e6596
fix skip tests
tdhock Nov 2, 2023
02027e2
set user name and email before running tests
tdhock Nov 2, 2023
4962559
test owner=animint, repo=animint/animint2pages_test_repo
Faye-yufan Nov 4, 2023
7c1186c
new setting not working, change token to the previous one
Faye-yufan Nov 4, 2023
38776ad
expect geom_text color
tdhock Nov 5, 2023
56a3583
fix geom text
tdhock Nov 5, 2023
48a4296
bugfix geom_text
tdhock Nov 5, 2023
cbdabd1
text color tests
tdhock Nov 5, 2023
f922021
specify columns in meta
tdhock Nov 5, 2023
fb65ff8
use get_fill in get_fill_off
tdhock Nov 6, 2023
a11d1d2
remove typo
tdhock Nov 12, 2023
2698902
reformat line breaks
tdhock Nov 12, 2023
c71b8ff
comment
tdhock Nov 12, 2023
1fde9d2
range_is_zero helper
tdhock Nov 12, 2023
9cfe4d4
rm sqrt y example
tdhock Nov 12, 2023
7b6066a
typo
tdhock Nov 12, 2023
e8bfa46
clarify geom_text fix
tdhock Nov 12, 2023
893788b
clarify gallery input/output
tdhock Nov 12, 2023
9cc8788
big re-organization
tdhock Nov 12, 2023
b4eed26
fix scales
tdhock Nov 12, 2023
6f91b76
bugfix geom_point stroke param
tdhock Nov 13, 2023
ff7cdaa
bugfix for geom_point with aes(color) and param fill
tdhock Nov 13, 2023
a260b8c
fix text size, angle, stroke
tdhock Nov 13, 2023
84a1d3b
fix global variables and polygon drawing
tdhock Nov 13, 2023
ed3c140
rm _stroke
tdhock Nov 13, 2023
493fc83
print diff.vars
tdhock Nov 13, 2023
f0b90c9
more prints
tdhock Nov 13, 2023
51f95ef
d is local
tdhock Nov 13, 2023
ec0641e
set defaults after geom specific code
tdhock Nov 14, 2023
325ec99
change && to || to fix point fill
tdhock Nov 14, 2023
e0e6bbd
tile color/stroke transparent by default
tdhock Nov 14, 2023
5fb272f
text fill comes from colour
tdhock Nov 14, 2023
06492f2
use getHTML
tdhock Nov 14, 2023
f479795
move expect_warning to next test
tdhock Nov 14, 2023
151e25e
fix off tests
tdhock Nov 15, 2023
1d9f795
fix default alpha_off
tdhock Nov 15, 2023
4180b88
fix tests
tdhock Nov 15, 2023
c5efbaa
fix tests
tdhock Nov 15, 2023
42b0271
version++
tdhock Nov 15, 2023
47c9f1b
get_alpha_off same as alpha when aes is set
tdhock Nov 15, 2023
fb8f297
commit repos.txt
tdhock Nov 16, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .Rbuildignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
readme_website.md
.github
^.*\.Rproj$
^\.Rproj\.user$
Expand Down
5 changes: 4 additions & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package: animint2
Title: Animated Interactive Grammar of Graphics
Version: 2023.6.11
Version: 2023.10.27
URL: https://animint.github.io/animint2/
BugReports: https://github.com/animint/animint2/issues
Authors@R: c(
Expand Down Expand Up @@ -76,6 +76,7 @@ Imports:
methods
Suggests:
servr,
gert, gitcreds, gh,
sp,
gistr (>= 0.2),
shiny,
Expand Down Expand Up @@ -272,9 +273,11 @@ Collate:
'z_gist.R'
'z_helperFunctions.R'
'z_knitr.R'
'z_pages.R'
'z_print.R'
'z_scales.R'
'z_theme_animint.R'
'z_transformShape.R'
RoxygenNote: 7.2.3
Config/Needs/website: tidyverse/tidytemplate
VignetteBuilder: knitr
2 changes: 2 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ export(alpha)
export(animint)
export(animint2dir)
export(animint2gist)
export(animint2pages)
export(animintOutput)
export(annotate)
export(annotation_custom)
Expand Down Expand Up @@ -489,6 +490,7 @@ export(theme_void)
export(toRGB)
export(transform_position)
export(unit)
export(update_gallery)
export(update_geom_defaults)
export(update_labels)
export(update_stat_defaults)
Expand Down
11 changes: 10 additions & 1 deletion NEWS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
# Changes in 2023.10.27

- New function `animint2pages(viz,"new_github_repo")` for
publishing/sharing animints, replacement for animint2gist, which
stopped working recently.
- New option `animint(source="http://path.to/source.R")` which should
be the URL of data viz source code, used to display a link at the
below the rendered viz.

# Changes in 2023.6.11

- Remove maptools dependency.
Expand Down Expand Up @@ -92,4 +101,4 @@

# Changes in 2017.08.24

- DSL: clickSelects/showSelected are now specified as parameters rather than aesthetics.
- DSL: clickSelects/showSelected are now specified as parameters rather than aesthetics.
8 changes: 6 additions & 2 deletions R/z_animint.R
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,10 @@ animint2dir <- function(plot.list, out.dir = NULL,
if(!is.null(plot.list$out.dir)){
plot.list$out.dir <- NULL
}
if(is.character(plot.list[["source"]])){
meta$source <- plot.list[["source"]]
plot.list$source <- NULL
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this allows the user to specify source as one of the plot options, it should be a URL where we can find the source code for this data viz.

}

## Extract essential info from ggplots, reality checks.
for(list.name in names(plot.list)){
Expand Down Expand Up @@ -631,8 +635,8 @@ animint2dir <- function(plot.list, out.dir = NULL,
file.copy(style.file, file.path(out.dir, "styles.css"), overwrite=TRUE)
}
file.copy(to.copy, out.dir, overwrite=TRUE, recursive=TRUE)
export.names <-
c("geoms", "time", "duration", "selectors", "plots", "title")
export.names <- c(
"geoms", "time", "duration", "selectors", "plots", "title", "source")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this saves the source option in the plot.json file.

export.data <- list()
for(export.name in export.names){
if(export.name %in% ls(meta)){
Expand Down
223 changes: 223 additions & 0 deletions R/z_pages.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,223 @@
#' Publish a list of ggplots as interactive visualizations on a GitHub repository
#'
#' This function takes a named list of ggplots, generates interactive animations,
#' and pushes the generated files to a specified GitHub repository. You can
#' choose to keep the repository private or public.
#' Before using this function set your appropriate git 'user.username' and 'user.email'
#'
#' @param plot.list A named list of ggplots and option lists.
#' @param github_repo The name of the GitHub repository to which the files will be pushed.
#' @param commit_message A string specifying the commit message for the pushed files.
#' @param private A logical flag indicating whether the GitHub repository should be private or not.
#' @param required_opts Character vector of plot.list element names which are checked (stop with an error if not present). Use required_opts=NULL to skip check.
#' @param ... Additional options passed onto \code{animint2dir}.
#'
#' @return The function returns the initialized GitHub repository object.
#'
#' @examples
#' \dontrun{
#' library(animint2)
#' p1 <- ggplot(mtcars, aes(x = mpg, y = wt)) +
#' geom_point()
#' p2 <- ggplot(mtcars, aes(x = hp, y = wt)) +
#' geom_point()
#' viz <- list(plot1 = p1, plot2 = p2)
#' animint2pages(
#' viz,
#' github_repo = "my_animint2_plots",
#' commit_message = "New animint",
#' private = TRUE)
#' }
#'
#' @export
animint2pages <- function(plot.list, github_repo, commit_message = "Commit from animint2pages", private = FALSE, required_opts = c("title","source"), ...) {

for(opt in required_opts){
if(!opt %in% names(plot.list)){
stop(sprintf("plot.list does not contain option named %s, which is required by animint2pages", opt))
}
}

# Check for required packages
for(pkg in c("gert", "gh")){
if (!requireNamespace(pkg)) {
stop(sprintf("Please run `install.packages('%s')` before using this function", pkg))
}
}

# Generate plot files
res <- animint2dir(plot.list, open.browser = FALSE, ...)

# Select non-ignored files to post
all_files <- Sys.glob(file.path(res$out.dir, "*"))
file_info <- file.info(all_files)
to_post <- all_files[!(file_info$size == 0 | grepl("~$", all_files))]

tmp_dir <- tempfile()

tryCatch({
creds <- gitcreds::gitcreds_get()
}, error = function(e) stop("A GitHub token is required to create and push to a new repository. \nTo create a GitHub token, follow these steps:\n1. Go to https://github.com/settings/tokens/new?scopes=repo&description=animint2pages\n2. Confirm your password if prompted.\n3. Ensure that the 'repo' scope is checked.\n4. Click 'Generate token' at the bottom of the page.\n5. Copy the generated token.\nAfter creating the token, you can set it up in your R environment by running: \nSys.setenv(GITHUB_PAT=\"yourGithubPAT\") \ngert::git_config_global_set(\"user.name\", \"yourUserName\") \ngert::git_config_global_set(\"user.email\", \"yourEmail\") \n"))

# Raise error if github_repo contains '/'
if (grepl("/", github_repo)) {
stop("The github_repo argument should not contain '/'.")
}

# Check for existing repository
whoami <- suppressMessages(gh::gh_whoami())
owner <- whoami$login

if (!check_no_github_repo(owner, github_repo)) {
create <- gh::gh("POST /user/repos", name = github_repo, private = private)
origin_url <- create$clone_url
repo <- gert::git_init(path = tmp_dir)
gert::git_remote_add(name = "origin", url = origin_url, repo = repo)
} else {
origin_url <- paste0("https://github.com/", owner, "/", github_repo, ".git")
repo <- gert::git_clone(origin_url, tmp_dir)
}

viz_url <- paste0("https://", whoami$login, ".github.io/", github_repo)
if (length(git2r::commits(repo)) == 0) {
initial_commit(tmp_dir, repo, viz_url)
}

# Handle gh-pages branch
manage_gh_pages(repo, to_post, tmp_dir, commit_message)
message(
"Visualization will be available at ", viz_url,
"\nDeployment via GitHub Pages may take a few minutes..."
)

repo
}

initial_commit <- function(tmp_dir, repo, viz_url) {
readme_file_path <- file.path(tmp_dir, "README.md")
header <- "## New animint visualization\n"
url_hyperlink <- sprintf("[%s](%s)\n", viz_url, viz_url)
full_content <- paste0(header, url_hyperlink)
writeLines(full_content, readme_file_path)

gert::git_add("README.md", repo = repo)
gert::git_commit("Initial commit", repo = repo)
df_or_vec <- gert::git_branch(repo)
# check if it is a data frame or an atomic vector
if (is.data.frame(df_or_vec)) {
all_branches <- df_or_vec[["name"]]
current_master <- all_branches[df_or_vec$active]
} else {
all_branches <- df_or_vec
current_master <- df_or_vec
}
# do not attempt to rename a branch to "main" when a branch with that name already exists
if (current_master != "main" && !"main" %in% all_branches) {
gert::git_branch_move(branch = current_master, new_branch = "main", repo = repo)
}
gert::git_push(repo = repo, remote = "origin", set_upstream = TRUE)
}

manage_gh_pages <- function(repo, to_post, tmp_dir, commit_message) {
branches <- gert::git_branch_list(local = TRUE, repo = repo)

if (!"gh-pages" %in% branches$name) {
gert::git_branch_create(repo = repo, branch = "gh-pages")
}

gert::git_branch_checkout("gh-pages", repo = repo)
file.copy(to_post, tmp_dir, recursive = TRUE)
gert::git_add(files = ".", repo = repo)
gert::git_commit(message = commit_message, repo = repo)
gert::git_push(remote = "origin", set_upstream = TRUE, repo = repo, force = TRUE)
}

check_no_github_repo <- function(owner, repo) {
tryCatch(
{
gh::gh("/repos/{owner}/{repo}", owner = owner, repo = repo)
TRUE
},
"http_error_404" = function(err) FALSE
)
}

get_pages_info <- function(viz_user_repo){
viz_dir <- tempfile()
origin_url <- paste0("https://github.com/", viz_user_repo, ".git")
gert::git_clone(origin_url, viz_dir)
gert::git_branch_checkout("gh-pages", repo=viz_dir)
Capture.PNG <- file.path(viz_dir, "Capture.PNG")
if(!file.exists(Capture.PNG)){
stop(sprintf("gh-pages branch of %s should contain file named Capture.PNG (screenshot of data viz)", viz_user_repo))
}
plot.json <- file.path(viz_dir, "plot.json")
jlist <- RJSONIO::fromJSON(plot.json)
commit.row <- gert::git_log(max=1, repo=viz_dir)
repo.row <- data.table(
viz_user_repo, Capture.PNG, commit.POSIXct=commit.row$time)
to.check <- c(
source="URL of data viz source code",
title="string describing the data viz")
for(attr.name in names(to.check)){
attr.value <- jlist[[attr.name]]
if(
is.character(attr.value)
&& length(attr.value)==1
&& !is.na(attr.value)
&& nchar(attr.value)>0
){
set(repo.row, j=attr.name, value=attr.value)
}else{
stop(sprintf("plot.json file in gh-pages branch of %s should have element named %s which should be %s", viz_user_repo, attr.name, to.check[[attr.name]]))
}
}
repo.row
}

##' A gallery is a collection of animints that have been published to
##' github pages. First repos.txt is read, then we clone each repo
##' which is not already present in meta.csv, and parse meta-data
##' (title, source, Capture.PNG) from the gh-pages branch, and
##' write/commit the data, re-render index.Rmd in gallery, and push
##' gallery to origin.
##' @title Update gallery
##' @param gallery_path path to local github repo with gh-pages active.
##' @return named list of data tables (meta and error).
##' @author Toby Dylan Hocking
##' @export
update_gallery <- function(gallery_path="~/R/gallery"){
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here is a new function for updating the gallery at https://github.com/animint/gallery/tree/gh-pages
please code review @Faye-yufan
probably do not want to test this, because it actually pushes to github?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually I could add a test to make sure that it updates the meta.csv / error.csv files

repos.txt <- file.path(gallery_path, "repos.txt")
repos.dt <- fread(repos.txt,header=FALSE,col.names="viz_user_repo")
meta.csv <- file.path(gallery_path, "meta.csv")
old.meta <- fread(meta.csv)
todo.meta <- repos.dt[!old.meta, on="viz_user_repo"]
meta.dt.list <- list(old.meta)
error.dt.list <- list()
add.POSIXct <- Sys.time()
for(viz_user_repo in todo.meta[["viz_user_repo"]]){
tryCatch({
meta.row <- data.table(add.POSIXct, get_repo_row(viz_user_repo))
meta.dt.list[[viz_user_repo]] <- meta.row
Capture.PNG <- meta.row[["Capture.PNG"]]
repo.png <- file.path(
gallery_path, "repos", paste0(viz_user_repo, ".png"))
user.dir <- dirname(repo.png)
dir.create(user.dir, showWarnings = FALSE, recursive = TRUE)
file.copy(Capture.PNG, repo.png, overwrite = TRUE)
}, error=function(e){
error.dt.list[[viz_user_repo]] <<- data.table(
add.POSIXct, viz_user_repo, error=e$message)
})
}
(meta.dt <- rbindlist(meta.dt.list))
(error.dt <- rbindlist(error.dt.list))
fwrite(meta.dt, meta.csv)
fwrite(error.dt, file.path(gallery_path, "error.csv"))
rmarkdown::render(file.path(gallery_path, "index.Rmd"))
to_add <- c("*.csv", file.path("repos","*","*.png"), "index.html")
gert::git_add(to_add, repo=gallery_path)
gert::git_commit(paste("update", add.POSIXct), repo=gallery_path)
gert::git_push("origin", repo=gallery_path)
list(meta=meta.dt, error=error.dt)
}
7 changes: 6 additions & 1 deletion inst/htmljs/animint.js
Original file line number Diff line number Diff line change
Expand Up @@ -2258,7 +2258,12 @@ var animint = function (to_select, json_file) {
// Widgets at bottom of page
////////////////////////////////////////////
element.append("br");

if(response.hasOwnProperty("source")){
element.append("a")
.attr("id","a_source_href")
.attr("href", response.source)
.text("source");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the user viz had a source option, this creates an <a> tag with href displayed below the viz.

}
// loading table.
var show_hide_table = element.append("button")
.text("Show download status table");
Expand Down
53 changes: 53 additions & 0 deletions man/animint2pages.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading