diff --git a/.github/.DS_Store b/.github/.DS_Store deleted file mode 100644 index 36b372c..0000000 Binary files a/.github/.DS_Store and /dev/null differ diff --git a/.gitignore b/.gitignore index 08d9016..5e21a40 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,7 @@ Meta doc .Rproj.user .Rhistory -.DS_Store +**/.DS_Store .RData .Ruserdata inst/doc @@ -12,4 +12,4 @@ run_test.R /doc/ /Meta/ .secrets -inst/extdata/tmp/default* \ No newline at end of file +inst/extdata/tmp/default* diff --git a/R/setup_project.R b/R/setup_project.R new file mode 100644 index 0000000..2d82a8e --- /dev/null +++ b/R/setup_project.R @@ -0,0 +1,80 @@ +#' Template Function to Initiate a New Quarto-Based OTTR Course +#' +#' This function will be invoked by RStudio to create a new RStudio Project +#' containing boilerplates files required to start a new Quarto-based OTTR course. +#' +#' For more details, refer to the RStudio Project Templates link: +#' https://rstudio.github.io/rstudio-extensions/rstudio_project_templates.html +#' +#' @param path Path to newly created project +#' @param ... User inputs +#' @noRd +setup_project_quarto <- function(path, ...) { + # collect inputs + dots <- list(...) + + # create directory + dir.create(path, recursive = TRUE, showWarnings = FALSE) + # create img folder within path + dir.create(file.path(path, "img"), recursive = TRUE, showWarnings = FALSE) + # create img/box-images folder within path + dir.create(file.path(path, "img", "box-images"), recursive = TRUE, showWarnings = FALSE) + # create .github folder within path + dir.create(file.path(path, ".github"), recursive = TRUE, showWarnings = FALSE) + # create .github/workflows folder within path + dir.create(file.path(path, ".github", "workflows"), recursive = TRUE, showWarnings = FALSE) + + # Vector of filenames to be copied + boilerplate_file <- c("index.qmd", "intro.qmd", "404.qmd", "theme.scss", + "style.css", "references.bib", "_quarto.yml", "config_automation.yml") + # Apply the function to each file in the vector + lapply(boilerplate_file, copy_files, dots$style_set, path) + + path_quarto_yml <- file.path(path, "_quarto.yml") + + quarto_yml <- yaml::read_yaml(path_quarto_yml) + quarto_yml$book$title <- dots$title + quarto_yml$book$author <- dots$author + quarto_yml$book$`repo-url` <- dots$repo_url + + # For Custom Style set, user provides logo + if (dots$style_set == "Custom") { + file.copy(file.path(normalizePath(dirname(dots$logo)), "logo.png"), file.path(path, "img", "logo.png")) + } + + write(yaml::as.yaml(quarto_yml, handlers = list(logical = yaml::verbatim_logical)), + path_quarto_yml) + + # Vector of filenames to be copied (images) + boilerplate_file_img <- c("img/logo.png", "img/favicon.ico", + "img/box-images/note.png", "img/box-images/warning.png", + "img/box-images/github.png", "img/box-images/dictionary.png", + "img/box-images/thinking_face.png", "img/box-images/under_construction.png") + # Apply the function to each file in the vector + lapply(boilerplate_file_img, copy_files, dots$style_set, path) + + # Vector of filenames to be copied (Github Actions) + boilerplate_file_gha <- c(".github/workflows/pull_request.yml", ".github/workflows/delete-preview.yml", + ".github/workflows/render-all.yml") + # Apply the function to each file in the vector + lapply(boilerplate_file_gha, copy_files, dots$style_set, path) +} + +# Utility function to copy each file +copy_files <- function(file_name, style_set, project_path) { + if (style_set == "FHDaSL") { + style_set <- "fhdasl" + } else if (style_set == "ITN") { + style_set <- "itn" + } else if (style_set == "AnVIL") { + style_set <- "anvil" + } else if (style_set == "GDSCN") { + style_set <- "gdscn" + } else { + style_set <- "custom" + } + + source_path <- system.file(file.path("style-sets", style_set, file_name), package = "ottrpal") + destination_path <- file.path(project_path, file_name) + file.copy(source_path, destination_path) +} diff --git a/inst/rstudio/templates/project/logo.png b/inst/rstudio/templates/project/logo.png new file mode 100644 index 0000000..2187267 Binary files /dev/null and b/inst/rstudio/templates/project/logo.png differ diff --git a/inst/rstudio/templates/project/rstudio_project_template.dcf b/inst/rstudio/templates/project/rstudio_project_template.dcf new file mode 100644 index 0000000..539e47e --- /dev/null +++ b/inst/rstudio/templates/project/rstudio_project_template.dcf @@ -0,0 +1,27 @@ +Binding: setup_project_quarto +Title: Quarto-Based OTTR Course +Icon: logo.png + +Parameter: style_set +Widget: SelectInput +Label: Style Set +Fields: FHDaSL, ITN, AnVIL, GDSCN, Custom + +Parameter: title +Widget: TextInput +Label: Course Title +Position: right + +Parameter: author +Widget: TextInput +Label: Course Author +Position: right + +Parameter: logo +Widget: FileInput +Label: Logo (for Custom Style Set) + +Parameter: repo_url +Widget: TextInput +Label: GitHub Repo URL +Position: right diff --git a/inst/style-sets/anvil/.github/workflows/delete-preview.yml b/inst/style-sets/anvil/.github/workflows/delete-preview.yml new file mode 100644 index 0000000..7d8cf01 --- /dev/null +++ b/inst/style-sets/anvil/.github/workflows/delete-preview.yml @@ -0,0 +1,25 @@ +name: Delete Preview + +on: + pull_request: + types: [closed] + +jobs: + delete-preview: + runs-on: ubuntu-latest + steps: + + # This is because if a PR is closed before a render finishes it won't find it. + - name: Sleep for 5 minutes + run: sleep 300s + shell: bash + + # Check out current repository + - name: checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + # Delete the branch! + - name: Delete branch locally and remotely + run: git push origin --delete preview-${{ github.event.pull_request.number }} || echo "No branch to delete" diff --git a/inst/style-sets/anvil/.github/workflows/pull_request.yml b/inst/style-sets/anvil/.github/workflows/pull_request.yml new file mode 100644 index 0000000..5b9ee7b --- /dev/null +++ b/inst/style-sets/anvil/.github/workflows/pull_request.yml @@ -0,0 +1,169 @@ +name: Pull Request + +on: + pull_request: + branches: [ main, staging ] + +jobs: + yaml-check: + name: Load user automation choices + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + # Use the yaml-env-action action. + - name: Load environment from YAML + uses: doughepi/yaml-env-action@v1.0.0 + with: + files: config_automation.yml # Pass a space-separated list of configuration files. Rightmost files take precedence. + + # Delete the branch if this has been run before + - name: Delete branch locally and remotely + run: git push origin --delete preview-${{ github.event.pull_request.number }} || echo "No branch to delete" + + # Make the branch fresh + - name: Make the branch fresh + run: | + git config --global --add safe.directory $GITHUB_WORKSPACE + git config --global user.name 'github-actions[bot]' + git config --global user.email 'github-actions[bot]@users.noreply.github.com' + + branch_name='preview-${{ github.event.pull_request.number }}' + echo branch doesnt exist + git checkout -b $branch_name || echo branch exists + git push --set-upstream origin $branch_name + shell: bash + + outputs: + public_repository: "${{ steps.public_repository.outputs.public }}" + toggle_spell_check: "${{ env.SPELL_CHECK }}" + toggle_url_check: "${{ env.URL_CHECKER }}" + toggle_render_preview: "${{ env.RENDER_PREVIEW }}" + rendering_docker_image: "${{ env.RENDERING_DOCKER_IMAGE }}" + +########################## Make the error reports ############################## + spell-check: + name: Check spelling + needs: yaml-check + if: ${{needs.yaml-check.outputs.toggle_spell_check == 'yes'}} + uses: jhudsl/ottr-reports/.github/workflows/report-maker.yml@main + with: + check_type: spelling + error_min: 3 + gh_pat: secrets.GH_PAT + + url-check: + name: Check URLs + needs: yaml-check + if: ${{needs.yaml-check.outputs.toggle_url_check == 'yes'}} + uses: jhudsl/ottr-reports/.github/workflows/report-maker.yml@main + with: + check_type: urls + error_min: 0 + gh_pat: secrets.GH_PAT + + render-preview: + name: Render preview + needs: yaml-check + runs-on: ubuntu-latest + container: + image: ${{needs.yaml-check.outputs.rendering_docker_image}} + if: ${{needs.yaml-check.outputs.toggle_render_preview == 'yes'}} + + steps: + - name: Checkout files + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + # Set up git checkout + - name: Set up git checkout + run: | + git config --global --add safe.directory $GITHUB_WORKSPACE + git config --global user.name 'github-actions[bot]' + git config --global user.email 'github-actions[bot]@users.noreply.github.com' + + branch_name='preview-${{ github.event.pull_request.number }}' + git fetch --all + git checkout $branch_name + git merge -s recursive --strategy-option=theirs origin/${{ github.head_ref }} --allow-unrelated-histories + shell: bash + + # Now we want to render all the html files from the qmd files + - name: Run render html + id: site + run: quarto render + + # This checks on the steps before it and makes sure that they completed. + # If the renders didn't complete we don't want to commit the file changes + - name: Check on render steps + if: steps.site.outcome != 'success' + run: | + echo site status ${{steps.site.outcome}} + exit 1 + + - name: Website preview for download + run: zip website-preview.zip docs/* -r + + # Commit the rendered website files + - name: Commit rendered website files to preview branch + id: commit + run: | + branch_name='preview-${{ github.event.pull_request.number }}' + git diff origin/main -- '*.html' >/dev/null && changes=true || changes=false + echo "changes=$changes" >> $GITHUB_OUTPUT + git add . --force + git commit -m 'Render preview' || echo "No changes to commit" + git pull --set-upstream origin $branch_name --allow-unrelated-histories --strategy-option=ours + git push --force || echo "No changes to commit" + shell: bash + + - name: Find Comment + uses: peter-evans/find-comment@v1 + id: fc + with: + issue-number: ${{ github.event.pull_request.number }} + comment-author: 'github-actions[bot]' + body-includes: latest commit + + - name: Build components of the comment + id: build-components + run: | + course_name=$(head -n 1 _website.yml | cut -d'"' -f 2| tr " " "-") + website_link=$(echo "https://htmlpreview.github.io/?https://raw.githubusercontent.com/$GITHUB_REPOSITORY/preview-${{ github.event.pull_request.number }}/docs/index.html") + docs_link=$(echo "https://github.com/$GITHUB_REPOSITORY/raw/preview-${{ github.event.pull_request.number }}/website-preview.zip") + echo "docs_link=$docs_link" >> $GITHUB_OUTPUT + echo "website_link=$website_link" >> $GITHUB_OUTPUT + echo "time=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT + echo "commit_id=$GITHUB_SHA" >> $GITHUB_OUTPUT + echo ${{steps.commit.outputs.changes}} + + - name: Create or update comment + if: steps.commit.outputs.changes == 'true' + uses: peter-evans/create-or-update-comment@v1 + with: + comment-id: ${{ steps.fc.outputs.comment-id }} + issue-number: ${{ github.event.pull_request.number }} + body: | + :eyes: [Quick Preview of Website](${{ steps.build-components.outputs.website_link }}) - Click for a preview of recent changes. + :file_folder: [Download Full Website](${{ steps.build-components.outputs.docs_link }}) - Download complete Zip file of the website. + + The Quick Preview may not display all HTML features accurately, but it provides a basic overview. + + _Updated at ${{ steps.build-components.outputs.time }} with changes from the latest commit ${{ steps.build-components.outputs.commit_id }}_ + edit-mode: replace + + - name: No comment if no changes + if: steps.commit.outputs.changes == 'false' + uses: peter-evans/create-or-update-comment@v1 + with: + comment-id: ${{ steps.fc.outputs.comment-id }} + issue-number: ${{ github.event.pull_request.number }} + body: | + The latest commit did not produce rendering changes. + + _Updated at ${{ steps.build-components.outputs.time }} with changes from ${{ steps.build-components.outputs.commit_id }}_ + edit-mode: replace diff --git a/inst/style-sets/anvil/.github/workflows/render-all.yml b/inst/style-sets/anvil/.github/workflows/render-all.yml new file mode 100644 index 0000000..775e2db --- /dev/null +++ b/inst/style-sets/anvil/.github/workflows/render-all.yml @@ -0,0 +1,133 @@ +name: Render All Output + +on: + workflow_dispatch: + push: + branches: [ main ] + paths: + - '**/*.qmd' + +jobs: + yaml-check: + name: Load User Automation Choices + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + # Use the yaml-env-action action. + - name: Load environment from YAML + uses: doughepi/yaml-env-action@v1.0.0 + with: + files: config_automation.yml # Pass a space-separated list of configuration files. Rightmost files take precedence. + outputs: + toggle_coursera: "${{ env.RENDER_COURSERA }}" + toggle_leanpub: "${{ env.RENDER_LEANPUB }}" + rendering_docker_image: "${{ env.RENDERING_DOCKER_IMAGE }}" + + clean-docs: + name: Clean docs folder + needs: yaml-check + runs-on: ubuntu-latest + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + + - name: Delete all files inside docs + run: | + rm -rf docs/* + mkdir -p docs + + - name: Commit changes + run: | + git config --global user.name 'github-actions[bot]' + git config --global user.email 'github-actions[bot]@users.noreply.github.com' + git add docs/ + git commit -m "Clean up docs directory" || echo "No changes to commit" + git push + + render-quarto-book: + name: Render Quarto Book + needs: [yaml-check, clean-docs] + runs-on: ubuntu-latest + container: + image: ${{needs.yaml-check.outputs.rendering_docker_image}} + + steps: + - name: checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + token: ${{ secrets.GH_PAT }} + + - name: Login as github actions bot + run: | + git config --global --add safe.directory $GITHUB_WORKSPACE + git config --global user.name 'github-actions[bot]' + git config --global user.email 'github-actions[bot]@users.noreply.github.com' + echo ${{needs.yaml-check.outputs.rendering_docker_image}} + + # Run quarto::quarto_render() + - name: Run quarto render + id: quarto-render + run: | + Rscript -e "quarto::quarto_render()" + + # This checks on the steps before it and makes sure that they completed. + # If the renders didn't complete we don't want to commit the file changes + - name: Check on render step + if: steps.quarto-render.outcome != 'success' + run: | + echo Quarto Render status ${{steps.quarto-render.outcome}} + exit 1 + + # Commit the rendered files inside docs/ + - name: Commit rendered files + env: + GH_PAT: ${{ secrets.GH_PAT }} + run: | + git remote set-url origin https://${GH_PAT}@github.com/${GITHUB_REPOSITORY} + git fetch origin + git add --force docs/* + git commit -m 'Render Quarto Book' || echo "No changes to commit" + git pull --allow-unrelated-histories --strategy-option=ours + git push -u origin main || echo "No changes to push" + + render-tocless: + name: Render TOC-less Quarto Book + needs: [yaml-check, clean-docs, render-quarto-book] + runs-on: ubuntu-latest + container: + image: ${{needs.yaml-check.outputs.rendering_docker_image}} + if: ${{needs.yaml-check.outputs.toggle_coursera == 'yes' || needs.yaml-check.outputs.toggle_leanpub == 'yes'}} + + steps: + - name: checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + token: ${{ secrets.GH_PAT }} + + - name: Login as github-actions bot + run: | + git config --global --add safe.directory $GITHUB_WORKSPACE + git config --global user.name 'github-actions[bot]' + git config --global user.email 'github-actions[bot]@users.noreply.github.com' + + # Rendered content for Leanpub and Coursera is similar. + # This job creates a shared scaffold for both. + - name: Run TOC-less version of render + id: toc_less_quarto + run: Rscript -e "quarto::quarto_render('.', quarto_args = c('--output-dir', 'docs/no_toc'), metadata = list(sidebar = F, toc = F))" + + # Commit the TOC-less version files + - name: Commit TOC-less Quarto files + env: + GH_PAT: ${{ secrets.GH_PAT }} + run: | + git remote set-url origin https://${GH_PAT}@github.com/${GITHUB_REPOSITORY} + git fetch origin + git add --force docs/no_toc/* + git commit -m 'Render TOC-less Quarto Book' || echo "No changes to commit" + git pull --allow-unrelated-histories --strategy-option=ours + git push -u origin main || echo "No changes to push" diff --git a/inst/style-sets/anvil/404.qmd b/inst/style-sets/anvil/404.qmd new file mode 100644 index 0000000..5309332 --- /dev/null +++ b/inst/style-sets/anvil/404.qmd @@ -0,0 +1,7 @@ +--- +title: "Page Not Found" +--- + +The page you requested cannot be found (perhaps it was moved or renamed). + +Try going back to the previous page or leave a [GitHub issue](https://github.com/fhdsl/ottr/issues/new) for more information. \ No newline at end of file diff --git a/inst/style-sets/anvil/_quarto.yml b/inst/style-sets/anvil/_quarto.yml new file mode 100644 index 0000000..1b4bcd8 --- /dev/null +++ b/inst/style-sets/anvil/_quarto.yml @@ -0,0 +1,65 @@ +project: + type: book + output-dir: docs + +book: + title: "Quarto Based OTTR Course" + author: "Fred Hutch Data Science Lab" + date: "1/1/2025" + favicon: img/favicon.ico + bread-crumbs: false + + page-navigation: true + search: true + repo-url: https://github.com/fhdsl/ottr + repo-actions: [edit, issue] + + chapters: + - index.qmd + - intro.qmd + + sidebar: + logo: "img/logo.png" + logo-href: "https://anvilproject.org/" + foreground: "#1B365D" + + page-footer: + left: | + This book was built with Quarto using + OTTR. + center: | + All illustrations CC-BY. +
+ All other materials CC-BY unless noted otherwise. + right: + - icon: github + href: https://github.com/anvilproject + - icon: twitter + href: https://twitter.com/useAnVIL + + +bibliography: references.bib + +format: + html: + theme: + - theme.scss + grid: + sidebar-width: 260px + css: style.css + linkcolor: '#68ace5' + mainfont: "Karla" + + sidebar: true + toc: true + + code-link: true + code-copy: true + + link-external-newwindow: true + + image: img/favicon.ico + license: "CC BY" +knitr: + opts_chunk: + fig.path: "resources/images/figure/" diff --git a/inst/style-sets/anvil/config_automation.yml b/inst/style-sets/anvil/config_automation.yml new file mode 100644 index 0000000..a5fb422 --- /dev/null +++ b/inst/style-sets/anvil/config_automation.yml @@ -0,0 +1,24 @@ + +##### Checks run at pull request ##### +# Check quiz formatting +check-quizzes: no +# Check that urls in the content are not broken +url-checker: yes +# Render preview of content with changes (Rmd's and md's are checked) +render-preview: yes +# Spell check Rmds and quizzes +spell-check: yes +# Style any R code +style-code: yes +# Test build the docker image if any docker-relevant files have been changed +docker-test: no + +##### Renderings run upon merge to main branch ##### +# Rendering each platform's content +render-bookdown: yes +render-leanpub: yes +render-coursera: no + +# What docker image should be used for rendering? +# The default is jhudsl/base_ottr:latest +rendering-docker-image: 'jhudsl/ottr_quarto:latest' diff --git a/inst/style-sets/anvil/img/box-images/dictionary.png b/inst/style-sets/anvil/img/box-images/dictionary.png new file mode 100644 index 0000000..75ddac7 Binary files /dev/null and b/inst/style-sets/anvil/img/box-images/dictionary.png differ diff --git a/inst/style-sets/anvil/img/box-images/github.png b/inst/style-sets/anvil/img/box-images/github.png new file mode 100644 index 0000000..a93acd3 Binary files /dev/null and b/inst/style-sets/anvil/img/box-images/github.png differ diff --git a/inst/style-sets/anvil/img/box-images/note.png b/inst/style-sets/anvil/img/box-images/note.png new file mode 100644 index 0000000..72de3ae Binary files /dev/null and b/inst/style-sets/anvil/img/box-images/note.png differ diff --git a/inst/style-sets/anvil/img/box-images/thinking_face.png b/inst/style-sets/anvil/img/box-images/thinking_face.png new file mode 100644 index 0000000..c2c279a Binary files /dev/null and b/inst/style-sets/anvil/img/box-images/thinking_face.png differ diff --git a/inst/style-sets/anvil/img/box-images/under_construction.png b/inst/style-sets/anvil/img/box-images/under_construction.png new file mode 100644 index 0000000..a67bd5c Binary files /dev/null and b/inst/style-sets/anvil/img/box-images/under_construction.png differ diff --git a/inst/style-sets/anvil/img/box-images/warning.png b/inst/style-sets/anvil/img/box-images/warning.png new file mode 100644 index 0000000..405fb61 Binary files /dev/null and b/inst/style-sets/anvil/img/box-images/warning.png differ diff --git a/inst/style-sets/anvil/img/favicon.ico b/inst/style-sets/anvil/img/favicon.ico new file mode 100755 index 0000000..f1eb1c4 Binary files /dev/null and b/inst/style-sets/anvil/img/favicon.ico differ diff --git a/inst/style-sets/anvil/img/logo.png b/inst/style-sets/anvil/img/logo.png new file mode 100644 index 0000000..83c7b67 Binary files /dev/null and b/inst/style-sets/anvil/img/logo.png differ diff --git a/inst/style-sets/anvil/index.qmd b/inst/style-sets/anvil/index.qmd new file mode 100644 index 0000000..0f24338 --- /dev/null +++ b/inst/style-sets/anvil/index.qmd @@ -0,0 +1,14 @@ +# Quarto Based OTTR Course {.unnumbered} + +This course is part of a series of courses for the [Informatics Technology for Cancer Research (ITCR)](https://itcr.cancer.gov/) called the Informatics Technology for Cancer Research Education Resource. This material was created by the ITCR Training Network (ITN) which is a collaborative effort of researchers around the United States to support cancer informatics and data science training through resources, technology, and events. This initiative is funded by the following grant: [National Cancer Institute (NCI)](https://www.cancer.gov/) UE5 CA254170. Our courses feature tools developed by ITCR Investigators and make it easier for principal investigators, scientists, and analysts to integrate cancer informatics into their workflows. Please see our website at [www.itcrtraining.org](www.itcrtraining.org) for more information. + + +## Available Course Formats + +This course is available in multiple formats which allows you to take it in the way that best suites your needs. You can take it for certificate which can be for free or fee. + +- The material for this course can be viewed without login requirement on this [website](https://www.ottrproject.org/). This format might be most appropriate for you if you rely on screen-reader technology. +- This course can be taken for [free certification through Leanpub](https://leanpub.com/). +- This course can be taken on [Coursera for certification here](https://www.coursera.org/) (but it is not available for free on Coursera). +- Our courses are open source, you can find the [source material for this course on GitHub](https://github.com/fhdsl/ottr). + diff --git a/inst/style-sets/anvil/intro.qmd b/inst/style-sets/anvil/intro.qmd new file mode 100644 index 0000000..35cead0 --- /dev/null +++ b/inst/style-sets/anvil/intro.qmd @@ -0,0 +1,221 @@ +# New Chapter + +## Learning Objectives + +Every chapter also needs Learning objectives. + +## Libraries + +For this chapter, we'll need the following packages attached: + +*Remember to add [any additional packages you need to your course's own docker image](https://github.com/jhudsl/OTTR_Template/wiki/Using-Docker#starting-a-new-docker-image). + +```{r} +library(magrittr) +``` + +## Topic of Section + +You can write all your text in sections like this, using `##` to indicate a new header. you can use additional pound symbols to create lower levels of headers. + +See [here](https://www.rstudio.com/wp-content/uploads/2015/02/rmarkdown-cheatsheet.pdf) for additional general information about how you can format text within R Markdown files. In addition, see [here](https://pandoc.org/MANUAL.html#pandocs-markdown) for more in depth and advanced options. + +### Subtopic + +Here's a subheading (using three pound symbols) and some text in this subsection! + +## Code examples + +You can demonstrate code like this: + +```{r} +output_dir <- file.path("resources", "code_output") +if (!dir.exists(output_dir)) { + dir.create(output_dir) +} +``` + +And make plots too: + +```{r} +hist_plot <- hist(iris$Sepal.Length) +``` + +You can also save these plots to file: + +```{r} +png(file.path(output_dir, "test_plot.png")) +hist_plot +dev.off() +``` + + +## Image example + +How to include a Google slide. It's simplest to use the `ottrpal` package: + +```{r} +#| fig-align: "center" +#| fig-alt: "Major point!! example image" +#| echo: false +#| out-width: "100%" +ottrpal::include_slide("https://docs.google.com/presentation/d/1Dw_rBb1hySN_76xh9-x5J2dWF_das9BAUjQigf2fN-E/edit#slide=id.g252f18e2576_1_0") +``` + + + +## Video examples + +You may also want to embed videos in your course. If alternatively, you just want to include a link you can do so like this: + +Check out this [link to a video](https://www.youtube.com/embed/VOCYL-FNbr0) using markdown syntax. + +### Using `knitr` + +To embed videos in your course, you can use `knitr::include_url()` like this: +Note that you should use `echo=FALSE` in the code chunk because we don't want the code part of this to show up. If you are unfamiliar with [how R Markdown code chunks work, read this](https://rmarkdown.rstudio.com/lesson-3.html). + + +```{r} +#| echo: false +knitr::include_url("https://www.youtube.com/embed/VOCYL-FNbr0") +``` + +### Using HTML + + + +### Using `knitr` + +```{r, fig.align="center", echo=FALSE, out.width="100%"} +knitr::include_url("https://drive.google.com/file/d/1mm72K4V7fqpgAfWkr6b7HTZrc3f-T6AV/preview") +``` + +### Using HTML + + + +## Website Examples + +Yet again you can use a link to a website like so: + +[A Website](https://yihui.org) + +You might want to have users open a website in a new tab by default, especially if they need to reference both the course and a resource at once. + +[A Website](https://yihui.org){target="_blank"} + +Or, you can embed some websites. + +### Using `knitr` + +This works: + +```{r, fig.align="center", echo=FALSE} +knitr::include_url("https://yihui.org") +``` + + +### Using HTML + + + + +## Stylized boxes + +Occasionally, you might find it useful to emphasize a particular piece of information. To help you do so, we have provided css code and images (no need for you to worry about that!) to create the following stylized boxes. + +You can use these boxes in your course with either of two options: using HTML code or Pandoc syntax. + +### Using `rmarkdown` container syntax + +The `rmarkdown` package allows for a different syntax to be converted to the HTML that you just saw and also allows for conversion to LaTeX. See the [Bookdown](https://bookdown.org/yihui/rmarkdown-cookbook/custom-blocks.html) documentation for more information. Note that Bookdown uses Pandoc. + + +``` +::: {.notice} +Note using rmarkdown syntax. + +::: +``` + +::: {.notice} +Note using rmarkdown syntax. + +::: + +As an example you might do something like this: + +::: {.notice} +Please click on the subsection headers in the left hand +navigation bar (e.g., 2.1, 4.3) a second time to expand the +table of contents and enable the `scroll_highlight` feature +([see more](introduction.html#scroll-highlight)) +::: + + +### Using HTML + +To add a warning box like the following use: + +
+Followed by the text you want inside +
+ +This will create the following: + +
+ +Followed by the text you want inside + +
+ +Here is a `
` box: + +
+ +Note text + +
+ +Here is a `
` box: + +
+ +GitHub text + +
+ + +Here is a `
` box: + +
+ +dictionary text + +
+ + +Here is a `
` box: + +
+ +reflection text + +
+ + +Here is a `
` box: + +
+ +Work in Progress text + +
+ + +## Dropdown summaries + +
You can hide additional information in a dropdown menu +Here's more words that are hidden. +
diff --git a/inst/style-sets/anvil/references.bib b/inst/style-sets/anvil/references.bib new file mode 100644 index 0000000..0220dbd --- /dev/null +++ b/inst/style-sets/anvil/references.bib @@ -0,0 +1,19 @@ +@article{knuth84, + author = {Knuth, Donald E.}, + title = {Literate Programming}, + year = {1984}, + issue_date = {May 1984}, + publisher = {Oxford University Press, Inc.}, + address = {USA}, + volume = {27}, + number = {2}, + issn = {0010-4620}, + url = {https://doi.org/10.1093/comjnl/27.2.97}, + doi = {10.1093/comjnl/27.2.97}, + journal = {Comput. J.}, + month = may, + pages = {97–111}, + numpages = {15} +} + + diff --git a/inst/style-sets/anvil/style.css b/inst/style-sets/anvil/style.css new file mode 100755 index 0000000..0bae626 --- /dev/null +++ b/inst/style-sets/anvil/style.css @@ -0,0 +1,176 @@ +/* Imports fonts from Google Fonts (Abril Fatface, Karla, and Lora) with different weights and styles */ +@import url('https://fonts.googleapis.com/css?family=Abril+Fatface|Karla:400,400i,700,700i|Lora:400,400i,700,700i&display=swap'); + +/* Styles for paragraph captions, setting their color and margin */ +p.caption { + color: #777; + margin-top: 10px; +} + +/* Styles for paragraph code, which inherit white-space property */ +p code { + white-space: inherit; +} + +/* Styles for pre elements to prevent words from breaking unnaturally */ +pre { + word-break: normal; + word-wrap: normal; +} + +/* Inherits the white-space property for consistent code formatting */ +pre code { + white-space: inherit; +} + + +/*------------- Header text---------------- */ +h1, h2, h3, h4 { + font-family: 'Lora', arial, sans-serif; +} + +.title { + font-family: 'Lora'; + font-size: 4em !important; + color: #012d72; + margin-top: 0.275em !important; + margin-bottom: 0.35em !important; +} + +.subtitle { + font-family: 'Lora'; + color: #0b8d96; +} + +/* Sidebar Logo */ +.sidebar-logo {} + +/* Stylized boxes */ +div.notice, div.warning, div.github, div.dictionary, div.reflection, div.wip { + padding: 1em; + margin: 1em 0; + padding-left: 100px; + min-height: 120px; + background-repeat: no-repeat; +} + +div.notice{ + border: 4px #68ace5; + border-style: solid; + background-size: 70px; + background-position: 15px center; + background-color: #e8ebee; + background-image: url("/img/box-images/note.png"); +} + + +div.warning{ + border: 4px #e0471c; + border-style: solid; + background-size: 70px; + background-position: 15px center; + background-color: #e8ebee; + background-image: url("/img/box-images/warning.png"); +} + +div.github{ + border: 4px #000000; + border-style: solid; + background-size: 70px; + background-position: 15px center; + background-color: #e8ebee; + background-image: url("/img/box-images/github.png"); +} + +div.dictionary{ + border: 4px #68ace5; + border-style: solid; + background-size: 70px; + background-position: 15px center; + background-color: #e8ebee; + background-image: url("/img/box-images/dictionary.png"); +} + +div.reflection{ + border: 4px #68ace5; + border-style: solid; + background-size: 90px; + background-position: 15px center; + background-color: #e8ebee; + background-image: url("/img/box-images/thinking_face.png"); +} + +div.wip{ + border: 4px #000000; + border-style: solid; + background-size: 70px; + background-position: 15px center; + background-color: #f4d03f; + background-image: url("/img/box-images/under_construction.png"); +} + +/* Navbar */ +.chapter-title { + text-transform: none; +} +.menu-text { + text-transform: uppercase; +} + + + +/* iframes */ +iframe { + -moz-transform-origin: top left; + -webkit-transform-origin: top left; + -o-transform-origin: top left; + -ms-transform-origin: top left; + transform-origin: top left; +} + +.iframe-container { + overflow: auto; + -webkit-overflow-scrolling: touch; + border: #ddd 2px solid; + box-shadow: #888 0px 5px 8px; + margin-bottom: 1em; +} + +.iframe-container > iframe { + border: none; +} + + +/* Footer */ +.footer { + font-family: "Lora", serif; + font-size: 1em; + color: #193a5c; +} + + +/* Navbar Header */ +.navbar-logo { + max-height: 33px; +} + + +/* Navbar Footer */ +.nav-footer { + display: flex; + flex-direction: row; + flex-wrap: wrap; + justify-content: space-between; + align-items: baseline; + text-align: center; + padding-top: .5rem; + padding-bottom: .5rem; + background-color: #1B365D; + color: #fff !important; +} + + +/* Sidebar Hover Color */ +div.sidebar-item-container .active, div.sidebar-item-container .show>.nav-link, div.sidebar-item-container .sidebar-link>code { + color: #68ace5; +} diff --git a/inst/style-sets/anvil/theme.scss b/inst/style-sets/anvil/theme.scss new file mode 100644 index 0000000..1d1a179 --- /dev/null +++ b/inst/style-sets/anvil/theme.scss @@ -0,0 +1,2 @@ +/*-- scss:defaults --*/ +$toc-color: #68ace5; diff --git a/inst/style-sets/custom/.github/workflows/delete-preview.yml b/inst/style-sets/custom/.github/workflows/delete-preview.yml new file mode 100644 index 0000000..7d8cf01 --- /dev/null +++ b/inst/style-sets/custom/.github/workflows/delete-preview.yml @@ -0,0 +1,25 @@ +name: Delete Preview + +on: + pull_request: + types: [closed] + +jobs: + delete-preview: + runs-on: ubuntu-latest + steps: + + # This is because if a PR is closed before a render finishes it won't find it. + - name: Sleep for 5 minutes + run: sleep 300s + shell: bash + + # Check out current repository + - name: checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + # Delete the branch! + - name: Delete branch locally and remotely + run: git push origin --delete preview-${{ github.event.pull_request.number }} || echo "No branch to delete" diff --git a/inst/style-sets/custom/.github/workflows/pull_request.yml b/inst/style-sets/custom/.github/workflows/pull_request.yml new file mode 100644 index 0000000..5b9ee7b --- /dev/null +++ b/inst/style-sets/custom/.github/workflows/pull_request.yml @@ -0,0 +1,169 @@ +name: Pull Request + +on: + pull_request: + branches: [ main, staging ] + +jobs: + yaml-check: + name: Load user automation choices + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + # Use the yaml-env-action action. + - name: Load environment from YAML + uses: doughepi/yaml-env-action@v1.0.0 + with: + files: config_automation.yml # Pass a space-separated list of configuration files. Rightmost files take precedence. + + # Delete the branch if this has been run before + - name: Delete branch locally and remotely + run: git push origin --delete preview-${{ github.event.pull_request.number }} || echo "No branch to delete" + + # Make the branch fresh + - name: Make the branch fresh + run: | + git config --global --add safe.directory $GITHUB_WORKSPACE + git config --global user.name 'github-actions[bot]' + git config --global user.email 'github-actions[bot]@users.noreply.github.com' + + branch_name='preview-${{ github.event.pull_request.number }}' + echo branch doesnt exist + git checkout -b $branch_name || echo branch exists + git push --set-upstream origin $branch_name + shell: bash + + outputs: + public_repository: "${{ steps.public_repository.outputs.public }}" + toggle_spell_check: "${{ env.SPELL_CHECK }}" + toggle_url_check: "${{ env.URL_CHECKER }}" + toggle_render_preview: "${{ env.RENDER_PREVIEW }}" + rendering_docker_image: "${{ env.RENDERING_DOCKER_IMAGE }}" + +########################## Make the error reports ############################## + spell-check: + name: Check spelling + needs: yaml-check + if: ${{needs.yaml-check.outputs.toggle_spell_check == 'yes'}} + uses: jhudsl/ottr-reports/.github/workflows/report-maker.yml@main + with: + check_type: spelling + error_min: 3 + gh_pat: secrets.GH_PAT + + url-check: + name: Check URLs + needs: yaml-check + if: ${{needs.yaml-check.outputs.toggle_url_check == 'yes'}} + uses: jhudsl/ottr-reports/.github/workflows/report-maker.yml@main + with: + check_type: urls + error_min: 0 + gh_pat: secrets.GH_PAT + + render-preview: + name: Render preview + needs: yaml-check + runs-on: ubuntu-latest + container: + image: ${{needs.yaml-check.outputs.rendering_docker_image}} + if: ${{needs.yaml-check.outputs.toggle_render_preview == 'yes'}} + + steps: + - name: Checkout files + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + # Set up git checkout + - name: Set up git checkout + run: | + git config --global --add safe.directory $GITHUB_WORKSPACE + git config --global user.name 'github-actions[bot]' + git config --global user.email 'github-actions[bot]@users.noreply.github.com' + + branch_name='preview-${{ github.event.pull_request.number }}' + git fetch --all + git checkout $branch_name + git merge -s recursive --strategy-option=theirs origin/${{ github.head_ref }} --allow-unrelated-histories + shell: bash + + # Now we want to render all the html files from the qmd files + - name: Run render html + id: site + run: quarto render + + # This checks on the steps before it and makes sure that they completed. + # If the renders didn't complete we don't want to commit the file changes + - name: Check on render steps + if: steps.site.outcome != 'success' + run: | + echo site status ${{steps.site.outcome}} + exit 1 + + - name: Website preview for download + run: zip website-preview.zip docs/* -r + + # Commit the rendered website files + - name: Commit rendered website files to preview branch + id: commit + run: | + branch_name='preview-${{ github.event.pull_request.number }}' + git diff origin/main -- '*.html' >/dev/null && changes=true || changes=false + echo "changes=$changes" >> $GITHUB_OUTPUT + git add . --force + git commit -m 'Render preview' || echo "No changes to commit" + git pull --set-upstream origin $branch_name --allow-unrelated-histories --strategy-option=ours + git push --force || echo "No changes to commit" + shell: bash + + - name: Find Comment + uses: peter-evans/find-comment@v1 + id: fc + with: + issue-number: ${{ github.event.pull_request.number }} + comment-author: 'github-actions[bot]' + body-includes: latest commit + + - name: Build components of the comment + id: build-components + run: | + course_name=$(head -n 1 _website.yml | cut -d'"' -f 2| tr " " "-") + website_link=$(echo "https://htmlpreview.github.io/?https://raw.githubusercontent.com/$GITHUB_REPOSITORY/preview-${{ github.event.pull_request.number }}/docs/index.html") + docs_link=$(echo "https://github.com/$GITHUB_REPOSITORY/raw/preview-${{ github.event.pull_request.number }}/website-preview.zip") + echo "docs_link=$docs_link" >> $GITHUB_OUTPUT + echo "website_link=$website_link" >> $GITHUB_OUTPUT + echo "time=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT + echo "commit_id=$GITHUB_SHA" >> $GITHUB_OUTPUT + echo ${{steps.commit.outputs.changes}} + + - name: Create or update comment + if: steps.commit.outputs.changes == 'true' + uses: peter-evans/create-or-update-comment@v1 + with: + comment-id: ${{ steps.fc.outputs.comment-id }} + issue-number: ${{ github.event.pull_request.number }} + body: | + :eyes: [Quick Preview of Website](${{ steps.build-components.outputs.website_link }}) - Click for a preview of recent changes. + :file_folder: [Download Full Website](${{ steps.build-components.outputs.docs_link }}) - Download complete Zip file of the website. + + The Quick Preview may not display all HTML features accurately, but it provides a basic overview. + + _Updated at ${{ steps.build-components.outputs.time }} with changes from the latest commit ${{ steps.build-components.outputs.commit_id }}_ + edit-mode: replace + + - name: No comment if no changes + if: steps.commit.outputs.changes == 'false' + uses: peter-evans/create-or-update-comment@v1 + with: + comment-id: ${{ steps.fc.outputs.comment-id }} + issue-number: ${{ github.event.pull_request.number }} + body: | + The latest commit did not produce rendering changes. + + _Updated at ${{ steps.build-components.outputs.time }} with changes from ${{ steps.build-components.outputs.commit_id }}_ + edit-mode: replace diff --git a/inst/style-sets/custom/.github/workflows/render-all.yml b/inst/style-sets/custom/.github/workflows/render-all.yml new file mode 100644 index 0000000..775e2db --- /dev/null +++ b/inst/style-sets/custom/.github/workflows/render-all.yml @@ -0,0 +1,133 @@ +name: Render All Output + +on: + workflow_dispatch: + push: + branches: [ main ] + paths: + - '**/*.qmd' + +jobs: + yaml-check: + name: Load User Automation Choices + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + # Use the yaml-env-action action. + - name: Load environment from YAML + uses: doughepi/yaml-env-action@v1.0.0 + with: + files: config_automation.yml # Pass a space-separated list of configuration files. Rightmost files take precedence. + outputs: + toggle_coursera: "${{ env.RENDER_COURSERA }}" + toggle_leanpub: "${{ env.RENDER_LEANPUB }}" + rendering_docker_image: "${{ env.RENDERING_DOCKER_IMAGE }}" + + clean-docs: + name: Clean docs folder + needs: yaml-check + runs-on: ubuntu-latest + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + + - name: Delete all files inside docs + run: | + rm -rf docs/* + mkdir -p docs + + - name: Commit changes + run: | + git config --global user.name 'github-actions[bot]' + git config --global user.email 'github-actions[bot]@users.noreply.github.com' + git add docs/ + git commit -m "Clean up docs directory" || echo "No changes to commit" + git push + + render-quarto-book: + name: Render Quarto Book + needs: [yaml-check, clean-docs] + runs-on: ubuntu-latest + container: + image: ${{needs.yaml-check.outputs.rendering_docker_image}} + + steps: + - name: checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + token: ${{ secrets.GH_PAT }} + + - name: Login as github actions bot + run: | + git config --global --add safe.directory $GITHUB_WORKSPACE + git config --global user.name 'github-actions[bot]' + git config --global user.email 'github-actions[bot]@users.noreply.github.com' + echo ${{needs.yaml-check.outputs.rendering_docker_image}} + + # Run quarto::quarto_render() + - name: Run quarto render + id: quarto-render + run: | + Rscript -e "quarto::quarto_render()" + + # This checks on the steps before it and makes sure that they completed. + # If the renders didn't complete we don't want to commit the file changes + - name: Check on render step + if: steps.quarto-render.outcome != 'success' + run: | + echo Quarto Render status ${{steps.quarto-render.outcome}} + exit 1 + + # Commit the rendered files inside docs/ + - name: Commit rendered files + env: + GH_PAT: ${{ secrets.GH_PAT }} + run: | + git remote set-url origin https://${GH_PAT}@github.com/${GITHUB_REPOSITORY} + git fetch origin + git add --force docs/* + git commit -m 'Render Quarto Book' || echo "No changes to commit" + git pull --allow-unrelated-histories --strategy-option=ours + git push -u origin main || echo "No changes to push" + + render-tocless: + name: Render TOC-less Quarto Book + needs: [yaml-check, clean-docs, render-quarto-book] + runs-on: ubuntu-latest + container: + image: ${{needs.yaml-check.outputs.rendering_docker_image}} + if: ${{needs.yaml-check.outputs.toggle_coursera == 'yes' || needs.yaml-check.outputs.toggle_leanpub == 'yes'}} + + steps: + - name: checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + token: ${{ secrets.GH_PAT }} + + - name: Login as github-actions bot + run: | + git config --global --add safe.directory $GITHUB_WORKSPACE + git config --global user.name 'github-actions[bot]' + git config --global user.email 'github-actions[bot]@users.noreply.github.com' + + # Rendered content for Leanpub and Coursera is similar. + # This job creates a shared scaffold for both. + - name: Run TOC-less version of render + id: toc_less_quarto + run: Rscript -e "quarto::quarto_render('.', quarto_args = c('--output-dir', 'docs/no_toc'), metadata = list(sidebar = F, toc = F))" + + # Commit the TOC-less version files + - name: Commit TOC-less Quarto files + env: + GH_PAT: ${{ secrets.GH_PAT }} + run: | + git remote set-url origin https://${GH_PAT}@github.com/${GITHUB_REPOSITORY} + git fetch origin + git add --force docs/no_toc/* + git commit -m 'Render TOC-less Quarto Book' || echo "No changes to commit" + git pull --allow-unrelated-histories --strategy-option=ours + git push -u origin main || echo "No changes to push" diff --git a/inst/style-sets/custom/404.qmd b/inst/style-sets/custom/404.qmd new file mode 100644 index 0000000..5309332 --- /dev/null +++ b/inst/style-sets/custom/404.qmd @@ -0,0 +1,7 @@ +--- +title: "Page Not Found" +--- + +The page you requested cannot be found (perhaps it was moved or renamed). + +Try going back to the previous page or leave a [GitHub issue](https://github.com/fhdsl/ottr/issues/new) for more information. \ No newline at end of file diff --git a/inst/style-sets/custom/_quarto.yml b/inst/style-sets/custom/_quarto.yml new file mode 100644 index 0000000..3f1ac82 --- /dev/null +++ b/inst/style-sets/custom/_quarto.yml @@ -0,0 +1,65 @@ +project: + type: book + output-dir: docs + +book: + title: "Quarto Based OTTR Course" + author: "Fred Hutch Data Science Lab" + date: "1/1/2025" + favicon: img/favicon.ico + bread-crumbs: false + + page-navigation: true + search: true + repo-url: https://github.com/fhdsl/ottr + repo-actions: [edit, issue] + + chapters: + - index.qmd + - intro.qmd + + sidebar: + logo: "img/logo.png" + logo-href: "https://hutchdatascience.org/" + foreground: "#1B365D" + + page-footer: + left: | + This book was built with Quarto using + OTTR. + center: | + All illustrations CC-BY. +
+ All other materials CC-BY unless noted otherwise. + right: + - icon: github + href: https://github.com/fhdsl + - icon: slack + href: https://fhdata.slack.com/join/signup#/domain-signup + + +bibliography: references.bib + +format: + html: + theme: + - theme.scss + grid: + sidebar-width: 260px + css: style.css + linkcolor: "#00C1D5" + mainfont: "Karla" + + sidebar: true + toc: true + + code-link: true + code-copy: true + + link-external-newwindow: true + + image: img/favicon.ico + license: "CC BY" +knitr: + opts_chunk: + fig.path: "resources/images/figure/" diff --git a/inst/style-sets/custom/config_automation.yml b/inst/style-sets/custom/config_automation.yml new file mode 100644 index 0000000..a5fb422 --- /dev/null +++ b/inst/style-sets/custom/config_automation.yml @@ -0,0 +1,24 @@ + +##### Checks run at pull request ##### +# Check quiz formatting +check-quizzes: no +# Check that urls in the content are not broken +url-checker: yes +# Render preview of content with changes (Rmd's and md's are checked) +render-preview: yes +# Spell check Rmds and quizzes +spell-check: yes +# Style any R code +style-code: yes +# Test build the docker image if any docker-relevant files have been changed +docker-test: no + +##### Renderings run upon merge to main branch ##### +# Rendering each platform's content +render-bookdown: yes +render-leanpub: yes +render-coursera: no + +# What docker image should be used for rendering? +# The default is jhudsl/base_ottr:latest +rendering-docker-image: 'jhudsl/ottr_quarto:latest' diff --git a/inst/style-sets/custom/img/box-images/dictionary.png b/inst/style-sets/custom/img/box-images/dictionary.png new file mode 100644 index 0000000..75ddac7 Binary files /dev/null and b/inst/style-sets/custom/img/box-images/dictionary.png differ diff --git a/inst/style-sets/custom/img/box-images/github.png b/inst/style-sets/custom/img/box-images/github.png new file mode 100644 index 0000000..a93acd3 Binary files /dev/null and b/inst/style-sets/custom/img/box-images/github.png differ diff --git a/inst/style-sets/custom/img/box-images/note.png b/inst/style-sets/custom/img/box-images/note.png new file mode 100644 index 0000000..72de3ae Binary files /dev/null and b/inst/style-sets/custom/img/box-images/note.png differ diff --git a/inst/style-sets/custom/img/box-images/thinking_face.png b/inst/style-sets/custom/img/box-images/thinking_face.png new file mode 100644 index 0000000..c2c279a Binary files /dev/null and b/inst/style-sets/custom/img/box-images/thinking_face.png differ diff --git a/inst/style-sets/custom/img/box-images/under_construction.png b/inst/style-sets/custom/img/box-images/under_construction.png new file mode 100644 index 0000000..a67bd5c Binary files /dev/null and b/inst/style-sets/custom/img/box-images/under_construction.png differ diff --git a/inst/style-sets/custom/img/box-images/warning.png b/inst/style-sets/custom/img/box-images/warning.png new file mode 100644 index 0000000..405fb61 Binary files /dev/null and b/inst/style-sets/custom/img/box-images/warning.png differ diff --git a/inst/style-sets/custom/img/favicon.ico b/inst/style-sets/custom/img/favicon.ico new file mode 100644 index 0000000..f41ff9b Binary files /dev/null and b/inst/style-sets/custom/img/favicon.ico differ diff --git a/inst/style-sets/custom/index.qmd b/inst/style-sets/custom/index.qmd new file mode 100644 index 0000000..0f24338 --- /dev/null +++ b/inst/style-sets/custom/index.qmd @@ -0,0 +1,14 @@ +# Quarto Based OTTR Course {.unnumbered} + +This course is part of a series of courses for the [Informatics Technology for Cancer Research (ITCR)](https://itcr.cancer.gov/) called the Informatics Technology for Cancer Research Education Resource. This material was created by the ITCR Training Network (ITN) which is a collaborative effort of researchers around the United States to support cancer informatics and data science training through resources, technology, and events. This initiative is funded by the following grant: [National Cancer Institute (NCI)](https://www.cancer.gov/) UE5 CA254170. Our courses feature tools developed by ITCR Investigators and make it easier for principal investigators, scientists, and analysts to integrate cancer informatics into their workflows. Please see our website at [www.itcrtraining.org](www.itcrtraining.org) for more information. + + +## Available Course Formats + +This course is available in multiple formats which allows you to take it in the way that best suites your needs. You can take it for certificate which can be for free or fee. + +- The material for this course can be viewed without login requirement on this [website](https://www.ottrproject.org/). This format might be most appropriate for you if you rely on screen-reader technology. +- This course can be taken for [free certification through Leanpub](https://leanpub.com/). +- This course can be taken on [Coursera for certification here](https://www.coursera.org/) (but it is not available for free on Coursera). +- Our courses are open source, you can find the [source material for this course on GitHub](https://github.com/fhdsl/ottr). + diff --git a/inst/style-sets/custom/intro.qmd b/inst/style-sets/custom/intro.qmd new file mode 100644 index 0000000..efaf241 --- /dev/null +++ b/inst/style-sets/custom/intro.qmd @@ -0,0 +1,220 @@ +# New Chapter + +## Learning Objectives + +Every chapter also needs Learning objectives. + +## Libraries + +For this chapter, we'll need the following packages attached: + +*Remember to add [any additional packages you need to your course's own docker image](https://github.com/jhudsl/OTTR_Template/wiki/Using-Docker#starting-a-new-docker-image). + +```{r} +library(magrittr) +``` + +## Topic of Section + +You can write all your text in sections like this, using `##` to indicate a new header. you can use additional pound symbols to create lower levels of headers. + +See [here](https://www.rstudio.com/wp-content/uploads/2015/02/rmarkdown-cheatsheet.pdf) for additional general information about how you can format text within R Markdown files. In addition, see [here](https://pandoc.org/MANUAL.html#pandocs-markdown) for more in depth and advanced options. + +### Subtopic + +Here's a subheading (using three pound symbols) and some text in this subsection! + +## Code examples + +You can demonstrate code like this: + +```{r} +output_dir <- file.path("resources", "code_output") +if (!dir.exists(output_dir)) { + dir.create(output_dir) +} +``` + +And make plots too: + +```{r} +hist_plot <- hist(iris$Sepal.Length) +``` + +You can also save these plots to file: + +```{r} +png(file.path(output_dir, "test_plot.png")) +hist_plot +dev.off() +``` + + +## Image example + +How to include a Google slide. It's simplest to use the `ottrpal` package: + +```{r} +#| fig-align: "center" +#| fig-alt: "Major point!! example image" +#| echo: false +#| out-width: "100%" +ottrpal::include_slide("https://docs.google.com/presentation/d/1Dw_rBb1hySN_76xh9-x5J2dWF_das9BAUjQigf2fN-E/edit#slide=id.g252f18e2576_1_0") +``` + + +## Video examples + +You may also want to embed videos in your course. If alternatively, you just want to include a link you can do so like this: + +Check out this [link to a video](https://www.youtube.com/embed/VOCYL-FNbr0) using markdown syntax. + +### Using `knitr` + +To embed videos in your course, you can use `knitr::include_url()` like this: +Note that you should use `echo=FALSE` in the code chunk because we don't want the code part of this to show up. If you are unfamiliar with [how R Markdown code chunks work, read this](https://rmarkdown.rstudio.com/lesson-3.html). + + +```{r} +#| echo: false +knitr::include_url("https://www.youtube.com/embed/VOCYL-FNbr0") +``` + +### Using HTML + + + +### Using `knitr` + +```{r, fig.align="center", echo=FALSE, out.width="100%"} +knitr::include_url("https://drive.google.com/file/d/1mm72K4V7fqpgAfWkr6b7HTZrc3f-T6AV/preview") +``` + +### Using HTML + + + +## Website Examples + +Yet again you can use a link to a website like so: + +[A Website](https://yihui.org) + +You might want to have users open a website in a new tab by default, especially if they need to reference both the course and a resource at once. + +[A Website](https://yihui.org){target="_blank"} + +Or, you can embed some websites. + +### Using `knitr` + +This works: + +```{r, fig.align="center", echo=FALSE} +knitr::include_url("https://yihui.org") +``` + + +### Using HTML + + + + +## Stylized boxes + +Occasionally, you might find it useful to emphasize a particular piece of information. To help you do so, we have provided css code and images (no need for you to worry about that!) to create the following stylized boxes. + +You can use these boxes in your course with either of two options: using HTML code or Pandoc syntax. + +### Using `rmarkdown` container syntax + +The `rmarkdown` package allows for a different syntax to be converted to the HTML that you just saw and also allows for conversion to LaTeX. See the [Bookdown](https://bookdown.org/yihui/rmarkdown-cookbook/custom-blocks.html) documentation for more information. Note that Bookdown uses Pandoc. + + +``` +::: {.notice} +Note using rmarkdown syntax. + +::: +``` + +::: {.notice} +Note using rmarkdown syntax. + +::: + +As an example you might do something like this: + +::: {.notice} +Please click on the subsection headers in the left hand +navigation bar (e.g., 2.1, 4.3) a second time to expand the +table of contents and enable the `scroll_highlight` feature +([see more](introduction.html#scroll-highlight)) +::: + + +### Using HTML + +To add a warning box like the following use: + +
+Followed by the text you want inside +
+ +This will create the following: + +
+ +Followed by the text you want inside + +
+ +Here is a `
` box: + +
+ +Note text + +
+ +Here is a `
` box: + +
+ +GitHub text + +
+ + +Here is a `
` box: + +
+ +dictionary text + +
+ + +Here is a `
` box: + +
+ +reflection text + +
+ + +Here is a `
` box: + +
+ +Work in Progress text + +
+ + +## Dropdown summaries + +
You can hide additional information in a dropdown menu +Here's more words that are hidden. +
diff --git a/inst/style-sets/custom/references.bib b/inst/style-sets/custom/references.bib new file mode 100644 index 0000000..0220dbd --- /dev/null +++ b/inst/style-sets/custom/references.bib @@ -0,0 +1,19 @@ +@article{knuth84, + author = {Knuth, Donald E.}, + title = {Literate Programming}, + year = {1984}, + issue_date = {May 1984}, + publisher = {Oxford University Press, Inc.}, + address = {USA}, + volume = {27}, + number = {2}, + issn = {0010-4620}, + url = {https://doi.org/10.1093/comjnl/27.2.97}, + doi = {10.1093/comjnl/27.2.97}, + journal = {Comput. J.}, + month = may, + pages = {97–111}, + numpages = {15} +} + + diff --git a/inst/style-sets/custom/style.css b/inst/style-sets/custom/style.css new file mode 100755 index 0000000..bd8efe3 --- /dev/null +++ b/inst/style-sets/custom/style.css @@ -0,0 +1,179 @@ +/* CUSTOMIZE */ +/* Imports fonts from Google Fonts (Abril Fatface, Karla, and Lora) with different weights and styles */ +@import url('https://fonts.googleapis.com/css?family=Abril+Fatface|Karla:400,400i,700,700i|Lora:400,400i,700,700i&display=swap'); + +/* Styles for paragraph captions, setting their color and margin */ +p.caption { + color: #777; + margin-top: 10px; +} + +/* Styles for paragraph code, which inherit white-space property */ +p code { + white-space: inherit; +} + +/* Styles for pre elements to prevent words from breaking unnaturally */ +pre { + word-break: normal; + word-wrap: normal; +} + +/* Inherits the white-space property for consistent code formatting */ +pre code { + white-space: inherit; +} + +/* CUSTOMIZE */ +/*------------- Header text---------------- */ +h1, h2, h3, h4 { + font-family: 'Lora', arial, sans-serif; +} + +.title { + font-family: 'Lora'; + font-size: 4em !important; + color: #012d72; + margin-top: 0.275em !important; + margin-bottom: 0.35em !important; +} + +.subtitle { + font-family: 'Lora'; + color: #0b8d96; +} + +/* CUSTOMIZE */ +/* Sidebar Logo */ +.sidebar-logo {} + +/* Stylized boxes */ +div.notice, div.warning, div.github, div.dictionary, div.reflection, div.wip { + padding: 1em; + margin: 1em 0; + padding-left: 100px; + min-height: 120px; + background-repeat: no-repeat; +} + +div.notice{ + border: 4px #68ace5; + border-style: solid; + background-size: 70px; + background-position: 15px center; + background-color: #e8ebee; + background-image: url("/img/box-images/note.png"); +} + + +div.warning{ + border: 4px #e0471c; + border-style: solid; + background-size: 70px; + background-position: 15px center; + background-color: #e8ebee; + background-image: url("/img/box-images/warning.png"); +} + +div.github{ + border: 4px #000000; + border-style: solid; + background-size: 70px; + background-position: 15px center; + background-color: #e8ebee; + background-image: url("/img/box-images/github.png"); +} + +div.dictionary{ + border: 4px #68ace5; + border-style: solid; + background-size: 70px; + background-position: 15px center; + background-color: #e8ebee; + background-image: url("/img/box-images/dictionary.png"); +} + +div.reflection{ + border: 4px #68ace5; + border-style: solid; + background-size: 90px; + background-position: 15px center; + background-color: #e8ebee; + background-image: url("/img/box-images/thinking_face.png"); +} + +div.wip{ + border: 4px #000000; + border-style: solid; + background-size: 70px; + background-position: 15px center; + background-color: #f4d03f; + background-image: url("/img/box-images/under_construction.png"); +} + +/* CUSTOMIZE */ +/* Navbar */ +.chapter-title { + text-transform: none; +} +.menu-text { + text-transform: uppercase; +} + + + +/* iframes */ +iframe { + -moz-transform-origin: top left; + -webkit-transform-origin: top left; + -o-transform-origin: top left; + -ms-transform-origin: top left; + transform-origin: top left; +} + +.iframe-container { + overflow: auto; + -webkit-overflow-scrolling: touch; + border: #ddd 2px solid; + box-shadow: #888 0px 5px 8px; + margin-bottom: 1em; +} + +.iframe-container > iframe { + border: none; +} + +/* CUSTOMIZE */ +/* Footer */ +.footer { + font-family: "Lora", serif; + font-size: 1em; + color: #193a5c; +} + +/* CUSTOMIZE */ +/* Navbar Header */ +.navbar-logo { + max-height: 33px; +} + +/* CUSTOMIZE */ +/* Navbar Footer */ +.nav-footer { + display: flex; + flex-direction: row; + flex-wrap: wrap; + justify-content: space-between; + align-items: baseline; + text-align: center; + padding-top: .5rem; + padding-bottom: .5rem; + background-color: #1B365D; + color: #fff !important; +} + + +/* Sidebar Hover Color */ +div.sidebar-item-container .active, div.sidebar-item-container .show>.nav-link, div.sidebar-item-container .sidebar-link>code { + color: #00C1D5; +} diff --git a/inst/style-sets/custom/theme.scss b/inst/style-sets/custom/theme.scss new file mode 100644 index 0000000..cef4f5c --- /dev/null +++ b/inst/style-sets/custom/theme.scss @@ -0,0 +1,2 @@ +/*-- scss:defaults --*/ +$toc-color: #00C1D5; diff --git a/inst/style-sets/fhdasl/.github/workflows/delete-preview.yml b/inst/style-sets/fhdasl/.github/workflows/delete-preview.yml new file mode 100644 index 0000000..7d8cf01 --- /dev/null +++ b/inst/style-sets/fhdasl/.github/workflows/delete-preview.yml @@ -0,0 +1,25 @@ +name: Delete Preview + +on: + pull_request: + types: [closed] + +jobs: + delete-preview: + runs-on: ubuntu-latest + steps: + + # This is because if a PR is closed before a render finishes it won't find it. + - name: Sleep for 5 minutes + run: sleep 300s + shell: bash + + # Check out current repository + - name: checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + # Delete the branch! + - name: Delete branch locally and remotely + run: git push origin --delete preview-${{ github.event.pull_request.number }} || echo "No branch to delete" diff --git a/inst/style-sets/fhdasl/.github/workflows/pull_request.yml b/inst/style-sets/fhdasl/.github/workflows/pull_request.yml new file mode 100644 index 0000000..5b9ee7b --- /dev/null +++ b/inst/style-sets/fhdasl/.github/workflows/pull_request.yml @@ -0,0 +1,169 @@ +name: Pull Request + +on: + pull_request: + branches: [ main, staging ] + +jobs: + yaml-check: + name: Load user automation choices + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + # Use the yaml-env-action action. + - name: Load environment from YAML + uses: doughepi/yaml-env-action@v1.0.0 + with: + files: config_automation.yml # Pass a space-separated list of configuration files. Rightmost files take precedence. + + # Delete the branch if this has been run before + - name: Delete branch locally and remotely + run: git push origin --delete preview-${{ github.event.pull_request.number }} || echo "No branch to delete" + + # Make the branch fresh + - name: Make the branch fresh + run: | + git config --global --add safe.directory $GITHUB_WORKSPACE + git config --global user.name 'github-actions[bot]' + git config --global user.email 'github-actions[bot]@users.noreply.github.com' + + branch_name='preview-${{ github.event.pull_request.number }}' + echo branch doesnt exist + git checkout -b $branch_name || echo branch exists + git push --set-upstream origin $branch_name + shell: bash + + outputs: + public_repository: "${{ steps.public_repository.outputs.public }}" + toggle_spell_check: "${{ env.SPELL_CHECK }}" + toggle_url_check: "${{ env.URL_CHECKER }}" + toggle_render_preview: "${{ env.RENDER_PREVIEW }}" + rendering_docker_image: "${{ env.RENDERING_DOCKER_IMAGE }}" + +########################## Make the error reports ############################## + spell-check: + name: Check spelling + needs: yaml-check + if: ${{needs.yaml-check.outputs.toggle_spell_check == 'yes'}} + uses: jhudsl/ottr-reports/.github/workflows/report-maker.yml@main + with: + check_type: spelling + error_min: 3 + gh_pat: secrets.GH_PAT + + url-check: + name: Check URLs + needs: yaml-check + if: ${{needs.yaml-check.outputs.toggle_url_check == 'yes'}} + uses: jhudsl/ottr-reports/.github/workflows/report-maker.yml@main + with: + check_type: urls + error_min: 0 + gh_pat: secrets.GH_PAT + + render-preview: + name: Render preview + needs: yaml-check + runs-on: ubuntu-latest + container: + image: ${{needs.yaml-check.outputs.rendering_docker_image}} + if: ${{needs.yaml-check.outputs.toggle_render_preview == 'yes'}} + + steps: + - name: Checkout files + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + # Set up git checkout + - name: Set up git checkout + run: | + git config --global --add safe.directory $GITHUB_WORKSPACE + git config --global user.name 'github-actions[bot]' + git config --global user.email 'github-actions[bot]@users.noreply.github.com' + + branch_name='preview-${{ github.event.pull_request.number }}' + git fetch --all + git checkout $branch_name + git merge -s recursive --strategy-option=theirs origin/${{ github.head_ref }} --allow-unrelated-histories + shell: bash + + # Now we want to render all the html files from the qmd files + - name: Run render html + id: site + run: quarto render + + # This checks on the steps before it and makes sure that they completed. + # If the renders didn't complete we don't want to commit the file changes + - name: Check on render steps + if: steps.site.outcome != 'success' + run: | + echo site status ${{steps.site.outcome}} + exit 1 + + - name: Website preview for download + run: zip website-preview.zip docs/* -r + + # Commit the rendered website files + - name: Commit rendered website files to preview branch + id: commit + run: | + branch_name='preview-${{ github.event.pull_request.number }}' + git diff origin/main -- '*.html' >/dev/null && changes=true || changes=false + echo "changes=$changes" >> $GITHUB_OUTPUT + git add . --force + git commit -m 'Render preview' || echo "No changes to commit" + git pull --set-upstream origin $branch_name --allow-unrelated-histories --strategy-option=ours + git push --force || echo "No changes to commit" + shell: bash + + - name: Find Comment + uses: peter-evans/find-comment@v1 + id: fc + with: + issue-number: ${{ github.event.pull_request.number }} + comment-author: 'github-actions[bot]' + body-includes: latest commit + + - name: Build components of the comment + id: build-components + run: | + course_name=$(head -n 1 _website.yml | cut -d'"' -f 2| tr " " "-") + website_link=$(echo "https://htmlpreview.github.io/?https://raw.githubusercontent.com/$GITHUB_REPOSITORY/preview-${{ github.event.pull_request.number }}/docs/index.html") + docs_link=$(echo "https://github.com/$GITHUB_REPOSITORY/raw/preview-${{ github.event.pull_request.number }}/website-preview.zip") + echo "docs_link=$docs_link" >> $GITHUB_OUTPUT + echo "website_link=$website_link" >> $GITHUB_OUTPUT + echo "time=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT + echo "commit_id=$GITHUB_SHA" >> $GITHUB_OUTPUT + echo ${{steps.commit.outputs.changes}} + + - name: Create or update comment + if: steps.commit.outputs.changes == 'true' + uses: peter-evans/create-or-update-comment@v1 + with: + comment-id: ${{ steps.fc.outputs.comment-id }} + issue-number: ${{ github.event.pull_request.number }} + body: | + :eyes: [Quick Preview of Website](${{ steps.build-components.outputs.website_link }}) - Click for a preview of recent changes. + :file_folder: [Download Full Website](${{ steps.build-components.outputs.docs_link }}) - Download complete Zip file of the website. + + The Quick Preview may not display all HTML features accurately, but it provides a basic overview. + + _Updated at ${{ steps.build-components.outputs.time }} with changes from the latest commit ${{ steps.build-components.outputs.commit_id }}_ + edit-mode: replace + + - name: No comment if no changes + if: steps.commit.outputs.changes == 'false' + uses: peter-evans/create-or-update-comment@v1 + with: + comment-id: ${{ steps.fc.outputs.comment-id }} + issue-number: ${{ github.event.pull_request.number }} + body: | + The latest commit did not produce rendering changes. + + _Updated at ${{ steps.build-components.outputs.time }} with changes from ${{ steps.build-components.outputs.commit_id }}_ + edit-mode: replace diff --git a/inst/style-sets/fhdasl/.github/workflows/render-all.yml b/inst/style-sets/fhdasl/.github/workflows/render-all.yml new file mode 100644 index 0000000..775e2db --- /dev/null +++ b/inst/style-sets/fhdasl/.github/workflows/render-all.yml @@ -0,0 +1,133 @@ +name: Render All Output + +on: + workflow_dispatch: + push: + branches: [ main ] + paths: + - '**/*.qmd' + +jobs: + yaml-check: + name: Load User Automation Choices + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + # Use the yaml-env-action action. + - name: Load environment from YAML + uses: doughepi/yaml-env-action@v1.0.0 + with: + files: config_automation.yml # Pass a space-separated list of configuration files. Rightmost files take precedence. + outputs: + toggle_coursera: "${{ env.RENDER_COURSERA }}" + toggle_leanpub: "${{ env.RENDER_LEANPUB }}" + rendering_docker_image: "${{ env.RENDERING_DOCKER_IMAGE }}" + + clean-docs: + name: Clean docs folder + needs: yaml-check + runs-on: ubuntu-latest + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + + - name: Delete all files inside docs + run: | + rm -rf docs/* + mkdir -p docs + + - name: Commit changes + run: | + git config --global user.name 'github-actions[bot]' + git config --global user.email 'github-actions[bot]@users.noreply.github.com' + git add docs/ + git commit -m "Clean up docs directory" || echo "No changes to commit" + git push + + render-quarto-book: + name: Render Quarto Book + needs: [yaml-check, clean-docs] + runs-on: ubuntu-latest + container: + image: ${{needs.yaml-check.outputs.rendering_docker_image}} + + steps: + - name: checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + token: ${{ secrets.GH_PAT }} + + - name: Login as github actions bot + run: | + git config --global --add safe.directory $GITHUB_WORKSPACE + git config --global user.name 'github-actions[bot]' + git config --global user.email 'github-actions[bot]@users.noreply.github.com' + echo ${{needs.yaml-check.outputs.rendering_docker_image}} + + # Run quarto::quarto_render() + - name: Run quarto render + id: quarto-render + run: | + Rscript -e "quarto::quarto_render()" + + # This checks on the steps before it and makes sure that they completed. + # If the renders didn't complete we don't want to commit the file changes + - name: Check on render step + if: steps.quarto-render.outcome != 'success' + run: | + echo Quarto Render status ${{steps.quarto-render.outcome}} + exit 1 + + # Commit the rendered files inside docs/ + - name: Commit rendered files + env: + GH_PAT: ${{ secrets.GH_PAT }} + run: | + git remote set-url origin https://${GH_PAT}@github.com/${GITHUB_REPOSITORY} + git fetch origin + git add --force docs/* + git commit -m 'Render Quarto Book' || echo "No changes to commit" + git pull --allow-unrelated-histories --strategy-option=ours + git push -u origin main || echo "No changes to push" + + render-tocless: + name: Render TOC-less Quarto Book + needs: [yaml-check, clean-docs, render-quarto-book] + runs-on: ubuntu-latest + container: + image: ${{needs.yaml-check.outputs.rendering_docker_image}} + if: ${{needs.yaml-check.outputs.toggle_coursera == 'yes' || needs.yaml-check.outputs.toggle_leanpub == 'yes'}} + + steps: + - name: checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + token: ${{ secrets.GH_PAT }} + + - name: Login as github-actions bot + run: | + git config --global --add safe.directory $GITHUB_WORKSPACE + git config --global user.name 'github-actions[bot]' + git config --global user.email 'github-actions[bot]@users.noreply.github.com' + + # Rendered content for Leanpub and Coursera is similar. + # This job creates a shared scaffold for both. + - name: Run TOC-less version of render + id: toc_less_quarto + run: Rscript -e "quarto::quarto_render('.', quarto_args = c('--output-dir', 'docs/no_toc'), metadata = list(sidebar = F, toc = F))" + + # Commit the TOC-less version files + - name: Commit TOC-less Quarto files + env: + GH_PAT: ${{ secrets.GH_PAT }} + run: | + git remote set-url origin https://${GH_PAT}@github.com/${GITHUB_REPOSITORY} + git fetch origin + git add --force docs/no_toc/* + git commit -m 'Render TOC-less Quarto Book' || echo "No changes to commit" + git pull --allow-unrelated-histories --strategy-option=ours + git push -u origin main || echo "No changes to push" diff --git a/inst/style-sets/fhdasl/404.qmd b/inst/style-sets/fhdasl/404.qmd new file mode 100644 index 0000000..5309332 --- /dev/null +++ b/inst/style-sets/fhdasl/404.qmd @@ -0,0 +1,7 @@ +--- +title: "Page Not Found" +--- + +The page you requested cannot be found (perhaps it was moved or renamed). + +Try going back to the previous page or leave a [GitHub issue](https://github.com/fhdsl/ottr/issues/new) for more information. \ No newline at end of file diff --git a/inst/style-sets/fhdasl/_quarto.yml b/inst/style-sets/fhdasl/_quarto.yml new file mode 100644 index 0000000..3f1ac82 --- /dev/null +++ b/inst/style-sets/fhdasl/_quarto.yml @@ -0,0 +1,65 @@ +project: + type: book + output-dir: docs + +book: + title: "Quarto Based OTTR Course" + author: "Fred Hutch Data Science Lab" + date: "1/1/2025" + favicon: img/favicon.ico + bread-crumbs: false + + page-navigation: true + search: true + repo-url: https://github.com/fhdsl/ottr + repo-actions: [edit, issue] + + chapters: + - index.qmd + - intro.qmd + + sidebar: + logo: "img/logo.png" + logo-href: "https://hutchdatascience.org/" + foreground: "#1B365D" + + page-footer: + left: | + This book was built with Quarto using + OTTR. + center: | + All illustrations CC-BY. +
+ All other materials CC-BY unless noted otherwise. + right: + - icon: github + href: https://github.com/fhdsl + - icon: slack + href: https://fhdata.slack.com/join/signup#/domain-signup + + +bibliography: references.bib + +format: + html: + theme: + - theme.scss + grid: + sidebar-width: 260px + css: style.css + linkcolor: "#00C1D5" + mainfont: "Karla" + + sidebar: true + toc: true + + code-link: true + code-copy: true + + link-external-newwindow: true + + image: img/favicon.ico + license: "CC BY" +knitr: + opts_chunk: + fig.path: "resources/images/figure/" diff --git a/inst/style-sets/fhdasl/config_automation.yml b/inst/style-sets/fhdasl/config_automation.yml new file mode 100644 index 0000000..a5fb422 --- /dev/null +++ b/inst/style-sets/fhdasl/config_automation.yml @@ -0,0 +1,24 @@ + +##### Checks run at pull request ##### +# Check quiz formatting +check-quizzes: no +# Check that urls in the content are not broken +url-checker: yes +# Render preview of content with changes (Rmd's and md's are checked) +render-preview: yes +# Spell check Rmds and quizzes +spell-check: yes +# Style any R code +style-code: yes +# Test build the docker image if any docker-relevant files have been changed +docker-test: no + +##### Renderings run upon merge to main branch ##### +# Rendering each platform's content +render-bookdown: yes +render-leanpub: yes +render-coursera: no + +# What docker image should be used for rendering? +# The default is jhudsl/base_ottr:latest +rendering-docker-image: 'jhudsl/ottr_quarto:latest' diff --git a/inst/style-sets/fhdasl/img/box-images/dictionary.png b/inst/style-sets/fhdasl/img/box-images/dictionary.png new file mode 100644 index 0000000..75ddac7 Binary files /dev/null and b/inst/style-sets/fhdasl/img/box-images/dictionary.png differ diff --git a/inst/style-sets/fhdasl/img/box-images/github.png b/inst/style-sets/fhdasl/img/box-images/github.png new file mode 100644 index 0000000..a93acd3 Binary files /dev/null and b/inst/style-sets/fhdasl/img/box-images/github.png differ diff --git a/inst/style-sets/fhdasl/img/box-images/note.png b/inst/style-sets/fhdasl/img/box-images/note.png new file mode 100644 index 0000000..72de3ae Binary files /dev/null and b/inst/style-sets/fhdasl/img/box-images/note.png differ diff --git a/inst/style-sets/fhdasl/img/box-images/thinking_face.png b/inst/style-sets/fhdasl/img/box-images/thinking_face.png new file mode 100644 index 0000000..c2c279a Binary files /dev/null and b/inst/style-sets/fhdasl/img/box-images/thinking_face.png differ diff --git a/inst/style-sets/fhdasl/img/box-images/under_construction.png b/inst/style-sets/fhdasl/img/box-images/under_construction.png new file mode 100644 index 0000000..a67bd5c Binary files /dev/null and b/inst/style-sets/fhdasl/img/box-images/under_construction.png differ diff --git a/inst/style-sets/fhdasl/img/box-images/warning.png b/inst/style-sets/fhdasl/img/box-images/warning.png new file mode 100644 index 0000000..405fb61 Binary files /dev/null and b/inst/style-sets/fhdasl/img/box-images/warning.png differ diff --git a/inst/style-sets/fhdasl/img/favicon.ico b/inst/style-sets/fhdasl/img/favicon.ico new file mode 100644 index 0000000..f41ff9b Binary files /dev/null and b/inst/style-sets/fhdasl/img/favicon.ico differ diff --git a/inst/style-sets/fhdasl/img/logo.png b/inst/style-sets/fhdasl/img/logo.png new file mode 100644 index 0000000..4bf74fc Binary files /dev/null and b/inst/style-sets/fhdasl/img/logo.png differ diff --git a/inst/style-sets/fhdasl/index.qmd b/inst/style-sets/fhdasl/index.qmd new file mode 100644 index 0000000..0f24338 --- /dev/null +++ b/inst/style-sets/fhdasl/index.qmd @@ -0,0 +1,14 @@ +# Quarto Based OTTR Course {.unnumbered} + +This course is part of a series of courses for the [Informatics Technology for Cancer Research (ITCR)](https://itcr.cancer.gov/) called the Informatics Technology for Cancer Research Education Resource. This material was created by the ITCR Training Network (ITN) which is a collaborative effort of researchers around the United States to support cancer informatics and data science training through resources, technology, and events. This initiative is funded by the following grant: [National Cancer Institute (NCI)](https://www.cancer.gov/) UE5 CA254170. Our courses feature tools developed by ITCR Investigators and make it easier for principal investigators, scientists, and analysts to integrate cancer informatics into their workflows. Please see our website at [www.itcrtraining.org](www.itcrtraining.org) for more information. + + +## Available Course Formats + +This course is available in multiple formats which allows you to take it in the way that best suites your needs. You can take it for certificate which can be for free or fee. + +- The material for this course can be viewed without login requirement on this [website](https://www.ottrproject.org/). This format might be most appropriate for you if you rely on screen-reader technology. +- This course can be taken for [free certification through Leanpub](https://leanpub.com/). +- This course can be taken on [Coursera for certification here](https://www.coursera.org/) (but it is not available for free on Coursera). +- Our courses are open source, you can find the [source material for this course on GitHub](https://github.com/fhdsl/ottr). + diff --git a/inst/style-sets/fhdasl/intro.qmd b/inst/style-sets/fhdasl/intro.qmd new file mode 100644 index 0000000..efaf241 --- /dev/null +++ b/inst/style-sets/fhdasl/intro.qmd @@ -0,0 +1,220 @@ +# New Chapter + +## Learning Objectives + +Every chapter also needs Learning objectives. + +## Libraries + +For this chapter, we'll need the following packages attached: + +*Remember to add [any additional packages you need to your course's own docker image](https://github.com/jhudsl/OTTR_Template/wiki/Using-Docker#starting-a-new-docker-image). + +```{r} +library(magrittr) +``` + +## Topic of Section + +You can write all your text in sections like this, using `##` to indicate a new header. you can use additional pound symbols to create lower levels of headers. + +See [here](https://www.rstudio.com/wp-content/uploads/2015/02/rmarkdown-cheatsheet.pdf) for additional general information about how you can format text within R Markdown files. In addition, see [here](https://pandoc.org/MANUAL.html#pandocs-markdown) for more in depth and advanced options. + +### Subtopic + +Here's a subheading (using three pound symbols) and some text in this subsection! + +## Code examples + +You can demonstrate code like this: + +```{r} +output_dir <- file.path("resources", "code_output") +if (!dir.exists(output_dir)) { + dir.create(output_dir) +} +``` + +And make plots too: + +```{r} +hist_plot <- hist(iris$Sepal.Length) +``` + +You can also save these plots to file: + +```{r} +png(file.path(output_dir, "test_plot.png")) +hist_plot +dev.off() +``` + + +## Image example + +How to include a Google slide. It's simplest to use the `ottrpal` package: + +```{r} +#| fig-align: "center" +#| fig-alt: "Major point!! example image" +#| echo: false +#| out-width: "100%" +ottrpal::include_slide("https://docs.google.com/presentation/d/1Dw_rBb1hySN_76xh9-x5J2dWF_das9BAUjQigf2fN-E/edit#slide=id.g252f18e2576_1_0") +``` + + +## Video examples + +You may also want to embed videos in your course. If alternatively, you just want to include a link you can do so like this: + +Check out this [link to a video](https://www.youtube.com/embed/VOCYL-FNbr0) using markdown syntax. + +### Using `knitr` + +To embed videos in your course, you can use `knitr::include_url()` like this: +Note that you should use `echo=FALSE` in the code chunk because we don't want the code part of this to show up. If you are unfamiliar with [how R Markdown code chunks work, read this](https://rmarkdown.rstudio.com/lesson-3.html). + + +```{r} +#| echo: false +knitr::include_url("https://www.youtube.com/embed/VOCYL-FNbr0") +``` + +### Using HTML + + + +### Using `knitr` + +```{r, fig.align="center", echo=FALSE, out.width="100%"} +knitr::include_url("https://drive.google.com/file/d/1mm72K4V7fqpgAfWkr6b7HTZrc3f-T6AV/preview") +``` + +### Using HTML + + + +## Website Examples + +Yet again you can use a link to a website like so: + +[A Website](https://yihui.org) + +You might want to have users open a website in a new tab by default, especially if they need to reference both the course and a resource at once. + +[A Website](https://yihui.org){target="_blank"} + +Or, you can embed some websites. + +### Using `knitr` + +This works: + +```{r, fig.align="center", echo=FALSE} +knitr::include_url("https://yihui.org") +``` + + +### Using HTML + + + + +## Stylized boxes + +Occasionally, you might find it useful to emphasize a particular piece of information. To help you do so, we have provided css code and images (no need for you to worry about that!) to create the following stylized boxes. + +You can use these boxes in your course with either of two options: using HTML code or Pandoc syntax. + +### Using `rmarkdown` container syntax + +The `rmarkdown` package allows for a different syntax to be converted to the HTML that you just saw and also allows for conversion to LaTeX. See the [Bookdown](https://bookdown.org/yihui/rmarkdown-cookbook/custom-blocks.html) documentation for more information. Note that Bookdown uses Pandoc. + + +``` +::: {.notice} +Note using rmarkdown syntax. + +::: +``` + +::: {.notice} +Note using rmarkdown syntax. + +::: + +As an example you might do something like this: + +::: {.notice} +Please click on the subsection headers in the left hand +navigation bar (e.g., 2.1, 4.3) a second time to expand the +table of contents and enable the `scroll_highlight` feature +([see more](introduction.html#scroll-highlight)) +::: + + +### Using HTML + +To add a warning box like the following use: + +
+Followed by the text you want inside +
+ +This will create the following: + +
+ +Followed by the text you want inside + +
+ +Here is a `
` box: + +
+ +Note text + +
+ +Here is a `
` box: + +
+ +GitHub text + +
+ + +Here is a `
` box: + +
+ +dictionary text + +
+ + +Here is a `
` box: + +
+ +reflection text + +
+ + +Here is a `
` box: + +
+ +Work in Progress text + +
+ + +## Dropdown summaries + +
You can hide additional information in a dropdown menu +Here's more words that are hidden. +
diff --git a/inst/style-sets/fhdasl/references.bib b/inst/style-sets/fhdasl/references.bib new file mode 100644 index 0000000..0220dbd --- /dev/null +++ b/inst/style-sets/fhdasl/references.bib @@ -0,0 +1,19 @@ +@article{knuth84, + author = {Knuth, Donald E.}, + title = {Literate Programming}, + year = {1984}, + issue_date = {May 1984}, + publisher = {Oxford University Press, Inc.}, + address = {USA}, + volume = {27}, + number = {2}, + issn = {0010-4620}, + url = {https://doi.org/10.1093/comjnl/27.2.97}, + doi = {10.1093/comjnl/27.2.97}, + journal = {Comput. J.}, + month = may, + pages = {97–111}, + numpages = {15} +} + + diff --git a/inst/style-sets/fhdasl/style.css b/inst/style-sets/fhdasl/style.css new file mode 100755 index 0000000..6d2b332 --- /dev/null +++ b/inst/style-sets/fhdasl/style.css @@ -0,0 +1,177 @@ +/* Imports fonts from Google Fonts (Abril Fatface, Karla, and Lora) with different weights and styles */ +@import url('https://fonts.googleapis.com/css?family=Abril+Fatface|Karla:400,400i,700,700i|Lora:400,400i,700,700i&display=swap'); + +/* Styles for paragraph captions, setting their color and margin */ +p.caption { + color: #777; + margin-top: 10px; +} + +/* Styles for paragraph code, which inherit white-space property */ +p code { + white-space: inherit; +} + +/* Styles for pre elements to prevent words from breaking unnaturally */ +pre { + word-break: normal; + word-wrap: normal; +} + +/* Inherits the white-space property for consistent code formatting */ +pre code { + white-space: inherit; +} + + +/*------------- Header text---------------- */ +h1, h2, h3, h4 { + font-family: 'Lora', arial, sans-serif; +} + +.title { + font-family: 'Lora'; + font-size: 4em !important; + color: #1B365D; + margin-top: 0.275em !important; + margin-bottom: 0.35em !important; +} + +.subtitle { + font-family: 'Lora'; + color: #0b8d96; +} + +/* Sidebar Logo */ +.sidebar-logo {} + +/* Stylized boxes */ +div.notice, div.warning, div.github, div.dictionary, div.reflection, div.wip { + padding: 1em; + margin: 1em 0; + padding-left: 100px; + min-height: 120px; + background-repeat: no-repeat; +} + +div.notice{ + border: 4px #68ace5; + border-style: solid; + background-size: 70px; + background-position: 15px center; + background-color: #e8ebee; + background-image: url("/img/box-images/note.png"); +} + + +div.warning{ + border: 4px #e0471c; + border-style: solid; + background-size: 70px; + background-position: 15px center; + background-color: #e8ebee; + background-image: url("/img/box-images/warning.png"); +} + +div.github{ + border: 4px #000000; + border-style: solid; + background-size: 70px; + background-position: 15px center; + background-color: #e8ebee; + background-image: url("/img/box-images/github.png"); +} + +div.dictionary{ + border: 4px #68ace5; + border-style: solid; + background-size: 70px; + background-position: 15px center; + background-color: #e8ebee; + background-image: url("/img/box-images/dictionary.png"); +} + +div.reflection{ + border: 4px #68ace5; + border-style: solid; + background-size: 90px; + background-position: 15px center; + background-color: #e8ebee; + background-image: url("/img/box-images/thinking_face.png"); +} + +div.wip{ + border: 4px #000000; + border-style: solid; + background-size: 70px; + background-position: 15px center; + background-color: #f4d03f; + background-image: url("/img/box-images/under_construction.png"); +} + +/* Navbar */ +.chapter-title { + text-transform: none; +} +.menu-text { + text-transform: uppercase; +} + + + +/* iframes */ +iframe { + -moz-transform-origin: top left; + -webkit-transform-origin: top left; + -o-transform-origin: top left; + -ms-transform-origin: top left; + transform-origin: top left; +} + +.iframe-container { + overflow: auto; + -webkit-overflow-scrolling: touch; + border: #ddd 2px solid; + box-shadow: #888 0px 5px 8px; + margin-bottom: 1em; +} + +.iframe-container > iframe { + border: none; +} + + +/* Footer */ +.footer { + font-family: "Lora", serif; + font-size: 1em; + color: #193a5c; +} + + +/* Navbar Header */ +.navbar-logo { + max-height: 33px; +} + + +/* Navbar Footer */ +.nav-footer { + display: flex; + flex-direction: row; + flex-wrap: wrap; + justify-content: space-between; + align-items: baseline; + text-align: center; + padding-top: .5rem; + padding-bottom: .5rem; + background-color: #1B365D; + color: #fff !important; +} + + +/* Sidebar Hover Color */ +div.sidebar-item-container .active, div.sidebar-item-container .show>.nav-link, div.sidebar-item-container .sidebar-link>code { + color: #00C1D5; +} + diff --git a/inst/style-sets/fhdasl/theme.scss b/inst/style-sets/fhdasl/theme.scss new file mode 100644 index 0000000..cef4f5c --- /dev/null +++ b/inst/style-sets/fhdasl/theme.scss @@ -0,0 +1,2 @@ +/*-- scss:defaults --*/ +$toc-color: #00C1D5; diff --git a/inst/style-sets/gdscn/.github/workflows/delete-preview.yml b/inst/style-sets/gdscn/.github/workflows/delete-preview.yml new file mode 100644 index 0000000..7d8cf01 --- /dev/null +++ b/inst/style-sets/gdscn/.github/workflows/delete-preview.yml @@ -0,0 +1,25 @@ +name: Delete Preview + +on: + pull_request: + types: [closed] + +jobs: + delete-preview: + runs-on: ubuntu-latest + steps: + + # This is because if a PR is closed before a render finishes it won't find it. + - name: Sleep for 5 minutes + run: sleep 300s + shell: bash + + # Check out current repository + - name: checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + # Delete the branch! + - name: Delete branch locally and remotely + run: git push origin --delete preview-${{ github.event.pull_request.number }} || echo "No branch to delete" diff --git a/inst/style-sets/gdscn/.github/workflows/pull_request.yml b/inst/style-sets/gdscn/.github/workflows/pull_request.yml new file mode 100644 index 0000000..5b9ee7b --- /dev/null +++ b/inst/style-sets/gdscn/.github/workflows/pull_request.yml @@ -0,0 +1,169 @@ +name: Pull Request + +on: + pull_request: + branches: [ main, staging ] + +jobs: + yaml-check: + name: Load user automation choices + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + # Use the yaml-env-action action. + - name: Load environment from YAML + uses: doughepi/yaml-env-action@v1.0.0 + with: + files: config_automation.yml # Pass a space-separated list of configuration files. Rightmost files take precedence. + + # Delete the branch if this has been run before + - name: Delete branch locally and remotely + run: git push origin --delete preview-${{ github.event.pull_request.number }} || echo "No branch to delete" + + # Make the branch fresh + - name: Make the branch fresh + run: | + git config --global --add safe.directory $GITHUB_WORKSPACE + git config --global user.name 'github-actions[bot]' + git config --global user.email 'github-actions[bot]@users.noreply.github.com' + + branch_name='preview-${{ github.event.pull_request.number }}' + echo branch doesnt exist + git checkout -b $branch_name || echo branch exists + git push --set-upstream origin $branch_name + shell: bash + + outputs: + public_repository: "${{ steps.public_repository.outputs.public }}" + toggle_spell_check: "${{ env.SPELL_CHECK }}" + toggle_url_check: "${{ env.URL_CHECKER }}" + toggle_render_preview: "${{ env.RENDER_PREVIEW }}" + rendering_docker_image: "${{ env.RENDERING_DOCKER_IMAGE }}" + +########################## Make the error reports ############################## + spell-check: + name: Check spelling + needs: yaml-check + if: ${{needs.yaml-check.outputs.toggle_spell_check == 'yes'}} + uses: jhudsl/ottr-reports/.github/workflows/report-maker.yml@main + with: + check_type: spelling + error_min: 3 + gh_pat: secrets.GH_PAT + + url-check: + name: Check URLs + needs: yaml-check + if: ${{needs.yaml-check.outputs.toggle_url_check == 'yes'}} + uses: jhudsl/ottr-reports/.github/workflows/report-maker.yml@main + with: + check_type: urls + error_min: 0 + gh_pat: secrets.GH_PAT + + render-preview: + name: Render preview + needs: yaml-check + runs-on: ubuntu-latest + container: + image: ${{needs.yaml-check.outputs.rendering_docker_image}} + if: ${{needs.yaml-check.outputs.toggle_render_preview == 'yes'}} + + steps: + - name: Checkout files + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + # Set up git checkout + - name: Set up git checkout + run: | + git config --global --add safe.directory $GITHUB_WORKSPACE + git config --global user.name 'github-actions[bot]' + git config --global user.email 'github-actions[bot]@users.noreply.github.com' + + branch_name='preview-${{ github.event.pull_request.number }}' + git fetch --all + git checkout $branch_name + git merge -s recursive --strategy-option=theirs origin/${{ github.head_ref }} --allow-unrelated-histories + shell: bash + + # Now we want to render all the html files from the qmd files + - name: Run render html + id: site + run: quarto render + + # This checks on the steps before it and makes sure that they completed. + # If the renders didn't complete we don't want to commit the file changes + - name: Check on render steps + if: steps.site.outcome != 'success' + run: | + echo site status ${{steps.site.outcome}} + exit 1 + + - name: Website preview for download + run: zip website-preview.zip docs/* -r + + # Commit the rendered website files + - name: Commit rendered website files to preview branch + id: commit + run: | + branch_name='preview-${{ github.event.pull_request.number }}' + git diff origin/main -- '*.html' >/dev/null && changes=true || changes=false + echo "changes=$changes" >> $GITHUB_OUTPUT + git add . --force + git commit -m 'Render preview' || echo "No changes to commit" + git pull --set-upstream origin $branch_name --allow-unrelated-histories --strategy-option=ours + git push --force || echo "No changes to commit" + shell: bash + + - name: Find Comment + uses: peter-evans/find-comment@v1 + id: fc + with: + issue-number: ${{ github.event.pull_request.number }} + comment-author: 'github-actions[bot]' + body-includes: latest commit + + - name: Build components of the comment + id: build-components + run: | + course_name=$(head -n 1 _website.yml | cut -d'"' -f 2| tr " " "-") + website_link=$(echo "https://htmlpreview.github.io/?https://raw.githubusercontent.com/$GITHUB_REPOSITORY/preview-${{ github.event.pull_request.number }}/docs/index.html") + docs_link=$(echo "https://github.com/$GITHUB_REPOSITORY/raw/preview-${{ github.event.pull_request.number }}/website-preview.zip") + echo "docs_link=$docs_link" >> $GITHUB_OUTPUT + echo "website_link=$website_link" >> $GITHUB_OUTPUT + echo "time=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT + echo "commit_id=$GITHUB_SHA" >> $GITHUB_OUTPUT + echo ${{steps.commit.outputs.changes}} + + - name: Create or update comment + if: steps.commit.outputs.changes == 'true' + uses: peter-evans/create-or-update-comment@v1 + with: + comment-id: ${{ steps.fc.outputs.comment-id }} + issue-number: ${{ github.event.pull_request.number }} + body: | + :eyes: [Quick Preview of Website](${{ steps.build-components.outputs.website_link }}) - Click for a preview of recent changes. + :file_folder: [Download Full Website](${{ steps.build-components.outputs.docs_link }}) - Download complete Zip file of the website. + + The Quick Preview may not display all HTML features accurately, but it provides a basic overview. + + _Updated at ${{ steps.build-components.outputs.time }} with changes from the latest commit ${{ steps.build-components.outputs.commit_id }}_ + edit-mode: replace + + - name: No comment if no changes + if: steps.commit.outputs.changes == 'false' + uses: peter-evans/create-or-update-comment@v1 + with: + comment-id: ${{ steps.fc.outputs.comment-id }} + issue-number: ${{ github.event.pull_request.number }} + body: | + The latest commit did not produce rendering changes. + + _Updated at ${{ steps.build-components.outputs.time }} with changes from ${{ steps.build-components.outputs.commit_id }}_ + edit-mode: replace diff --git a/inst/style-sets/gdscn/.github/workflows/render-all.yml b/inst/style-sets/gdscn/.github/workflows/render-all.yml new file mode 100644 index 0000000..775e2db --- /dev/null +++ b/inst/style-sets/gdscn/.github/workflows/render-all.yml @@ -0,0 +1,133 @@ +name: Render All Output + +on: + workflow_dispatch: + push: + branches: [ main ] + paths: + - '**/*.qmd' + +jobs: + yaml-check: + name: Load User Automation Choices + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + # Use the yaml-env-action action. + - name: Load environment from YAML + uses: doughepi/yaml-env-action@v1.0.0 + with: + files: config_automation.yml # Pass a space-separated list of configuration files. Rightmost files take precedence. + outputs: + toggle_coursera: "${{ env.RENDER_COURSERA }}" + toggle_leanpub: "${{ env.RENDER_LEANPUB }}" + rendering_docker_image: "${{ env.RENDERING_DOCKER_IMAGE }}" + + clean-docs: + name: Clean docs folder + needs: yaml-check + runs-on: ubuntu-latest + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + + - name: Delete all files inside docs + run: | + rm -rf docs/* + mkdir -p docs + + - name: Commit changes + run: | + git config --global user.name 'github-actions[bot]' + git config --global user.email 'github-actions[bot]@users.noreply.github.com' + git add docs/ + git commit -m "Clean up docs directory" || echo "No changes to commit" + git push + + render-quarto-book: + name: Render Quarto Book + needs: [yaml-check, clean-docs] + runs-on: ubuntu-latest + container: + image: ${{needs.yaml-check.outputs.rendering_docker_image}} + + steps: + - name: checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + token: ${{ secrets.GH_PAT }} + + - name: Login as github actions bot + run: | + git config --global --add safe.directory $GITHUB_WORKSPACE + git config --global user.name 'github-actions[bot]' + git config --global user.email 'github-actions[bot]@users.noreply.github.com' + echo ${{needs.yaml-check.outputs.rendering_docker_image}} + + # Run quarto::quarto_render() + - name: Run quarto render + id: quarto-render + run: | + Rscript -e "quarto::quarto_render()" + + # This checks on the steps before it and makes sure that they completed. + # If the renders didn't complete we don't want to commit the file changes + - name: Check on render step + if: steps.quarto-render.outcome != 'success' + run: | + echo Quarto Render status ${{steps.quarto-render.outcome}} + exit 1 + + # Commit the rendered files inside docs/ + - name: Commit rendered files + env: + GH_PAT: ${{ secrets.GH_PAT }} + run: | + git remote set-url origin https://${GH_PAT}@github.com/${GITHUB_REPOSITORY} + git fetch origin + git add --force docs/* + git commit -m 'Render Quarto Book' || echo "No changes to commit" + git pull --allow-unrelated-histories --strategy-option=ours + git push -u origin main || echo "No changes to push" + + render-tocless: + name: Render TOC-less Quarto Book + needs: [yaml-check, clean-docs, render-quarto-book] + runs-on: ubuntu-latest + container: + image: ${{needs.yaml-check.outputs.rendering_docker_image}} + if: ${{needs.yaml-check.outputs.toggle_coursera == 'yes' || needs.yaml-check.outputs.toggle_leanpub == 'yes'}} + + steps: + - name: checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + token: ${{ secrets.GH_PAT }} + + - name: Login as github-actions bot + run: | + git config --global --add safe.directory $GITHUB_WORKSPACE + git config --global user.name 'github-actions[bot]' + git config --global user.email 'github-actions[bot]@users.noreply.github.com' + + # Rendered content for Leanpub and Coursera is similar. + # This job creates a shared scaffold for both. + - name: Run TOC-less version of render + id: toc_less_quarto + run: Rscript -e "quarto::quarto_render('.', quarto_args = c('--output-dir', 'docs/no_toc'), metadata = list(sidebar = F, toc = F))" + + # Commit the TOC-less version files + - name: Commit TOC-less Quarto files + env: + GH_PAT: ${{ secrets.GH_PAT }} + run: | + git remote set-url origin https://${GH_PAT}@github.com/${GITHUB_REPOSITORY} + git fetch origin + git add --force docs/no_toc/* + git commit -m 'Render TOC-less Quarto Book' || echo "No changes to commit" + git pull --allow-unrelated-histories --strategy-option=ours + git push -u origin main || echo "No changes to push" diff --git a/inst/style-sets/gdscn/404.qmd b/inst/style-sets/gdscn/404.qmd new file mode 100644 index 0000000..5309332 --- /dev/null +++ b/inst/style-sets/gdscn/404.qmd @@ -0,0 +1,7 @@ +--- +title: "Page Not Found" +--- + +The page you requested cannot be found (perhaps it was moved or renamed). + +Try going back to the previous page or leave a [GitHub issue](https://github.com/fhdsl/ottr/issues/new) for more information. \ No newline at end of file diff --git a/inst/style-sets/gdscn/_quarto.yml b/inst/style-sets/gdscn/_quarto.yml new file mode 100644 index 0000000..4f371ff --- /dev/null +++ b/inst/style-sets/gdscn/_quarto.yml @@ -0,0 +1,65 @@ +project: + type: book + output-dir: docs + +book: + title: "Quarto Based OTTR Course" + author: "Fred Hutch Data Science Lab" + date: "1/1/2025" + favicon: img/favicon.ico + bread-crumbs: false + + page-navigation: true + search: true + repo-url: https://github.com/fhdsl/ottr + repo-actions: [edit, issue] + + chapters: + - index.qmd + - intro.qmd + + sidebar: + logo: "img/logo.png" + logo-href: "https://www.gdscn.org/" + foreground: "#1B365D" + + page-footer: + left: | + This book was built with Quarto using + OTTR. + center: | + All illustrations CC-BY. +
+ All other materials CC-BY unless noted otherwise. + right: + - icon: github + href: https://github.com/jhudsl + - icon: info-circle-fill + href: https://www.gdscn.org/contact-us + + +bibliography: references.bib + +format: + html: + theme: + - theme.scss + grid: + sidebar-width: 260px + css: style.css + linkcolor: "#73b263" + mainfont: "Karla" + + sidebar: true + toc: true + + code-link: true + code-copy: true + + link-external-newwindow: true + + image: img/favicon.ico + license: "CC BY" +knitr: + opts_chunk: + fig.path: "resources/images/figure/" diff --git a/inst/style-sets/gdscn/config_automation.yml b/inst/style-sets/gdscn/config_automation.yml new file mode 100644 index 0000000..a5fb422 --- /dev/null +++ b/inst/style-sets/gdscn/config_automation.yml @@ -0,0 +1,24 @@ + +##### Checks run at pull request ##### +# Check quiz formatting +check-quizzes: no +# Check that urls in the content are not broken +url-checker: yes +# Render preview of content with changes (Rmd's and md's are checked) +render-preview: yes +# Spell check Rmds and quizzes +spell-check: yes +# Style any R code +style-code: yes +# Test build the docker image if any docker-relevant files have been changed +docker-test: no + +##### Renderings run upon merge to main branch ##### +# Rendering each platform's content +render-bookdown: yes +render-leanpub: yes +render-coursera: no + +# What docker image should be used for rendering? +# The default is jhudsl/base_ottr:latest +rendering-docker-image: 'jhudsl/ottr_quarto:latest' diff --git a/inst/style-sets/gdscn/img/box-images/dictionary.png b/inst/style-sets/gdscn/img/box-images/dictionary.png new file mode 100644 index 0000000..75ddac7 Binary files /dev/null and b/inst/style-sets/gdscn/img/box-images/dictionary.png differ diff --git a/inst/style-sets/gdscn/img/box-images/github.png b/inst/style-sets/gdscn/img/box-images/github.png new file mode 100644 index 0000000..a93acd3 Binary files /dev/null and b/inst/style-sets/gdscn/img/box-images/github.png differ diff --git a/inst/style-sets/gdscn/img/box-images/note.png b/inst/style-sets/gdscn/img/box-images/note.png new file mode 100644 index 0000000..72de3ae Binary files /dev/null and b/inst/style-sets/gdscn/img/box-images/note.png differ diff --git a/inst/style-sets/gdscn/img/box-images/thinking_face.png b/inst/style-sets/gdscn/img/box-images/thinking_face.png new file mode 100644 index 0000000..c2c279a Binary files /dev/null and b/inst/style-sets/gdscn/img/box-images/thinking_face.png differ diff --git a/inst/style-sets/gdscn/img/box-images/under_construction.png b/inst/style-sets/gdscn/img/box-images/under_construction.png new file mode 100644 index 0000000..a67bd5c Binary files /dev/null and b/inst/style-sets/gdscn/img/box-images/under_construction.png differ diff --git a/inst/style-sets/gdscn/img/box-images/warning.png b/inst/style-sets/gdscn/img/box-images/warning.png new file mode 100644 index 0000000..405fb61 Binary files /dev/null and b/inst/style-sets/gdscn/img/box-images/warning.png differ diff --git a/inst/style-sets/gdscn/img/favicon.ico b/inst/style-sets/gdscn/img/favicon.ico new file mode 100644 index 0000000..1046ace Binary files /dev/null and b/inst/style-sets/gdscn/img/favicon.ico differ diff --git a/inst/style-sets/gdscn/img/logo.png b/inst/style-sets/gdscn/img/logo.png new file mode 100644 index 0000000..b4c22da Binary files /dev/null and b/inst/style-sets/gdscn/img/logo.png differ diff --git a/inst/style-sets/gdscn/index.qmd b/inst/style-sets/gdscn/index.qmd new file mode 100644 index 0000000..0f24338 --- /dev/null +++ b/inst/style-sets/gdscn/index.qmd @@ -0,0 +1,14 @@ +# Quarto Based OTTR Course {.unnumbered} + +This course is part of a series of courses for the [Informatics Technology for Cancer Research (ITCR)](https://itcr.cancer.gov/) called the Informatics Technology for Cancer Research Education Resource. This material was created by the ITCR Training Network (ITN) which is a collaborative effort of researchers around the United States to support cancer informatics and data science training through resources, technology, and events. This initiative is funded by the following grant: [National Cancer Institute (NCI)](https://www.cancer.gov/) UE5 CA254170. Our courses feature tools developed by ITCR Investigators and make it easier for principal investigators, scientists, and analysts to integrate cancer informatics into their workflows. Please see our website at [www.itcrtraining.org](www.itcrtraining.org) for more information. + + +## Available Course Formats + +This course is available in multiple formats which allows you to take it in the way that best suites your needs. You can take it for certificate which can be for free or fee. + +- The material for this course can be viewed without login requirement on this [website](https://www.ottrproject.org/). This format might be most appropriate for you if you rely on screen-reader technology. +- This course can be taken for [free certification through Leanpub](https://leanpub.com/). +- This course can be taken on [Coursera for certification here](https://www.coursera.org/) (but it is not available for free on Coursera). +- Our courses are open source, you can find the [source material for this course on GitHub](https://github.com/fhdsl/ottr). + diff --git a/inst/style-sets/gdscn/intro.qmd b/inst/style-sets/gdscn/intro.qmd new file mode 100644 index 0000000..873f820 --- /dev/null +++ b/inst/style-sets/gdscn/intro.qmd @@ -0,0 +1,219 @@ +# New Chapter + +## Learning Objectives + +Every chapter also needs Learning objectives. + +## Libraries + +For this chapter, we'll need the following packages attached: + +*Remember to add [any additional packages you need to your course's own docker image](https://github.com/jhudsl/OTTR_Template/wiki/Using-Docker#starting-a-new-docker-image). + +```{r} +library(magrittr) +``` + +## Topic of Section + +You can write all your text in sections like this, using `##` to indicate a new header. you can use additional pound symbols to create lower levels of headers. + +See [here](https://www.rstudio.com/wp-content/uploads/2015/02/rmarkdown-cheatsheet.pdf) for additional general information about how you can format text within R Markdown files. In addition, see [here](https://pandoc.org/MANUAL.html#pandocs-markdown) for more in depth and advanced options. + +### Subtopic + +Here's a subheading (using three pound symbols) and some text in this subsection! + +## Code examples + +You can demonstrate code like this: + +```{r} +output_dir <- file.path("resources", "code_output") +if (!dir.exists(output_dir)) { + dir.create(output_dir) +} +``` + +And make plots too: + +```{r} +hist_plot <- hist(iris$Sepal.Length) +``` + +You can also save these plots to file: + +```{r} +png(file.path(output_dir, "test_plot.png")) +hist_plot +dev.off() +``` + + +## Image example + +How to include a Google slide. It's simplest to use the `ottrpal` package: + +```{r} +#| fig-align: "center" +#| fig-alt: "Major point!! example image" +#| echo: false +#| out-width: "100%" +ottrpal::include_slide("https://docs.google.com/presentation/d/1Dw_rBb1hySN_76xh9-x5J2dWF_das9BAUjQigf2fN-E/edit#slide=id.g252f18e2576_1_0") +``` + +## Video examples + +You may also want to embed videos in your course. If alternatively, you just want to include a link you can do so like this: + +Check out this [link to a video](https://www.youtube.com/embed/VOCYL-FNbr0) using markdown syntax. + +### Using `knitr` + +To embed videos in your course, you can use `knitr::include_url()` like this: +Note that you should use `echo=FALSE` in the code chunk because we don't want the code part of this to show up. If you are unfamiliar with [how R Markdown code chunks work, read this](https://rmarkdown.rstudio.com/lesson-3.html). + + +```{r} +#| echo: false +knitr::include_url("https://www.youtube.com/embed/VOCYL-FNbr0") +``` + +### Using HTML + + + +### Using `knitr` + +```{r, fig.align="center", echo=FALSE, out.width="100%"} +knitr::include_url("https://drive.google.com/file/d/1mm72K4V7fqpgAfWkr6b7HTZrc3f-T6AV/preview") +``` + +### Using HTML + + + +## Website Examples + +Yet again you can use a link to a website like so: + +[A Website](https://yihui.org) + +You might want to have users open a website in a new tab by default, especially if they need to reference both the course and a resource at once. + +[A Website](https://yihui.org){target="_blank"} + +Or, you can embed some websites. + +### Using `knitr` + +This works: + +```{r, fig.align="center", echo=FALSE} +knitr::include_url("https://yihui.org") +``` + + +### Using HTML + + + + +## Stylized boxes + +Occasionally, you might find it useful to emphasize a particular piece of information. To help you do so, we have provided css code and images (no need for you to worry about that!) to create the following stylized boxes. + +You can use these boxes in your course with either of two options: using HTML code or Pandoc syntax. + +### Using `rmarkdown` container syntax + +The `rmarkdown` package allows for a different syntax to be converted to the HTML that you just saw and also allows for conversion to LaTeX. See the [Bookdown](https://bookdown.org/yihui/rmarkdown-cookbook/custom-blocks.html) documentation for more information. Note that Bookdown uses Pandoc. + + +``` +::: {.notice} +Note using rmarkdown syntax. + +::: +``` + +::: {.notice} +Note using rmarkdown syntax. + +::: + +As an example you might do something like this: + +::: {.notice} +Please click on the subsection headers in the left hand +navigation bar (e.g., 2.1, 4.3) a second time to expand the +table of contents and enable the `scroll_highlight` feature +([see more](introduction.html#scroll-highlight)) +::: + + +### Using HTML + +To add a warning box like the following use: + +
+Followed by the text you want inside +
+ +This will create the following: + +
+ +Followed by the text you want inside + +
+ +Here is a `
` box: + +
+ +Note text + +
+ +Here is a `
` box: + +
+ +GitHub text + +
+ + +Here is a `
` box: + +
+ +dictionary text + +
+ + +Here is a `
` box: + +
+ +reflection text + +
+ + +Here is a `
` box: + +
+ +Work in Progress text + +
+ + +## Dropdown summaries + +
You can hide additional information in a dropdown menu +Here's more words that are hidden. +
diff --git a/inst/style-sets/gdscn/references.bib b/inst/style-sets/gdscn/references.bib new file mode 100644 index 0000000..0220dbd --- /dev/null +++ b/inst/style-sets/gdscn/references.bib @@ -0,0 +1,19 @@ +@article{knuth84, + author = {Knuth, Donald E.}, + title = {Literate Programming}, + year = {1984}, + issue_date = {May 1984}, + publisher = {Oxford University Press, Inc.}, + address = {USA}, + volume = {27}, + number = {2}, + issn = {0010-4620}, + url = {https://doi.org/10.1093/comjnl/27.2.97}, + doi = {10.1093/comjnl/27.2.97}, + journal = {Comput. J.}, + month = may, + pages = {97–111}, + numpages = {15} +} + + diff --git a/inst/style-sets/gdscn/style.css b/inst/style-sets/gdscn/style.css new file mode 100755 index 0000000..761a93d --- /dev/null +++ b/inst/style-sets/gdscn/style.css @@ -0,0 +1,175 @@ +/* Imports fonts from Google Fonts (Abril Fatface, Karla, and Lora) with different weights and styles */ +@import url('https://fonts.googleapis.com/css?family=Abril+Fatface|Karla:400,400i,700,700i|Lora:400,400i,700,700i&display=swap'); + +/* Styles for paragraph captions, setting their color and margin */ +p.caption { + color: #777; + margin-top: 10px; +} + +/* Styles for paragraph code, which inherit white-space property */ +p code { + white-space: inherit; +} + +/* Styles for pre elements to prevent words from breaking unnaturally */ +pre { + word-break: normal; + word-wrap: normal; +} + +/* Inherits the white-space property for consistent code formatting */ +pre code { + white-space: inherit; +} + + +/*------------- Header text---------------- */ +h1, h2, h3, h4 { + font-family: 'Lora', arial, sans-serif; +} + +.title { + font-family: 'Lora'; + font-size: 4em !important; + color: #274731; + margin-top: 0.275em !important; + margin-bottom: 0.35em !important; +} + +.subtitle { + font-family: 'Lora'; + color: #0b8d96; +} + +/* Sidebar Logo */ +.sidebar-logo {} + +/* Stylized boxes */ +div.notice, div.warning, div.github, div.dictionary, div.reflection, div.wip { + padding: 1em; + margin: 1em 0; + padding-left: 100px; + min-height: 120px; + background-repeat: no-repeat; +} + +div.notice{ + border: 4px #68ace5; + border-style: solid; + background-size: 70px; + background-position: 15px center; + background-color: #e8ebee; + background-image: url("/img/box-images/note.png"); +} + + +div.warning{ + border: 4px #e0471c; + border-style: solid; + background-size: 70px; + background-position: 15px center; + background-color: #e8ebee; + background-image: url("/img/box-images/warning.png"); +} + +div.github{ + border: 4px #000000; + border-style: solid; + background-size: 70px; + background-position: 15px center; + background-color: #e8ebee; + background-image: url("/img/box-images/github.png"); +} + +div.dictionary{ + border: 4px #68ace5; + border-style: solid; + background-size: 70px; + background-position: 15px center; + background-color: #e8ebee; + background-image: url("/img/box-images/dictionary.png"); +} + +div.reflection{ + border: 4px #68ace5; + border-style: solid; + background-size: 90px; + background-position: 15px center; + background-color: #e8ebee; + background-image: url("/img/box-images/thinking_face.png"); +} + +div.wip{ + border: 4px #000000; + border-style: solid; + background-size: 70px; + background-position: 15px center; + background-color: #f4d03f; + background-image: url("/img/box-images/under_construction.png"); +} + +/* Navbar */ +.chapter-title { + text-transform: none; +} +.menu-text { + text-transform: uppercase; +} + + + +/* iframes */ +iframe { + -moz-transform-origin: top left; + -webkit-transform-origin: top left; + -o-transform-origin: top left; + -ms-transform-origin: top left; + transform-origin: top left; +} + +.iframe-container { + overflow: auto; + -webkit-overflow-scrolling: touch; + border: #ddd 2px solid; + box-shadow: #888 0px 5px 8px; + margin-bottom: 1em; +} + +.iframe-container > iframe { + border: none; +} + + +/* Footer */ +.footer { + font-family: "Lora", serif; + font-size: 1em; + color: #193a5c; +} + + +/* Navbar Header */ +.navbar-logo { + max-height: 33px; +} + + +/* Navbar Footer */ +.nav-footer { + display: flex; + flex-direction: row; + flex-wrap: wrap; + justify-content: space-between; + align-items: baseline; + text-align: center; + padding-top: .5rem; + padding-bottom: .5rem; + background-color: #1B365D; + color: #fff !important; +} + +/* Sidebar Hover Color */ +div.sidebar-item-container .active, div.sidebar-item-container .show>.nav-link, div.sidebar-item-container .sidebar-link>code { + color: #73b263; +} diff --git a/inst/style-sets/gdscn/theme.scss b/inst/style-sets/gdscn/theme.scss new file mode 100644 index 0000000..981b11b --- /dev/null +++ b/inst/style-sets/gdscn/theme.scss @@ -0,0 +1,2 @@ +/*-- scss:defaults --*/ +$toc-color: #73b263; diff --git a/inst/style-sets/itn/.github/workflows/delete-preview.yml b/inst/style-sets/itn/.github/workflows/delete-preview.yml new file mode 100644 index 0000000..7d8cf01 --- /dev/null +++ b/inst/style-sets/itn/.github/workflows/delete-preview.yml @@ -0,0 +1,25 @@ +name: Delete Preview + +on: + pull_request: + types: [closed] + +jobs: + delete-preview: + runs-on: ubuntu-latest + steps: + + # This is because if a PR is closed before a render finishes it won't find it. + - name: Sleep for 5 minutes + run: sleep 300s + shell: bash + + # Check out current repository + - name: checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + # Delete the branch! + - name: Delete branch locally and remotely + run: git push origin --delete preview-${{ github.event.pull_request.number }} || echo "No branch to delete" diff --git a/inst/style-sets/itn/.github/workflows/pull_request.yml b/inst/style-sets/itn/.github/workflows/pull_request.yml new file mode 100644 index 0000000..5b9ee7b --- /dev/null +++ b/inst/style-sets/itn/.github/workflows/pull_request.yml @@ -0,0 +1,169 @@ +name: Pull Request + +on: + pull_request: + branches: [ main, staging ] + +jobs: + yaml-check: + name: Load user automation choices + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + # Use the yaml-env-action action. + - name: Load environment from YAML + uses: doughepi/yaml-env-action@v1.0.0 + with: + files: config_automation.yml # Pass a space-separated list of configuration files. Rightmost files take precedence. + + # Delete the branch if this has been run before + - name: Delete branch locally and remotely + run: git push origin --delete preview-${{ github.event.pull_request.number }} || echo "No branch to delete" + + # Make the branch fresh + - name: Make the branch fresh + run: | + git config --global --add safe.directory $GITHUB_WORKSPACE + git config --global user.name 'github-actions[bot]' + git config --global user.email 'github-actions[bot]@users.noreply.github.com' + + branch_name='preview-${{ github.event.pull_request.number }}' + echo branch doesnt exist + git checkout -b $branch_name || echo branch exists + git push --set-upstream origin $branch_name + shell: bash + + outputs: + public_repository: "${{ steps.public_repository.outputs.public }}" + toggle_spell_check: "${{ env.SPELL_CHECK }}" + toggle_url_check: "${{ env.URL_CHECKER }}" + toggle_render_preview: "${{ env.RENDER_PREVIEW }}" + rendering_docker_image: "${{ env.RENDERING_DOCKER_IMAGE }}" + +########################## Make the error reports ############################## + spell-check: + name: Check spelling + needs: yaml-check + if: ${{needs.yaml-check.outputs.toggle_spell_check == 'yes'}} + uses: jhudsl/ottr-reports/.github/workflows/report-maker.yml@main + with: + check_type: spelling + error_min: 3 + gh_pat: secrets.GH_PAT + + url-check: + name: Check URLs + needs: yaml-check + if: ${{needs.yaml-check.outputs.toggle_url_check == 'yes'}} + uses: jhudsl/ottr-reports/.github/workflows/report-maker.yml@main + with: + check_type: urls + error_min: 0 + gh_pat: secrets.GH_PAT + + render-preview: + name: Render preview + needs: yaml-check + runs-on: ubuntu-latest + container: + image: ${{needs.yaml-check.outputs.rendering_docker_image}} + if: ${{needs.yaml-check.outputs.toggle_render_preview == 'yes'}} + + steps: + - name: Checkout files + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + # Set up git checkout + - name: Set up git checkout + run: | + git config --global --add safe.directory $GITHUB_WORKSPACE + git config --global user.name 'github-actions[bot]' + git config --global user.email 'github-actions[bot]@users.noreply.github.com' + + branch_name='preview-${{ github.event.pull_request.number }}' + git fetch --all + git checkout $branch_name + git merge -s recursive --strategy-option=theirs origin/${{ github.head_ref }} --allow-unrelated-histories + shell: bash + + # Now we want to render all the html files from the qmd files + - name: Run render html + id: site + run: quarto render + + # This checks on the steps before it and makes sure that they completed. + # If the renders didn't complete we don't want to commit the file changes + - name: Check on render steps + if: steps.site.outcome != 'success' + run: | + echo site status ${{steps.site.outcome}} + exit 1 + + - name: Website preview for download + run: zip website-preview.zip docs/* -r + + # Commit the rendered website files + - name: Commit rendered website files to preview branch + id: commit + run: | + branch_name='preview-${{ github.event.pull_request.number }}' + git diff origin/main -- '*.html' >/dev/null && changes=true || changes=false + echo "changes=$changes" >> $GITHUB_OUTPUT + git add . --force + git commit -m 'Render preview' || echo "No changes to commit" + git pull --set-upstream origin $branch_name --allow-unrelated-histories --strategy-option=ours + git push --force || echo "No changes to commit" + shell: bash + + - name: Find Comment + uses: peter-evans/find-comment@v1 + id: fc + with: + issue-number: ${{ github.event.pull_request.number }} + comment-author: 'github-actions[bot]' + body-includes: latest commit + + - name: Build components of the comment + id: build-components + run: | + course_name=$(head -n 1 _website.yml | cut -d'"' -f 2| tr " " "-") + website_link=$(echo "https://htmlpreview.github.io/?https://raw.githubusercontent.com/$GITHUB_REPOSITORY/preview-${{ github.event.pull_request.number }}/docs/index.html") + docs_link=$(echo "https://github.com/$GITHUB_REPOSITORY/raw/preview-${{ github.event.pull_request.number }}/website-preview.zip") + echo "docs_link=$docs_link" >> $GITHUB_OUTPUT + echo "website_link=$website_link" >> $GITHUB_OUTPUT + echo "time=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT + echo "commit_id=$GITHUB_SHA" >> $GITHUB_OUTPUT + echo ${{steps.commit.outputs.changes}} + + - name: Create or update comment + if: steps.commit.outputs.changes == 'true' + uses: peter-evans/create-or-update-comment@v1 + with: + comment-id: ${{ steps.fc.outputs.comment-id }} + issue-number: ${{ github.event.pull_request.number }} + body: | + :eyes: [Quick Preview of Website](${{ steps.build-components.outputs.website_link }}) - Click for a preview of recent changes. + :file_folder: [Download Full Website](${{ steps.build-components.outputs.docs_link }}) - Download complete Zip file of the website. + + The Quick Preview may not display all HTML features accurately, but it provides a basic overview. + + _Updated at ${{ steps.build-components.outputs.time }} with changes from the latest commit ${{ steps.build-components.outputs.commit_id }}_ + edit-mode: replace + + - name: No comment if no changes + if: steps.commit.outputs.changes == 'false' + uses: peter-evans/create-or-update-comment@v1 + with: + comment-id: ${{ steps.fc.outputs.comment-id }} + issue-number: ${{ github.event.pull_request.number }} + body: | + The latest commit did not produce rendering changes. + + _Updated at ${{ steps.build-components.outputs.time }} with changes from ${{ steps.build-components.outputs.commit_id }}_ + edit-mode: replace diff --git a/inst/style-sets/itn/.github/workflows/render-all.yml b/inst/style-sets/itn/.github/workflows/render-all.yml new file mode 100644 index 0000000..775e2db --- /dev/null +++ b/inst/style-sets/itn/.github/workflows/render-all.yml @@ -0,0 +1,133 @@ +name: Render All Output + +on: + workflow_dispatch: + push: + branches: [ main ] + paths: + - '**/*.qmd' + +jobs: + yaml-check: + name: Load User Automation Choices + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + # Use the yaml-env-action action. + - name: Load environment from YAML + uses: doughepi/yaml-env-action@v1.0.0 + with: + files: config_automation.yml # Pass a space-separated list of configuration files. Rightmost files take precedence. + outputs: + toggle_coursera: "${{ env.RENDER_COURSERA }}" + toggle_leanpub: "${{ env.RENDER_LEANPUB }}" + rendering_docker_image: "${{ env.RENDERING_DOCKER_IMAGE }}" + + clean-docs: + name: Clean docs folder + needs: yaml-check + runs-on: ubuntu-latest + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + + - name: Delete all files inside docs + run: | + rm -rf docs/* + mkdir -p docs + + - name: Commit changes + run: | + git config --global user.name 'github-actions[bot]' + git config --global user.email 'github-actions[bot]@users.noreply.github.com' + git add docs/ + git commit -m "Clean up docs directory" || echo "No changes to commit" + git push + + render-quarto-book: + name: Render Quarto Book + needs: [yaml-check, clean-docs] + runs-on: ubuntu-latest + container: + image: ${{needs.yaml-check.outputs.rendering_docker_image}} + + steps: + - name: checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + token: ${{ secrets.GH_PAT }} + + - name: Login as github actions bot + run: | + git config --global --add safe.directory $GITHUB_WORKSPACE + git config --global user.name 'github-actions[bot]' + git config --global user.email 'github-actions[bot]@users.noreply.github.com' + echo ${{needs.yaml-check.outputs.rendering_docker_image}} + + # Run quarto::quarto_render() + - name: Run quarto render + id: quarto-render + run: | + Rscript -e "quarto::quarto_render()" + + # This checks on the steps before it and makes sure that they completed. + # If the renders didn't complete we don't want to commit the file changes + - name: Check on render step + if: steps.quarto-render.outcome != 'success' + run: | + echo Quarto Render status ${{steps.quarto-render.outcome}} + exit 1 + + # Commit the rendered files inside docs/ + - name: Commit rendered files + env: + GH_PAT: ${{ secrets.GH_PAT }} + run: | + git remote set-url origin https://${GH_PAT}@github.com/${GITHUB_REPOSITORY} + git fetch origin + git add --force docs/* + git commit -m 'Render Quarto Book' || echo "No changes to commit" + git pull --allow-unrelated-histories --strategy-option=ours + git push -u origin main || echo "No changes to push" + + render-tocless: + name: Render TOC-less Quarto Book + needs: [yaml-check, clean-docs, render-quarto-book] + runs-on: ubuntu-latest + container: + image: ${{needs.yaml-check.outputs.rendering_docker_image}} + if: ${{needs.yaml-check.outputs.toggle_coursera == 'yes' || needs.yaml-check.outputs.toggle_leanpub == 'yes'}} + + steps: + - name: checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + token: ${{ secrets.GH_PAT }} + + - name: Login as github-actions bot + run: | + git config --global --add safe.directory $GITHUB_WORKSPACE + git config --global user.name 'github-actions[bot]' + git config --global user.email 'github-actions[bot]@users.noreply.github.com' + + # Rendered content for Leanpub and Coursera is similar. + # This job creates a shared scaffold for both. + - name: Run TOC-less version of render + id: toc_less_quarto + run: Rscript -e "quarto::quarto_render('.', quarto_args = c('--output-dir', 'docs/no_toc'), metadata = list(sidebar = F, toc = F))" + + # Commit the TOC-less version files + - name: Commit TOC-less Quarto files + env: + GH_PAT: ${{ secrets.GH_PAT }} + run: | + git remote set-url origin https://${GH_PAT}@github.com/${GITHUB_REPOSITORY} + git fetch origin + git add --force docs/no_toc/* + git commit -m 'Render TOC-less Quarto Book' || echo "No changes to commit" + git pull --allow-unrelated-histories --strategy-option=ours + git push -u origin main || echo "No changes to push" diff --git a/inst/style-sets/itn/404.qmd b/inst/style-sets/itn/404.qmd new file mode 100644 index 0000000..5309332 --- /dev/null +++ b/inst/style-sets/itn/404.qmd @@ -0,0 +1,7 @@ +--- +title: "Page Not Found" +--- + +The page you requested cannot be found (perhaps it was moved or renamed). + +Try going back to the previous page or leave a [GitHub issue](https://github.com/fhdsl/ottr/issues/new) for more information. \ No newline at end of file diff --git a/inst/style-sets/itn/_quarto.yml b/inst/style-sets/itn/_quarto.yml new file mode 100644 index 0000000..80e11af --- /dev/null +++ b/inst/style-sets/itn/_quarto.yml @@ -0,0 +1,65 @@ +project: + type: book + output-dir: docs + +book: + title: "Quarto Based OTTR Course" + author: "Fred Hutch Data Science Lab" + date: "1/1/2025" + favicon: img/favicon.ico + bread-crumbs: false + + page-navigation: true + search: true + repo-url: https://github.com/fhdsl/ottr + repo-actions: [edit, issue] + + chapters: + - index.qmd + - intro.qmd + + sidebar: + logo: "img/logo.png" + logo-href: "https://hutchdatascience.org/" + foreground: "#1B365D" + + page-footer: + left: | + This book was built with Quarto using + OTTR. + center: | + All illustrations CC-BY. +
+ All other materials CC-BY unless noted otherwise. + right: + - icon: github + href: https://github.com/fhdsl + - icon: slack + href: https://fhdata.slack.com/join/signup#/domain-signup + + +bibliography: references.bib + +format: + html: + theme: + - theme.scss + grid: + sidebar-width: 260px + css: style.css + linkcolor: '#e0471c' + mainfont: "Karla" + + sidebar: true + toc: true + + code-link: true + code-copy: true + + link-external-newwindow: true + + image: img/favicon.ico + license: "CC BY" +knitr: + opts_chunk: + fig.path: "resources/images/figure/" diff --git a/inst/style-sets/itn/config_automation.yml b/inst/style-sets/itn/config_automation.yml new file mode 100644 index 0000000..a5fb422 --- /dev/null +++ b/inst/style-sets/itn/config_automation.yml @@ -0,0 +1,24 @@ + +##### Checks run at pull request ##### +# Check quiz formatting +check-quizzes: no +# Check that urls in the content are not broken +url-checker: yes +# Render preview of content with changes (Rmd's and md's are checked) +render-preview: yes +# Spell check Rmds and quizzes +spell-check: yes +# Style any R code +style-code: yes +# Test build the docker image if any docker-relevant files have been changed +docker-test: no + +##### Renderings run upon merge to main branch ##### +# Rendering each platform's content +render-bookdown: yes +render-leanpub: yes +render-coursera: no + +# What docker image should be used for rendering? +# The default is jhudsl/base_ottr:latest +rendering-docker-image: 'jhudsl/ottr_quarto:latest' diff --git a/inst/style-sets/itn/img/box-images/dictionary.png b/inst/style-sets/itn/img/box-images/dictionary.png new file mode 100644 index 0000000..75ddac7 Binary files /dev/null and b/inst/style-sets/itn/img/box-images/dictionary.png differ diff --git a/inst/style-sets/itn/img/box-images/github.png b/inst/style-sets/itn/img/box-images/github.png new file mode 100644 index 0000000..a93acd3 Binary files /dev/null and b/inst/style-sets/itn/img/box-images/github.png differ diff --git a/inst/style-sets/itn/img/box-images/note.png b/inst/style-sets/itn/img/box-images/note.png new file mode 100644 index 0000000..72de3ae Binary files /dev/null and b/inst/style-sets/itn/img/box-images/note.png differ diff --git a/inst/style-sets/itn/img/box-images/thinking_face.png b/inst/style-sets/itn/img/box-images/thinking_face.png new file mode 100644 index 0000000..c2c279a Binary files /dev/null and b/inst/style-sets/itn/img/box-images/thinking_face.png differ diff --git a/inst/style-sets/itn/img/box-images/under_construction.png b/inst/style-sets/itn/img/box-images/under_construction.png new file mode 100644 index 0000000..a67bd5c Binary files /dev/null and b/inst/style-sets/itn/img/box-images/under_construction.png differ diff --git a/inst/style-sets/itn/img/box-images/warning.png b/inst/style-sets/itn/img/box-images/warning.png new file mode 100644 index 0000000..405fb61 Binary files /dev/null and b/inst/style-sets/itn/img/box-images/warning.png differ diff --git a/inst/style-sets/itn/img/favicon.ico b/inst/style-sets/itn/img/favicon.ico new file mode 100644 index 0000000..726a500 Binary files /dev/null and b/inst/style-sets/itn/img/favicon.ico differ diff --git a/inst/style-sets/itn/img/logo.png b/inst/style-sets/itn/img/logo.png new file mode 100644 index 0000000..0ade934 Binary files /dev/null and b/inst/style-sets/itn/img/logo.png differ diff --git a/inst/style-sets/itn/index.qmd b/inst/style-sets/itn/index.qmd new file mode 100644 index 0000000..0f24338 --- /dev/null +++ b/inst/style-sets/itn/index.qmd @@ -0,0 +1,14 @@ +# Quarto Based OTTR Course {.unnumbered} + +This course is part of a series of courses for the [Informatics Technology for Cancer Research (ITCR)](https://itcr.cancer.gov/) called the Informatics Technology for Cancer Research Education Resource. This material was created by the ITCR Training Network (ITN) which is a collaborative effort of researchers around the United States to support cancer informatics and data science training through resources, technology, and events. This initiative is funded by the following grant: [National Cancer Institute (NCI)](https://www.cancer.gov/) UE5 CA254170. Our courses feature tools developed by ITCR Investigators and make it easier for principal investigators, scientists, and analysts to integrate cancer informatics into their workflows. Please see our website at [www.itcrtraining.org](www.itcrtraining.org) for more information. + + +## Available Course Formats + +This course is available in multiple formats which allows you to take it in the way that best suites your needs. You can take it for certificate which can be for free or fee. + +- The material for this course can be viewed without login requirement on this [website](https://www.ottrproject.org/). This format might be most appropriate for you if you rely on screen-reader technology. +- This course can be taken for [free certification through Leanpub](https://leanpub.com/). +- This course can be taken on [Coursera for certification here](https://www.coursera.org/) (but it is not available for free on Coursera). +- Our courses are open source, you can find the [source material for this course on GitHub](https://github.com/fhdsl/ottr). + diff --git a/inst/style-sets/itn/intro.qmd b/inst/style-sets/itn/intro.qmd new file mode 100644 index 0000000..efaf241 --- /dev/null +++ b/inst/style-sets/itn/intro.qmd @@ -0,0 +1,220 @@ +# New Chapter + +## Learning Objectives + +Every chapter also needs Learning objectives. + +## Libraries + +For this chapter, we'll need the following packages attached: + +*Remember to add [any additional packages you need to your course's own docker image](https://github.com/jhudsl/OTTR_Template/wiki/Using-Docker#starting-a-new-docker-image). + +```{r} +library(magrittr) +``` + +## Topic of Section + +You can write all your text in sections like this, using `##` to indicate a new header. you can use additional pound symbols to create lower levels of headers. + +See [here](https://www.rstudio.com/wp-content/uploads/2015/02/rmarkdown-cheatsheet.pdf) for additional general information about how you can format text within R Markdown files. In addition, see [here](https://pandoc.org/MANUAL.html#pandocs-markdown) for more in depth and advanced options. + +### Subtopic + +Here's a subheading (using three pound symbols) and some text in this subsection! + +## Code examples + +You can demonstrate code like this: + +```{r} +output_dir <- file.path("resources", "code_output") +if (!dir.exists(output_dir)) { + dir.create(output_dir) +} +``` + +And make plots too: + +```{r} +hist_plot <- hist(iris$Sepal.Length) +``` + +You can also save these plots to file: + +```{r} +png(file.path(output_dir, "test_plot.png")) +hist_plot +dev.off() +``` + + +## Image example + +How to include a Google slide. It's simplest to use the `ottrpal` package: + +```{r} +#| fig-align: "center" +#| fig-alt: "Major point!! example image" +#| echo: false +#| out-width: "100%" +ottrpal::include_slide("https://docs.google.com/presentation/d/1Dw_rBb1hySN_76xh9-x5J2dWF_das9BAUjQigf2fN-E/edit#slide=id.g252f18e2576_1_0") +``` + + +## Video examples + +You may also want to embed videos in your course. If alternatively, you just want to include a link you can do so like this: + +Check out this [link to a video](https://www.youtube.com/embed/VOCYL-FNbr0) using markdown syntax. + +### Using `knitr` + +To embed videos in your course, you can use `knitr::include_url()` like this: +Note that you should use `echo=FALSE` in the code chunk because we don't want the code part of this to show up. If you are unfamiliar with [how R Markdown code chunks work, read this](https://rmarkdown.rstudio.com/lesson-3.html). + + +```{r} +#| echo: false +knitr::include_url("https://www.youtube.com/embed/VOCYL-FNbr0") +``` + +### Using HTML + + + +### Using `knitr` + +```{r, fig.align="center", echo=FALSE, out.width="100%"} +knitr::include_url("https://drive.google.com/file/d/1mm72K4V7fqpgAfWkr6b7HTZrc3f-T6AV/preview") +``` + +### Using HTML + + + +## Website Examples + +Yet again you can use a link to a website like so: + +[A Website](https://yihui.org) + +You might want to have users open a website in a new tab by default, especially if they need to reference both the course and a resource at once. + +[A Website](https://yihui.org){target="_blank"} + +Or, you can embed some websites. + +### Using `knitr` + +This works: + +```{r, fig.align="center", echo=FALSE} +knitr::include_url("https://yihui.org") +``` + + +### Using HTML + + + + +## Stylized boxes + +Occasionally, you might find it useful to emphasize a particular piece of information. To help you do so, we have provided css code and images (no need for you to worry about that!) to create the following stylized boxes. + +You can use these boxes in your course with either of two options: using HTML code or Pandoc syntax. + +### Using `rmarkdown` container syntax + +The `rmarkdown` package allows for a different syntax to be converted to the HTML that you just saw and also allows for conversion to LaTeX. See the [Bookdown](https://bookdown.org/yihui/rmarkdown-cookbook/custom-blocks.html) documentation for more information. Note that Bookdown uses Pandoc. + + +``` +::: {.notice} +Note using rmarkdown syntax. + +::: +``` + +::: {.notice} +Note using rmarkdown syntax. + +::: + +As an example you might do something like this: + +::: {.notice} +Please click on the subsection headers in the left hand +navigation bar (e.g., 2.1, 4.3) a second time to expand the +table of contents and enable the `scroll_highlight` feature +([see more](introduction.html#scroll-highlight)) +::: + + +### Using HTML + +To add a warning box like the following use: + +
+Followed by the text you want inside +
+ +This will create the following: + +
+ +Followed by the text you want inside + +
+ +Here is a `
` box: + +
+ +Note text + +
+ +Here is a `
` box: + +
+ +GitHub text + +
+ + +Here is a `
` box: + +
+ +dictionary text + +
+ + +Here is a `
` box: + +
+ +reflection text + +
+ + +Here is a `
` box: + +
+ +Work in Progress text + +
+ + +## Dropdown summaries + +
You can hide additional information in a dropdown menu +Here's more words that are hidden. +
diff --git a/inst/style-sets/itn/references.bib b/inst/style-sets/itn/references.bib new file mode 100644 index 0000000..0220dbd --- /dev/null +++ b/inst/style-sets/itn/references.bib @@ -0,0 +1,19 @@ +@article{knuth84, + author = {Knuth, Donald E.}, + title = {Literate Programming}, + year = {1984}, + issue_date = {May 1984}, + publisher = {Oxford University Press, Inc.}, + address = {USA}, + volume = {27}, + number = {2}, + issn = {0010-4620}, + url = {https://doi.org/10.1093/comjnl/27.2.97}, + doi = {10.1093/comjnl/27.2.97}, + journal = {Comput. J.}, + month = may, + pages = {97–111}, + numpages = {15} +} + + diff --git a/inst/style-sets/itn/style.css b/inst/style-sets/itn/style.css new file mode 100755 index 0000000..cd073e2 --- /dev/null +++ b/inst/style-sets/itn/style.css @@ -0,0 +1,176 @@ +/* Imports fonts from Google Fonts (Abril Fatface, Karla, and Lora) with different weights and styles */ +@import url('https://fonts.googleapis.com/css?family=Abril+Fatface|Karla:400,400i,700,700i|Lora:400,400i,700,700i&display=swap'); + +/* Styles for paragraph captions, setting their color and margin */ +p.caption { + color: #777; + margin-top: 10px; +} + +/* Styles for paragraph code, which inherit white-space property */ +p code { + white-space: inherit; +} + +/* Styles for pre elements to prevent words from breaking unnaturally */ +pre { + word-break: normal; + word-wrap: normal; +} + +/* Inherits the white-space property for consistent code formatting */ +pre code { + white-space: inherit; +} + + +/*------------- Header text---------------- */ +h1, h2, h3, h4 { + font-family: 'Lora', arial, sans-serif; +} + +.title { + font-family: 'Lora'; + font-size: 4em !important; + color: #193a5c; + margin-top: 0.275em !important; + margin-bottom: 0.35em !important; +} + +.subtitle { + font-family: 'Lora'; + color: #0b8d96; +} + +/* Sidebar Logo */ +.sidebar-logo {} + +/* Stylized boxes */ +div.notice, div.warning, div.github, div.dictionary, div.reflection, div.wip { + padding: 1em; + margin: 1em 0; + padding-left: 100px; + min-height: 120px; + background-repeat: no-repeat; +} + +div.notice{ + border: 4px #68ace5; + border-style: solid; + background-size: 70px; + background-position: 15px center; + background-color: #e8ebee; + background-image: url("/img/box-images/note.png"); +} + + +div.warning{ + border: 4px #e0471c; + border-style: solid; + background-size: 70px; + background-position: 15px center; + background-color: #e8ebee; + background-image: url("/img/box-images/warning.png"); +} + +div.github{ + border: 4px #000000; + border-style: solid; + background-size: 70px; + background-position: 15px center; + background-color: #e8ebee; + background-image: url("/img/box-images/github.png"); +} + +div.dictionary{ + border: 4px #68ace5; + border-style: solid; + background-size: 70px; + background-position: 15px center; + background-color: #e8ebee; + background-image: url("/img/box-images/dictionary.png"); +} + +div.reflection{ + border: 4px #68ace5; + border-style: solid; + background-size: 90px; + background-position: 15px center; + background-color: #e8ebee; + background-image: url("/img/box-images/thinking_face.png"); +} + +div.wip{ + border: 4px #000000; + border-style: solid; + background-size: 70px; + background-position: 15px center; + background-color: #f4d03f; + background-image: url("/img/box-images/under_construction.png"); +} + +/* Navbar */ +.chapter-title { + text-transform: none; +} +.menu-text { + text-transform: uppercase; +} + + + +/* iframes */ +iframe { + -moz-transform-origin: top left; + -webkit-transform-origin: top left; + -o-transform-origin: top left; + -ms-transform-origin: top left; + transform-origin: top left; +} + +.iframe-container { + overflow: auto; + -webkit-overflow-scrolling: touch; + border: #ddd 2px solid; + box-shadow: #888 0px 5px 8px; + margin-bottom: 1em; +} + +.iframe-container > iframe { + border: none; +} + + +/* Footer */ +.footer { + font-family: "Lora", serif; + font-size: 1em; + color: #193a5c; +} + + +/* Navbar Header */ +.navbar-logo { + max-height: 33px; +} + + +/* Navbar Footer */ +.nav-footer { + display: flex; + flex-direction: row; + flex-wrap: wrap; + justify-content: space-between; + align-items: baseline; + text-align: center; + padding-top: .5rem; + padding-bottom: .5rem; + background-color: #1B365D; + color: #fff !important; +} + + +/* Sidebar Hover Color */ +div.sidebar-item-container .active, div.sidebar-item-container .show>.nav-link, div.sidebar-item-container .sidebar-link>code { + color: #e0471c; +} diff --git a/inst/style-sets/itn/theme.scss b/inst/style-sets/itn/theme.scss new file mode 100644 index 0000000..b46e955 --- /dev/null +++ b/inst/style-sets/itn/theme.scss @@ -0,0 +1,2 @@ +/*-- scss:defaults --*/ +$toc-color: #e0471c; \ No newline at end of file