├── .Rbuildignore
├── .github
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── ISSUE_TEMPLATE
│ ├── bug.yml
│ ├── config.yml
│ ├── cran-release.yml
│ ├── feature.yml
│ ├── question.yml
│ └── release.yml
├── pull_request_template.md
└── workflows
│ ├── check.yaml
│ ├── cla.yaml
│ ├── docs.yaml
│ ├── post-release.yaml
│ ├── release.yaml
│ └── scheduled.yaml
├── .gitignore
├── .gitlab-ci.yml
├── .lintr
├── .pre-commit-config.yaml
├── DESCRIPTION
├── LICENSE
├── NAMESPACE
├── NEWS.md
├── R
├── TealAppDriver.R
├── checkmate.R
├── dummy_functions.R
├── include_css_js.R
├── init.R
├── landing_popup_module.R
├── module_bookmark_manager.R
├── module_data_summary.R
├── module_filter_data.R
├── module_filter_manager.R
├── module_init_data.R
├── module_nested_tabs.R
├── module_session_info.R
├── module_snapshot_manager.R
├── module_teal.R
├── module_teal_data.R
├── module_teal_lockfile.R
├── module_teal_with_splash.R
├── module_transform_data.R
├── modules.R
├── reporter_previewer_module.R
├── show_rcode_modal.R
├── tdata.R
├── teal.R
├── teal_data_module-eval_code.R
├── teal_data_module-within.R
├── teal_data_module.R
├── teal_data_utils.R
├── teal_modifiers.R
├── teal_reporter.R
├── teal_slices-store.R
├── teal_slices.R
├── teal_transform_module.R
├── utils.R
├── validate_inputs.R
├── validations.R
└── zzz.R
├── README.md
├── SECURITY.md
├── _pkgdown.yml
├── inst
├── WORDLIST
├── css
│ ├── custom.css
│ ├── sidebar.css
│ └── validation.css
├── design
│ ├── filters-mapping.drawio
│ ├── teal-app-components-hover.drawio
│ ├── teal-app-components.drawio
│ ├── teal-transform-module-decorators.drawio
│ └── teal-transform-module-transformators.drawio
└── js
│ ├── clipboard.js
│ ├── init.js
│ └── togglePanelItems.js
├── man
├── TealAppDriver.Rd
├── TealReportCard.Rd
├── TealSlicesBlock.Rd
├── add_landing_modal.Rd
├── append_module.Rd
├── bookmarks_identical.Rd
├── build_app_title.Rd
├── check_filter_datanames.Rd
├── check_modules_datanames.Rd
├── check_reactive.Rd
├── create_app_id.Rd
├── decorate_err_msg.Rd
├── deep_copy_filter.Rd
├── dot-add_signature_to_data.Rd
├── dot-call_once_when.Rd
├── dot-get_hashes_code.Rd
├── dot-smart_rbind.Rd
├── dot-teal_favicon.Rd
├── example_module.Rd
├── extract_transformators.Rd
├── figures
│ ├── filterpanel.png
│ ├── lifecycle-archived.svg
│ ├── lifecycle-defunct.svg
│ ├── lifecycle-deprecated.svg
│ ├── lifecycle-experimental.svg
│ ├── lifecycle-maturing.svg
│ ├── lifecycle-questioning.svg
│ ├── lifecycle-soft-deprecated.svg
│ ├── lifecycle-stable.svg
│ ├── lifecycle-superseded.svg
│ ├── logo.svg
│ ├── readme_app.webp
│ ├── reporter.jpg
│ └── showrcode.jpg
├── get_client_timezone.Rd
├── get_unique_labels.Rd
├── include_css_files.Rd
├── include_js_files.Rd
├── include_teal_css_js.Rd
├── init.Rd
├── is_arg_used.Rd
├── landing_popup_module.Rd
├── make_teal_transform_server.Rd
├── module_bookmark_manager.Rd
├── module_data_summary.Rd
├── module_filter_data.Rd
├── module_filter_manager.Rd
├── module_init_data.Rd
├── module_labels.Rd
├── module_management.Rd
├── module_session_info.Rd
├── module_snapshot_manager.Rd
├── module_teal.Rd
├── module_teal_data.Rd
├── module_teal_lockfile.Rd
├── module_teal_module.Rd
├── module_teal_with_splash.Rd
├── module_transform_data.Rd
├── modules_bookmarkable.Rd
├── modules_depth.Rd
├── pluralize.Rd
├── report_card_template.Rd
├── reporter_previewer_module.Rd
├── restoreValue.Rd
├── run_js_files.Rd
├── show_rcode_modal.Rd
├── slices_store.Rd
├── tdata.Rd
├── teal-package.Rd
├── teal_data_module.Rd
├── teal_data_to_filtered_data.Rd
├── teal_data_utilities.Rd
├── teal_extend_server.Rd
├── teal_modifiers.Rd
├── teal_modules.Rd
├── teal_slices.Rd
├── teal_transform_module.Rd
├── validate_app_title_tag.Rd
├── validate_has_data.Rd
├── validate_has_elements.Rd
├── validate_has_variable.Rd
├── validate_in.Rd
├── validate_inputs.Rd
├── validate_n_levels.Rd
├── validate_no_intersection.Rd
└── validate_one_row_per_id.Rd
├── revdep
└── .gitignore
├── staged_dependencies.yaml
├── teal.Rproj
├── tests
├── testthat.R
└── testthat
│ ├── helper-shinytest2.R
│ ├── setup-logger.R
│ ├── setup-options.R
│ ├── setup-testing_depth.R
│ ├── test-init.R
│ ├── test-module_session_info.R
│ ├── test-module_teal.R
│ ├── test-modules.R
│ ├── test-report_previewer_module.R
│ ├── test-shinytest2-data_summary.R
│ ├── test-shinytest2-decorators.R
│ ├── test-shinytest2-filter_panel.R
│ ├── test-shinytest2-init.R
│ ├── test-shinytest2-landing_popup.R
│ ├── test-shinytest2-module_bookmark_manager.R
│ ├── test-shinytest2-modules.R
│ ├── test-shinytest2-reporter.R
│ ├── test-shinytest2-show-rcode.R
│ ├── test-shinytest2-teal_data_module.R
│ ├── test-shinytest2-teal_slices.R
│ ├── test-shinytest2-wunder_bar.R
│ ├── test-teal_data_module-eval_code.R
│ ├── test-teal_data_module.R
│ ├── test-teal_reporter.R
│ ├── test-teal_slices-store.R
│ ├── test-teal_slices.R
│ ├── test-teal_transform_module.R
│ ├── test-utils.R
│ ├── test-validate_has_data.R
│ └── test-validate_inputs.R
└── vignettes
├── .gitignore
├── adding-support-for-reporting.Rmd
├── blueprint
├── _setup.Rmd
├── actors.Rmd
├── dataflow.Rmd
├── filter_panel.Rmd
├── in_app_data.Rmd
├── index.Rmd
├── input_data.Rmd
├── intro.Rmd
├── module_encapsulation.Rmd
└── product_map.Rmd
├── bootstrap-themes-in-teal.Rmd
├── creating-custom-modules.Rmd
├── data-as-shiny-module.Rmd
├── filter-panel.Rmd
├── getting-started-with-teal.Rmd
├── images
├── bs-corners.png
├── bs-final.png
├── bs-font-size.png
├── bs-launch.png
├── bs-theme-set.png
├── custom_app.png
├── filters-mapping.svg
├── reporter.jpg
├── show_code_prepro_missing.png
├── show_code_prepro_present.png
├── teal-app-components-hover.svg
├── teal-app-components.svg
├── teal-transform-module-decorators.svg
└── teal-transform-module-transformators.svg
├── including-data-in-teal-applications.Rmd
├── teal-as-a-shiny-module.Rmd
├── teal-options.Rmd
├── transform-input-data.Rmd
└── transform-module-output.Rmd
/.Rbuildignore:
--------------------------------------------------------------------------------
1 | LICENSE
2 | ^renv$
3 | ^renv\.lock$
4 | CODE_OF_CONDUCT.md
5 | SECURITY.md
6 | ^.*\.Rproj$
7 | ^Jenkinsfile$
8 | ^Makefile$
9 | ^Meta$
10 | ^TODO\.md$
11 | ^[^/]+\.R$
12 | ^[^/]+\.Rmd$
13 | ^[^/]+\.html$
14 | ^[^/]+\.png$
15 | ^\.CI-FORCE-RELEASE-VERSION$
16 | ^\.Rprofile$
17 | ^\.Rproj\.user$
18 | ^\.drone\.yml$
19 | ^\.github$
20 | ^\.gitlab-ci\.yml$
21 | ^\.lintr$
22 | ^\.travis\.yml$
23 | ^\_pkgdown\.yaml$
24 | ^\_pkgdown\.yml
25 | ^_dev$
26 | ^build_docker_image$
27 | ^cache$
28 | ^data-raw$
29 | ^data/script\.R$
30 | ^design$
31 | ^dev$
32 | ^doc$
33 | ^docs$
34 | ^logs$
35 | ^man-roxygen$
36 | ^outputdir$
37 | ^\.pre-commit-config\.yaml$
38 | ^scratch$
39 | ^staged_dependencies\.yaml$
40 | ^stubs$
41 | ^temp$
42 | ^templates$
43 | ^test_full_example$
44 | coverage.*
45 | ^pkgdown$
46 | ^.revdeprefs\.yaml$
47 | ^revdep$
48 | ^\.covrignore$
49 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug.yml:
--------------------------------------------------------------------------------
1 | ---
2 | name: 🐞 Bug Report
3 | description: File a bug report
4 | title: "[Bug]:
"
5 | labels: ["bug"]
6 | body:
7 | - type: markdown
8 | attributes:
9 | value: |
10 | Thanks for taking the time to fill out this bug report!
11 | - type: textarea
12 | id: what-happened
13 | attributes:
14 | label: What happened?
15 | description: Also tell us, what did you expect to happen?
16 | placeholder: Tell us what you see!
17 | value: "A bug happened!"
18 | validations:
19 | required: true
20 | - type: textarea
21 | id: session-info
22 | attributes:
23 | label: sessionInfo()
24 | description: Please copy and paste your output from `sessionInfo()`. This will be automatically formatted into code, so no need for backticks.
25 | render: R
26 | - type: textarea
27 | id: logs
28 | attributes:
29 | label: Relevant log output
30 | description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
31 | render: R
32 | - type: checkboxes
33 | id: code-of-conduct
34 | attributes:
35 | label: Code of Conduct
36 | description: By submitting this issue, you agree to follow our [Code of Conduct.](https://insightsengineering.github.io/teal/latest-tag/CODE_OF_CONDUCT.html)
37 | options:
38 | - label: I agree to follow this project's Code of Conduct.
39 | required: true
40 | - type: checkboxes
41 | id: contributor-guidelines
42 | attributes:
43 | label: Contribution Guidelines
44 | description: By submitting this issue, you agree to follow our [Contribution Guidelines.](https://insightsengineering.github.io/teal/latest-tag/CONTRIBUTING.html)
45 | options:
46 | - label: I agree to follow this project's Contribution Guidelines.
47 | required: true
48 | - type: checkboxes
49 | id: security-policy
50 | attributes:
51 | label: Security Policy
52 | description: By submitting this issue, you agree to follow our [Security Policy.](https://github.com/insightsengineering/teal/security/policy)
53 | options:
54 | - label: I agree to follow this project's Security Policy.
55 | required: true
56 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/config.yml:
--------------------------------------------------------------------------------
1 | ---
2 | blank_issues_enabled: false
3 |
4 | contact_links:
5 | - name: We are hiring!
6 | url: https://careers.gene.com/
7 | about: Genentech and Roche are hiring!
8 | - name: Pharmaverse
9 | url: https://pharmaverse.org/
10 | about: Related projects @ Pharmaverse.org
11 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature.yml:
--------------------------------------------------------------------------------
1 | ---
2 | name: ✨ Feature Request
3 | description: Request or propose a new feature
4 | title: "[Feature Request]: "
5 | labels: ["enhancement"]
6 | body:
7 | - type: textarea
8 | attributes:
9 | label: Feature description
10 | validations:
11 | required: true
12 | - type: checkboxes
13 | id: code-of-conduct
14 | attributes:
15 | label: Code of Conduct
16 | description: By submitting this issue, you agree to follow our [Code of Conduct.](https://insightsengineering.github.io/teal/latest-tag/CODE_OF_CONDUCT.html)
17 | options:
18 | - label: I agree to follow this project's Code of Conduct.
19 | required: true
20 | - type: checkboxes
21 | id: contributor-guidelines
22 | attributes:
23 | label: Contribution Guidelines
24 | description: By submitting this issue, you agree to follow our [Contribution Guidelines.](https://insightsengineering.github.io/teal/latest-tag/CONTRIBUTING.html)
25 | options:
26 | - label: I agree to follow this project's Contribution Guidelines.
27 | required: true
28 | - type: checkboxes
29 | id: security-policy
30 | attributes:
31 | label: Security Policy
32 | description: By submitting this issue, you agree to follow our [Security Policy.](https://github.com/insightsengineering/teal/security/policy)
33 | options:
34 | - label: I agree to follow this project's Security Policy.
35 | required: true
36 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/question.yml:
--------------------------------------------------------------------------------
1 | ---
2 | name: ❓ Question
3 | description: Question about usage or documentation
4 | title: "[Question]: "
5 | labels: ["question"]
6 | body:
7 | - type: textarea
8 | attributes:
9 | label: What is your question?
10 | validations:
11 | required: true
12 | - type: checkboxes
13 | id: code-of-conduct
14 | attributes:
15 | label: Code of Conduct
16 | description: By submitting this issue, you agree to follow our [Code of Conduct.](https://insightsengineering.github.io/teal/latest-tag/CODE_OF_CONDUCT.html)
17 | options:
18 | - label: I agree to follow this project's Code of Conduct.
19 | required: true
20 | - type: checkboxes
21 | id: contributor-guidelines
22 | attributes:
23 | label: Contribution Guidelines
24 | description: By submitting this issue, you agree to follow our [Contribution Guidelines.](https://insightsengineering.github.io/teal/latest-tag/CONTRIBUTING.html)
25 | options:
26 | - label: I agree to follow this project's Contribution Guidelines.
27 | required: true
28 | - type: checkboxes
29 | id: security-policy
30 | attributes:
31 | label: Security Policy
32 | description: By submitting this issue, you agree to follow our [Security Policy.](https://github.com/insightsengineering/teal/security/policy)
33 | options:
34 | - label: I agree to follow this project's Security Policy.
35 | required: true
36 |
--------------------------------------------------------------------------------
/.github/pull_request_template.md:
--------------------------------------------------------------------------------
1 | # Pull Request
2 |
3 |
4 |
5 | Fixes #nnn
6 |
--------------------------------------------------------------------------------
/.github/workflows/cla.yaml:
--------------------------------------------------------------------------------
1 | name: CLA 🔏
2 |
3 | on:
4 | issue_comment:
5 | types:
6 | - created
7 | # For PRs that originate from forks
8 | pull_request_target:
9 | types:
10 | - opened
11 | - closed
12 | - synchronize
13 |
14 | jobs:
15 | CLA:
16 | name: CLA 📝
17 | uses: insightsengineering/.github/.github/workflows/cla.yaml@main
18 | secrets: inherit
19 |
--------------------------------------------------------------------------------
/.github/workflows/docs.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | name: Docs 📚
3 |
4 | on:
5 | push:
6 | branches:
7 | - main
8 | paths:
9 | - "inst/templates/**"
10 | - "_pkgdown.*"
11 | - DESCRIPTION
12 | - "**.md"
13 | - "**.Rmd"
14 | - "man/**"
15 | - "LICENSE.*"
16 | - NAMESPACE
17 | pull_request:
18 | types:
19 | - opened
20 | - synchronize
21 | - reopened
22 | - ready_for_review
23 | branches:
24 | - main
25 | paths:
26 | - "inst/templates/**"
27 | - "_pkgdown.*"
28 | - DESCRIPTION
29 | - "**.md"
30 | - "**.Rmd"
31 | - "man/**"
32 | - "LICENSE.*"
33 | - NAMESPACE
34 | workflow_dispatch:
35 |
36 | jobs:
37 | docs:
38 | name: Pkgdown Docs 📚
39 | uses: insightsengineering/r.pkg.template/.github/workflows/pkgdown.yaml@main
40 | secrets:
41 | REPO_GITHUB_TOKEN: ${{ secrets.REPO_GITHUB_TOKEN }}
42 | with:
43 | default-landing-page: latest-tag
44 | additional-unit-test-report-directories: unit-test-report-non-cran
45 | deps-installation-method: setup-r-dependencies
46 |
--------------------------------------------------------------------------------
/.github/workflows/post-release.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | name: Post release ✨
3 |
4 | on:
5 | release:
6 | types: ["released"]
7 |
8 | jobs:
9 | vbump:
10 | name: Version Bump 🤜🤛
11 | uses: insightsengineering/r.pkg.template/.github/workflows/version-bump.yaml@main
12 | secrets:
13 | REPO_GITHUB_TOKEN: ${{ secrets.REPO_GITHUB_TOKEN }}
14 | with:
15 | vbump-after-release: true
16 |
--------------------------------------------------------------------------------
/.github/workflows/release.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | name: Release 🎈
3 |
4 | on:
5 | push:
6 | tags:
7 | - "v*"
8 | workflow_dispatch:
9 |
10 | jobs:
11 | docs:
12 | name: Pkgdown Docs 📚
13 | needs: release
14 | uses: insightsengineering/r.pkg.template/.github/workflows/pkgdown.yaml@main
15 | secrets:
16 | REPO_GITHUB_TOKEN: ${{ secrets.REPO_GITHUB_TOKEN }}
17 | with:
18 | default-landing-page: latest-tag
19 | deps-installation-method: setup-r-dependencies
20 | validation:
21 | name: R Package Validation report 📃
22 | needs: release
23 | uses: insightsengineering/r.pkg.template/.github/workflows/validation.yaml@main
24 | secrets:
25 | REPO_GITHUB_TOKEN: ${{ secrets.REPO_GITHUB_TOKEN }}
26 | with:
27 | deps-installation-method: setup-r-dependencies
28 | release:
29 | name: Create release 🎉
30 | uses: insightsengineering/r.pkg.template/.github/workflows/release.yaml@main
31 | secrets:
32 | REPO_GITHUB_TOKEN: ${{ secrets.REPO_GITHUB_TOKEN }}
33 | build:
34 | name: Build package and reports 🎁
35 | needs: [release, docs]
36 | uses: insightsengineering/r.pkg.template/.github/workflows/build-check-install.yaml@main
37 | secrets:
38 | REPO_GITHUB_TOKEN: ${{ secrets.REPO_GITHUB_TOKEN }}
39 | with:
40 | additional-env-vars: |
41 | _R_CHECK_CRAN_INCOMING_REMOTE_=false
42 | additional-r-cmd-check-params: --as-cran
43 | enforce-note-blocklist: true
44 | note-blocklist: |
45 | checking dependencies in R code .* NOTE
46 | checking R code for possible problems .* NOTE
47 | checking examples .* NOTE
48 | checking Rd line widths .* NOTE
49 | checking top-level files .* NOTE
50 | unit-test-report-brand: >-
51 | https://raw.githubusercontent.com/insightsengineering/hex-stickers/main/thumbs/teal.png
52 | deps-installation-method: setup-r-dependencies
53 | coverage:
54 | name: Coverage 📔
55 | needs: [release, docs]
56 | uses: insightsengineering/r.pkg.template/.github/workflows/test-coverage.yaml@main
57 | secrets:
58 | REPO_GITHUB_TOKEN: ${{ secrets.REPO_GITHUB_TOKEN }}
59 | with:
60 | additional-env-vars: |
61 | NOT_CRAN=true
62 | deps-installation-method: setup-r-dependencies
63 | wasm:
64 | name: Build WASM packages 🧑🏭
65 | needs: release
66 | uses: insightsengineering/r.pkg.template/.github/workflows/wasm.yaml@main
67 |
--------------------------------------------------------------------------------
/.github/workflows/scheduled.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | name: Scheduled 🕰️
3 |
4 | on:
5 | schedule:
6 | - cron: '45 3 * * 0'
7 | workflow_dispatch:
8 | inputs:
9 | chosen-workflow:
10 | description: |
11 | Select which workflow you'd like to run
12 | required: true
13 | type: choice
14 | default: rhub
15 | options:
16 | - rhub
17 | - dependency-test
18 | - branch-cleanup
19 | - revdepcheck
20 |
21 | jobs:
22 | dependency-test:
23 | if: >
24 | github.event_name == 'schedule' || (
25 | github.event_name == 'workflow_dispatch' &&
26 | inputs.chosen-workflow == 'dependency-test'
27 | )
28 | strategy:
29 | fail-fast: false
30 | matrix:
31 | test-strategy: ["min_cohort", "min_isolated", "release", "max"]
32 | uses: insightsengineering/r.pkg.template/.github/workflows/verdepcheck.yaml@main
33 | name: Dependency Test - ${{ matrix.test-strategy }} 🔢
34 | secrets:
35 | REPO_GITHUB_TOKEN: ${{ secrets.REPO_GITHUB_TOKEN }}
36 | GCHAT_WEBHOOK: ${{ secrets.GCHAT_WEBHOOK }}
37 | with:
38 | strategy: ${{ matrix.test-strategy }}
39 | additional-env-vars: |
40 | PKG_SYSREQS_DRY_RUN=true
41 | extra-deps: |
42 | matrixStats (>= 1.5.0)
43 | branch-cleanup:
44 | if: >
45 | github.event_name == 'schedule' || (
46 | github.event_name == 'workflow_dispatch' &&
47 | inputs.chosen-workflow == 'branch-cleanup'
48 | )
49 | name: Branch Cleanup 🧹
50 | uses: insightsengineering/r.pkg.template/.github/workflows/branch-cleanup.yaml@main
51 | secrets:
52 | REPO_GITHUB_TOKEN: ${{ secrets.REPO_GITHUB_TOKEN }}
53 | revdepcheck:
54 | if: >
55 | github.event_name == 'schedule' || (
56 | github.event_name == 'workflow_dispatch' &&
57 | inputs.chosen-workflow == 'revdepcheck'
58 | )
59 | name: revdepcheck ↩️
60 | uses: insightsengineering/r.pkg.template/.github/workflows/revdepcheck.yaml@main
61 |
62 | rhub:
63 | if: >
64 | github.event_name == 'schedule' || (
65 | github.event_name == 'workflow_dispatch' &&
66 | inputs.chosen-workflow == 'rhub'
67 | )
68 | name: R-hub 🌐
69 | uses: insightsengineering/r.pkg.template/.github/workflows/rhub.yaml@main
70 |
71 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.Rcheck
2 | *.html
3 | *.rprof
4 | *.sas.txt
5 | *~
6 | .DS_Store
7 | .RData
8 | .Rhistory
9 | .Rproj.user
10 | .Ruserdata
11 | .httr-oauth
12 | .project
13 | .settings/**
14 | /.project
15 | Meta
16 | coverage.*
17 | devel/*
18 | doc
19 | docs
20 | inst/outputs/*
21 | logs
22 | packrat/lib*/
23 | temp
24 | temp_w
25 | templates/
26 | tmp.*
27 | vignettes/*.R
28 | vignettes/*.html
29 | vignettes/*.md
30 | inst/doc
31 | tests/testthat/_snaps/**/*.new.md
32 | tests/testthat/_snaps/**/*.new.svg
33 | teal_app.lock
34 |
--------------------------------------------------------------------------------
/.gitlab-ci.yml:
--------------------------------------------------------------------------------
1 | ---
2 |
3 | include:
4 | - project: 'nest/automation/gitlab-shared-library'
5 | ref: main
6 | file: R/R_NEST_min.gitlab-ci.yml
7 |
--------------------------------------------------------------------------------
/.lintr:
--------------------------------------------------------------------------------
1 | linters: linters_with_defaults(
2 | line_length_linter = line_length_linter(120),
3 | cyclocomp_linter = NULL,
4 | object_usage_linter = NULL
5 | )
6 |
--------------------------------------------------------------------------------
/.pre-commit-config.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # All available hooks: https://pre-commit.com/hooks.html
3 | # R specific hooks: https://github.com/lorenzwalthert/precommit
4 | default_stages: [pre-commit]
5 | default_language_version:
6 | python: python3
7 | repos:
8 | - repo: https://github.com/lorenzwalthert/precommit
9 | rev: v0.4.3.9009
10 | hooks:
11 | - id: style-files
12 | name: Style code with `styler`
13 | args:
14 | [--style_pkg=styler, --style_fun=tidyverse_style, --cache-root=styler]
15 | - id: roxygenize
16 | name: Regenerate package documentation
17 | additional_dependencies:
18 | - davidgohel/flextable # Error: package 'flextable' is not available
19 | - davidgohel/gdtools # for flextable
20 | - mirai
21 | - checkmate
22 | - cli
23 | - htmltools
24 | - jsonlite
25 | - lifecycle
26 | - logger
27 | - magrittr
28 | - methods
29 | - renv
30 | - rlang
31 | - shiny
32 | - shinyjs
33 | - stats
34 | - insightsengineering/roxy.shinylive
35 | - insightsengineering/teal.code
36 | - insightsengineering/teal.data
37 | - insightsengineering/teal.logger
38 | - insightsengineering/teal.reporter
39 | - insightsengineering/teal.slice
40 | - insightsengineering/teal.widgets
41 | - utils
42 | - shinytest2 # Necessary for documentation
43 | - shinyvalidate # Necessary for documentation
44 | - rvest # Necessary for documentation
45 | - id: spell-check
46 | name: Check spelling with `spelling`
47 | exclude: >
48 | (?x)^(
49 | .*\.[rR]|
50 | .*\.css|
51 | .*\.jpg|
52 | .*\.js|
53 | .*\.png|
54 | .*\.py|
55 | .*\.RData|
56 | .*\.Rds|
57 | .*\.rds|
58 | .*\.Rproj|
59 | .*\.sh|
60 | .*\.svg|
61 | .*\.xml|
62 | (.*/|)\_pkgdown.y[a]?ml|
63 | (.*/|)\.covrignore|
64 | (.*/|)\.gitignore|
65 | (.*/|)\.gitlab-ci\.y[a]?ml|
66 | (.*/|)\.lintr|
67 | (.*/|)\.pre-commit-.*|
68 | (.*/|)\.Rbuildignore|
69 | (.*/|)\.Renviron|
70 | (.*/|)\.Rprofile|
71 | (.*/|)CODEOWNERS|
72 | (.*/|)DESCRIPTION|
73 | (.*/|)LICENSE|
74 | (.*/|)NAMESPACE|
75 | (.*/|)staged_dependencies\.y[a]?ml|
76 | (.*/|)WORDLIST|
77 | \.github/.*\.y[a]?ml|
78 | data/.*
79 | )$
80 | - id: no-browser-statement
81 | name: Check for browser() statement
82 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright 2022 F. Hoffmann-La Roche AG
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 |
--------------------------------------------------------------------------------
/NAMESPACE:
--------------------------------------------------------------------------------
1 | # Generated by roxygen2: do not edit by hand
2 |
3 | S3method(c,teal_slices)
4 | S3method(format,teal_module)
5 | S3method(format,teal_modules)
6 | S3method(join_keys,tdata)
7 | S3method(print,teal_module)
8 | S3method(print,teal_modules)
9 | S3method(srv_teal_module,default)
10 | S3method(srv_teal_module,teal_module)
11 | S3method(srv_teal_module,teal_modules)
12 | S3method(ui_teal_module,default)
13 | S3method(ui_teal_module,teal_module)
14 | S3method(ui_teal_module,teal_modules)
15 | S3method(within,teal_data_module)
16 | export(TealReportCard)
17 | export(add_landing_modal)
18 | export(as.teal_slices)
19 | export(as_tdata)
20 | export(build_app_title)
21 | export(example_module)
22 | export(get_code_tdata)
23 | export(get_metadata)
24 | export(init)
25 | export(landing_popup_module)
26 | export(make_teal_transform_server)
27 | export(modify_footer)
28 | export(modify_header)
29 | export(modify_title)
30 | export(module)
31 | export(modules)
32 | export(new_tdata)
33 | export(report_card_template)
34 | export(reporter_previewer_module)
35 | export(show_rcode_modal)
36 | export(srv_session_info)
37 | export(srv_teal)
38 | export(srv_teal_with_splash)
39 | export(srv_transform_teal_data)
40 | export(tdata2env)
41 | export(teal_data_module)
42 | export(teal_slices)
43 | export(teal_transform_module)
44 | export(ui_session_info)
45 | export(ui_teal)
46 | export(ui_teal_with_splash)
47 | export(ui_transform_teal_data)
48 | export(validate_has_data)
49 | export(validate_has_elements)
50 | export(validate_has_variable)
51 | export(validate_in)
52 | export(validate_inputs)
53 | export(validate_n_levels)
54 | export(validate_no_intersection)
55 | export(validate_one_row_per_id)
56 | import(shiny)
57 | import(teal.data)
58 | import(teal.slice)
59 | importFrom(methods,new)
60 | importFrom(methods,setMethod)
61 | importFrom(shiny,reactiveVal)
62 | importFrom(shiny,reactiveValues)
63 | importFrom(stats,setNames)
64 | importMethodsFrom(teal.code,eval_code)
65 |
--------------------------------------------------------------------------------
/R/checkmate.R:
--------------------------------------------------------------------------------
1 | #' Check that argument is reactive.
2 | #'
3 | #' @inherit checkmate::check_class params return
4 | #'
5 | #' @keywords internal
6 | check_reactive <- function(x, null.ok = FALSE) { # nolint: object_name_linter.
7 | if (!isTRUE(checkmate::test_class(x, classes = "reactive", null.ok = null.ok))) {
8 | cl <- class(x)
9 | return(sprintf(
10 | "Must be a reactive (i.e. inherit from 'reactive' class) but has class%s '%s'",
11 | if (length(cl) > 1L) "es" else "",
12 | paste0(cl, collapse = "','")
13 | ))
14 | }
15 | return(TRUE)
16 | }
17 | #' @rdname check_reactive
18 | test_reactive <- function(x, null.ok = FALSE) { # nolint: object_name_linter.
19 | isTRUE(check_reactive(x, null.ok = null.ok))
20 | }
21 | #' @rdname check_reactive
22 | assert_reactive <- checkmate::makeAssertionFunction(check_reactive)
23 |
24 | #' Capture error and decorate error message.
25 | #'
26 | #' @param x object to evaluate
27 | #' @param pre (`character(1)`) A string to prepend to error message
28 | #' @param post (`character(1)`) A string to append to error message
29 | #'
30 | #' @return `x` if no error, otherwise throws error with decorated message
31 | #'
32 | #' @keywords internal
33 | decorate_err_msg <- function(x, pre = character(0), post = character(0)) {
34 | tryCatch(
35 | x,
36 | error = function(e) {
37 | stop(
38 | "\n",
39 | pre,
40 | "\n",
41 | e$message,
42 | "\n",
43 | post,
44 | call. = FALSE
45 | )
46 | }
47 | )
48 | x
49 | }
50 |
--------------------------------------------------------------------------------
/R/include_css_js.R:
--------------------------------------------------------------------------------
1 | #' Include `CSS` files from `/inst/css/` package directory to application header
2 | #'
3 | #' `system.file` should not be used to access files in other packages, it does
4 | #' not work with `devtools`. Therefore, we redefine this method in each package
5 | #' as needed. Thus, we do not export this method.
6 | #'
7 | #' @param pattern (`character`) pattern of files to be included
8 | #'
9 | #' @return HTML code that includes `CSS` files.
10 | #' @keywords internal
11 | include_css_files <- function(pattern = "*") {
12 | css_files <- list.files(
13 | system.file("css", package = "teal", mustWork = TRUE),
14 | pattern = pattern, full.names = TRUE
15 | )
16 |
17 | singleton(
18 | tags$head(lapply(css_files, includeCSS))
19 | )
20 | }
21 |
22 | #' Include `JS` files from `/inst/js/` package directory to application header
23 | #'
24 | #' `system.file` should not be used to access files in other packages, it does
25 | #' not work with `devtools`. Therefore, we redefine this method in each package
26 | #' as needed. Thus, we do not export this method
27 | #'
28 | #' @param pattern (`character`) pattern of files to be included, passed to `system.file`
29 | #' @param except (`character`) vector of basename filenames to be excluded
30 | #'
31 | #' @return HTML code that includes `JS` files.
32 | #' @keywords internal
33 | include_js_files <- function(pattern = NULL, except = NULL) {
34 | checkmate::assert_character(except, min.len = 1, any.missing = FALSE, null.ok = TRUE)
35 | js_files <- list.files(system.file("js", package = "teal", mustWork = TRUE), pattern = pattern, full.names = TRUE)
36 | js_files <- js_files[!(basename(js_files) %in% except)] # no-op if except is NULL
37 |
38 | singleton(lapply(js_files, includeScript))
39 | }
40 |
41 | #' Run `JS` file from `/inst/js/` package directory
42 | #'
43 | #' This is triggered from the server to execute on the client
44 | #' rather than triggered directly on the client.
45 | #' Unlike `include_js_files` which includes `JavaScript` functions,
46 | #' the `run_js` actually executes `JavaScript` functions.
47 | #'
48 | #' `system.file` should not be used to access files in other packages, it does
49 | #' not work with `devtools`. Therefore, we redefine this method in each package
50 | #' as needed. Thus, we do not export this method.
51 | #'
52 | #' @param files (`character`) vector of filenames.
53 | #'
54 | #' @return `NULL`, invisibly.
55 | #' @keywords internal
56 | run_js_files <- function(files) {
57 | checkmate::assert_character(files, min.len = 1, any.missing = FALSE)
58 | lapply(files, function(file) {
59 | shinyjs::runjs(paste0(readLines(system.file("js", file, package = "teal", mustWork = TRUE)), collapse = "\n"))
60 | })
61 | invisible(NULL)
62 | }
63 |
64 | #' Code to include `teal` `CSS` and `JavaScript` files
65 | #'
66 | #' This is useful when you want to use the same `JavaScript` and `CSS` files that are
67 | #' used with the `teal` application.
68 | #' This is also useful for running standalone modules in `teal` with the correct
69 | #' styles.
70 | #' Also initializes `shinyjs` so you can use it.
71 | #'
72 | #' Simply add `include_teal_css_js()` as one of the UI elements.
73 | #' @return A `shiny.tag.list`.
74 | #' @keywords internal
75 | include_teal_css_js <- function() {
76 | tagList(
77 | shinyjs::useShinyjs(),
78 | include_css_files(),
79 | # init.js is executed from the server
80 | include_js_files(except = "init.js"),
81 | shinyjs::hidden(icon("fas fa-gear")), # add hidden icon to load font-awesome css for icons
82 | )
83 | }
84 |
--------------------------------------------------------------------------------
/R/landing_popup_module.R:
--------------------------------------------------------------------------------
1 | #' Landing popup module
2 | #'
3 | #' @description `r lifecycle::badge("deprecated")` Creates a landing welcome popup for `teal` applications.
4 | #'
5 | #' This module is used to display a popup dialog when the application starts.
6 | #' The dialog blocks access to the application and must be closed with a button before the application can be viewed.
7 | #' This function is deprecated, please use `add_landing_modal()` on the teal app object instead.
8 | #'
9 | #' @param label (`character(1)`) Label of the module.
10 | #' @param title (`character(1)`) Text to be displayed as popup title.
11 | #' @param content (`character(1)`, `shiny.tag` or `shiny.tag.list`) with the content of the popup.
12 | #' Passed to `...` of `shiny::modalDialog`. See examples.
13 | #' @param buttons (`shiny.tag` or `shiny.tag.list`) Typically a `modalButton` or `actionButton`. See examples.
14 | #'
15 | #' @return A `teal_module` (extended with `teal_landing_module` class) to be used in `teal` applications.
16 | #'
17 | #' @export
18 | landing_popup_module <- function(label = "Landing Popup",
19 | title = NULL,
20 | content = NULL,
21 | buttons = modalButton("Accept")) {
22 | lifecycle::deprecate_soft(
23 | when = "0.16.0",
24 | what = "landing_popup_module()",
25 | details = paste(
26 | "landing_popup_module() is deprecated.",
27 | "Use add_landing_modal() on the teal app object instead."
28 | )
29 | )
30 | checkmate::assert_string(label)
31 | checkmate::assert_string(title, null.ok = TRUE)
32 | checkmate::assert_multi_class(
33 | content,
34 | classes = c("character", "shiny.tag", "shiny.tag.list", "html"), null.ok = TRUE
35 | )
36 | checkmate::assert_multi_class(buttons, classes = c("shiny.tag", "shiny.tag.list"))
37 |
38 | message("Initializing landing_popup_module")
39 |
40 | module <- module(
41 | label = label,
42 | datanames = NULL,
43 | server = function(id) {
44 | moduleServer(id, function(input, output, session) {
45 | showModal(
46 | modalDialog(
47 | id = "landingpopup",
48 | title = title,
49 | content,
50 | footer = buttons
51 | )
52 | )
53 | })
54 | }
55 | )
56 | class(module) <- c("teal_module_landing", class(module))
57 | module
58 | }
59 |
--------------------------------------------------------------------------------
/R/module_session_info.R:
--------------------------------------------------------------------------------
1 | #' `teal` user session info module
2 | #'
3 | #' Module to display the user session info popup and to download a lockfile. Module is included
4 | #' when running [init()] but skipped when using [`module_teal`]. Please be aware that session info
5 | #' contains R session information, so multiple module's calls will share the same information.
6 | #'
7 | #' @rdname module_session_info
8 | #' @name module_session_info
9 | #'
10 | #' @inheritParams module_teal
11 | #'
12 | #' @examplesShinylive
13 | #' library(teal)
14 | #' interactive <- function() TRUE
15 | #' {{ next_example }}
16 | #' @examples
17 | #' ui <- fluidPage(
18 | #' ui_session_info("session_info")
19 | #' )
20 | #'
21 | #' server <- function(input, output, session) {
22 | #' srv_session_info("session_info")
23 | #' }
24 | #'
25 | #' if (interactive()) {
26 | #' shinyApp(ui, server)
27 | #' }
28 | #'
29 | #' @return `NULL` invisibly
30 | NULL
31 |
32 | #' @rdname module_session_info
33 | #' @export
34 | ui_session_info <- function(id) {
35 | ns <- NS(id)
36 | tags$div(
37 | teal.widgets::verbatim_popup_ui(ns("sessionInfo"), "Session Info", type = "link"),
38 | br(),
39 | ui_teal_lockfile(ns("lockfile")),
40 | textOutput(ns("identifier"))
41 | )
42 | }
43 |
44 | #' @rdname module_session_info
45 | #' @export
46 | srv_session_info <- function(id) {
47 | moduleServer(id, function(input, output, session) {
48 | srv_teal_lockfile("lockfile")
49 |
50 | output$identifier <- renderText(
51 | paste0("Pid:", Sys.getpid(), " Token:", substr(session$token, 25, 32))
52 | )
53 |
54 | teal.widgets::verbatim_popup_srv(
55 | "sessionInfo",
56 | verbatim_content = utils::capture.output(utils::sessionInfo()),
57 | title = "SessionInfo"
58 | )
59 | })
60 | }
61 |
--------------------------------------------------------------------------------
/R/module_teal_with_splash.R:
--------------------------------------------------------------------------------
1 | #' UI and server modules of `teal`
2 | #'
3 | #' @description `r lifecycle::badge("deprecated")`
4 | #' Please use [`module_teal`] instead.
5 | #'
6 | #' @inheritParams ui_teal
7 | #' @inheritParams srv_teal
8 | #' @inheritParams init
9 | #'
10 | #' @return
11 | #' Returns a `reactive` expression containing a `teal_data` object when data is loaded or `NULL` when it is not.
12 | #' @name module_teal_with_splash
13 | #'
14 | NULL
15 |
16 | #' @export
17 | #' @rdname module_teal_with_splash
18 | ui_teal_with_splash <- function(id,
19 | data,
20 | modules,
21 | title = build_app_title(),
22 | header = tags$p(),
23 | footer = tags$p()) {
24 | lifecycle::deprecate_soft(
25 | when = "0.16.0",
26 | what = "ui_teal_with_splash()",
27 | details = "Please use `?ui_teal` instead"
28 | )
29 | ns <- shiny::NS(id)
30 | fluidPage(
31 | title = tags$div(
32 | id = ns("teal-app-title"),
33 | tags$head(
34 | tags$title("teal app"),
35 | tags$link(
36 | rel = "icon",
37 | href = .teal_favicon,
38 | sizes = "any"
39 | )
40 | )
41 | ),
42 | tags$header(id = ns("teal-header-content")),
43 | ui_teal(id = id, modules = modules),
44 | tags$footer(
45 | id = "teal-footer",
46 | tags$div(id = "teal-footer-content"),
47 | ui_session_info(ns("teal-footer-session_info"))
48 | )
49 | )
50 | }
51 |
52 | #' @export
53 | #' @rdname module_teal_with_splash
54 | srv_teal_with_splash <- function(id, data, modules, filter = teal_slices()) {
55 | lifecycle::deprecate_soft(
56 | when = "0.16.0",
57 | what = "srv_teal_with_splash()",
58 | details = "Deprecated, please use `?srv_teal` instead"
59 | )
60 | srv_teal(id = id, data = data, modules = modules, filter = filter)
61 | srv_session_info("teal-footer-session_info")
62 | }
63 |
--------------------------------------------------------------------------------
/R/reporter_previewer_module.R:
--------------------------------------------------------------------------------
1 | #' Create a `teal` module for previewing a report
2 | #'
3 | #' @description `r lifecycle::badge("experimental")`
4 | #'
5 | #' This function wraps [teal.reporter::reporter_previewer_ui()] and
6 | #' [teal.reporter::reporter_previewer_srv()] into a `teal_module` to be
7 | #' used in `teal` applications.
8 | #'
9 | #' If you are creating a `teal` application using [init()] then this
10 | #' module will be added to your application automatically if any of your `teal_modules`
11 | #' support report generation.
12 | #'
13 | #' @inheritParams teal_modules
14 | #' @param server_args (named `list`)
15 | #' Arguments passed to [teal.reporter::reporter_previewer_srv()].
16 | #'
17 | #' @return
18 | #' `teal_module` (extended with `teal_module_previewer` class) containing the `teal.reporter` previewer functionality.
19 | #'
20 | #' @export
21 | #'
22 | reporter_previewer_module <- function(label = "Report previewer", server_args = list()) {
23 | checkmate::assert_string(label)
24 | checkmate::assert_list(server_args, names = "named")
25 | checkmate::assert_true(all(names(server_args) %in% names(formals(teal.reporter::reporter_previewer_srv))))
26 |
27 | message("Initializing reporter_previewer_module")
28 |
29 | srv <- function(id, reporter, ...) {
30 | teal.reporter::reporter_previewer_srv(id, reporter, ...)
31 | }
32 |
33 | ui <- function(id, ...) {
34 | teal.reporter::reporter_previewer_ui(id, ...)
35 | }
36 |
37 | module <- module(
38 | label = "temporary label",
39 | server = srv, ui = ui,
40 | server_args = server_args, ui_args = list(), datanames = NULL
41 | )
42 | # Module is created with a placeholder label and the label is changed later.
43 | # This is to prevent another module being labeled "Report previewer".
44 | class(module) <- c(class(module), "teal_module_previewer")
45 | module$label <- label
46 | attr(module, "teal_bookmarkable") <- TRUE
47 | module
48 | }
49 |
--------------------------------------------------------------------------------
/R/show_rcode_modal.R:
--------------------------------------------------------------------------------
1 | #' Show `R` code modal
2 | #'
3 | #' @description `r lifecycle::badge("deprecated")`
4 | #'
5 | #' Use the [shiny::showModal()] function to show the `R` code inside.
6 | #'
7 | #' @param title (`character(1)`)
8 | #' Title of the modal, displayed in the first comment of the `R` code.
9 | #' @param rcode (`character`)
10 | #' vector with `R` code to show inside the modal.
11 | #' @param session (`ShinySession`) optional
12 | #' `shiny` session object, defaults to [shiny::getDefaultReactiveDomain()].
13 | #'
14 | #' @references [shiny::showModal()]
15 | #' @export
16 | show_rcode_modal <- function(title = NULL, rcode, session = getDefaultReactiveDomain()) {
17 | lifecycle::deprecate_soft(
18 | when = "0.16.0",
19 | what = "show_rcode_modal()",
20 | details = "This function will be removed in the next release."
21 | )
22 |
23 | rcode <- paste(rcode, collapse = "\n")
24 |
25 | ns <- session$ns
26 | showModal(modalDialog(
27 | tagList(
28 | tags$div(
29 | actionButton(ns("copyRCode"), "Copy to Clipboard", `data-clipboard-target` = paste0("#", ns("r_code"))),
30 | modalButton("Dismiss")
31 | ),
32 | tags$div(tags$pre(id = ns("r_code"), rcode)),
33 | ),
34 | title = title,
35 | footer = tagList(
36 | actionButton(ns("copyRCode"), "Copy to Clipboard", `data-clipboard-target` = paste0("#", ns("r_code"))),
37 | modalButton("Dismiss")
38 | ),
39 | size = "l",
40 | easyClose = TRUE
41 | ))
42 | }
43 |
--------------------------------------------------------------------------------
/R/tdata.R:
--------------------------------------------------------------------------------
1 | #' Create a `tdata` object
2 | #'
3 | #' @description `r lifecycle::badge("superseded")`
4 | #'
5 | #' Recent changes in `teal` cause modules to fail because modules expect a `tdata` object
6 | #' to be passed to the `data` argument but instead they receive a `teal_data` object,
7 | #' which is additionally wrapped in a reactive expression in the server functions.
8 | #' In order to easily adapt such modules without a proper refactor,
9 | #' use this function to downgrade the `data` argument.
10 | #'
11 | #' @name tdata
12 | #' @param ... ignored
13 | #' @return nothing
14 | NULL
15 |
16 | #' @rdname tdata
17 | #' @export
18 | new_tdata <- function(...) {
19 | .deprecate_tdata_msg()
20 | }
21 |
22 | #' @rdname tdata
23 | #' @export
24 | tdata2env <- function(...) {
25 | .deprecate_tdata_msg()
26 | }
27 |
28 | #' @rdname tdata
29 | #' @export
30 | get_code_tdata <- function(...) {
31 | .deprecate_tdata_msg()
32 | }
33 |
34 | #' @rdname tdata
35 | #' @export
36 | join_keys.tdata <- function(...) {
37 | .deprecate_tdata_msg()
38 | }
39 |
40 | #' @rdname tdata
41 | #' @export
42 | get_metadata <- function(...) {
43 | .deprecate_tdata_msg()
44 | }
45 |
46 | #' @rdname tdata
47 | #' @export
48 | as_tdata <- function(...) {
49 | .deprecate_tdata_msg()
50 | }
51 |
52 |
53 | .deprecate_tdata_msg <- function() {
54 | lifecycle::deprecate_stop(
55 | when = "0.16.0",
56 | what = "tdata()",
57 | details = paste(
58 | "tdata has been removed in favour of `teal_data`.\n",
59 | "Please follow migration instructions https://github.com/insightsengineering/teal/discussions/987."
60 | )
61 | )
62 | }
63 |
--------------------------------------------------------------------------------
/R/teal.R:
--------------------------------------------------------------------------------
1 | #' `teal`: Interactive exploration of clinical trials data
2 | #'
3 | #' The `teal` package provides a `shiny` based framework for creating an
4 | #' interactive data analysis environment.
5 | #'
6 | #' To learn mode about the package, visit the [project website](https://insightsengineering.github.io/teal/latest-tag/)
7 | #' or read the [init()] manual page.
8 | #'
9 | #' @keywords internal
10 | "_PACKAGE"
11 |
12 | #' @import shiny teal.data teal.slice
13 | #' @importFrom stats setNames
14 | #' @export
15 | NULL
16 |
--------------------------------------------------------------------------------
/R/teal_data_module-eval_code.R:
--------------------------------------------------------------------------------
1 | setOldClass("teal_data_module")
2 |
3 | #' Evaluate code on `teal_data_module`
4 | #'
5 | #' @details
6 | #' `eval_code` evaluates given code in the environment of the `teal_data` object created by the `teal_data_module`.
7 | #' The code is added to the `@code` slot of the `teal_data`.
8 | #'
9 | #' @param object (`teal_data_module`)
10 | #' @inheritParams teal.code::eval_code
11 | #'
12 | #' @return
13 | #' `eval_code` returns a `teal_data_module` object with a delayed evaluation of `code` when the module is run.
14 | #'
15 | #' @examples
16 | #' eval_code(tdm, "dataset1 <- subset(dataset1, Species == 'virginica')")
17 | #'
18 | #' @include teal_data_module.R
19 | #' @name eval_code
20 | #' @rdname teal_data_module
21 | #' @aliases eval_code,teal_data_module,character-method
22 | #' @aliases eval_code,teal_data_module,language-method
23 | #' @aliases eval_code,teal_data_module,expression-method
24 | #'
25 | #' @importFrom methods setMethod
26 | #' @importMethodsFrom teal.code eval_code
27 | #'
28 | setMethod("eval_code", signature = c("teal_data_module", "character"), function(object, code) {
29 | teal_data_module(
30 | ui = function(id) {
31 | ns <- NS(id)
32 | object$ui(ns("mutate_inner"))
33 | },
34 | server = function(id) {
35 | moduleServer(id, function(input, output, session) {
36 | data <- object$server("mutate_inner")
37 | td <- eventReactive(data(),
38 | {
39 | if (inherits(data(), c("teal_data", "qenv.error"))) {
40 | eval_code(data(), code)
41 | } else {
42 | data()
43 | }
44 | },
45 | ignoreNULL = FALSE
46 | )
47 | td
48 | })
49 | }
50 | )
51 | })
52 |
53 | setMethod("eval_code", signature = c("teal_data_module", "language"), function(object, code) {
54 | eval_code(object, code = paste(lang2calls(code), collapse = "\n"))
55 | })
56 |
57 | setMethod("eval_code", signature = c("teal_data_module", "expression"), function(object, code) {
58 | eval_code(object, code = paste(lang2calls(code), collapse = "\n"))
59 | })
60 |
--------------------------------------------------------------------------------
/R/teal_data_module-within.R:
--------------------------------------------------------------------------------
1 | #' Evaluate expression on `teal_data_module`
2 | #'
3 | #' @details
4 | #' `within` is a convenience function for evaluating inline code inside the environment of a `teal_data_module`.
5 | #' It accepts only inline expressions (both simple and compound) and allows for injecting values into `expr` through
6 | #' the `...` argument: as `name:value` pairs are passed to `...`, `name` in `expr` will be replaced with `value.`
7 | #'
8 | #' @param data (`teal_data_module`) object
9 | #' @param expr (`expression`) to evaluate. Must be inline code. See [within()]
10 | #' @param ... See `Details`.
11 | #'
12 | #' @return
13 | #' `within` returns a `teal_data_module` object with a delayed evaluation of `expr` when the module is run.
14 | #'
15 | #' @examples
16 | #' within(tdm, dataset1 <- subset(dataset1, Species == "virginica"))
17 | #'
18 | #' # use additional parameter for expression value substitution.
19 | #' valid_species <- "versicolor"
20 | #' within(tdm, dataset1 <- subset(dataset1, Species %in% species), species = valid_species)
21 | #' @include teal_data_module.R
22 | #' @name within
23 | #' @rdname teal_data_module
24 | #'
25 | #' @export
26 | #'
27 | within.teal_data_module <- function(data, expr, ...) {
28 | expr <- substitute(expr)
29 | extras <- list(...)
30 |
31 | # Add braces for consistency.
32 | if (!identical(as.list(expr)[[1L]], as.symbol("{"))) {
33 | expr <- call("{", expr)
34 | }
35 |
36 | calls <- as.list(expr)[-1]
37 |
38 | # Inject extra values into expressions.
39 | calls <- lapply(calls, function(x) do.call(substitute, list(x, env = extras)))
40 |
41 | eval_code(object = data, code = as.expression(calls))
42 | }
43 |
--------------------------------------------------------------------------------
/R/teal_data_module.R:
--------------------------------------------------------------------------------
1 | #' Data module for `teal` applications
2 | #'
3 | #' @description
4 | #' `r lifecycle::badge("experimental")`
5 | #'
6 | #' Create a `teal_data_module` object and evaluate code on it with history tracking.
7 | #'
8 | #' @details
9 | #' `teal_data_module` creates a `shiny` module to interactively supply or modify data in a `teal` application.
10 | #' The module allows for running any code (creation _and_ some modification) after the app starts or reloads.
11 | #' The body of the server function will be run in the app rather than in the global environment.
12 | #' This means it will be run every time the app starts, so use sparingly.
13 | #'
14 | #' Pass this module instead of a `teal_data` object in a call to [init()].
15 | #' Note that the server function must always return a `teal_data` object wrapped in a reactive expression.
16 | #'
17 | #' See vignette `vignette("data-as-shiny-module", package = "teal")` for more details.
18 | #'
19 | #' @param ui (`function(id)`)
20 | #' `shiny` module UI function; must only take `id` argument
21 | #' @param server (`function(id)`)
22 | #' `shiny` module server function; must only take `id` argument;
23 | #' must return reactive expression containing `teal_data` object
24 | #' @param label (`character(1)`) Label of the module.
25 | #' @param once (`logical(1)`)
26 | #' If `TRUE`, the data module will be shown only once and will disappear after successful data loading.
27 | #' App user will no longer be able to interact with this module anymore.
28 | #' If `FALSE`, the data module can be reused multiple times.
29 | #' App user will be able to interact and change the data output from the module multiple times.
30 | #'
31 | #' @return
32 | #' `teal_data_module` returns a list of class `teal_data_module` containing two elements, `ui` and
33 | #' `server` provided via arguments.
34 | #'
35 | #' @examples
36 | #' tdm <- teal_data_module(
37 | #' ui = function(id) {
38 | #' ns <- NS(id)
39 | #' actionButton(ns("submit"), label = "Load data")
40 | #' },
41 | #' server = function(id) {
42 | #' moduleServer(id, function(input, output, session) {
43 | #' eventReactive(input$submit, {
44 | #' data <- within(
45 | #' teal_data(),
46 | #' {
47 | #' dataset1 <- iris
48 | #' dataset2 <- mtcars
49 | #' }
50 | #' )
51 | #'
52 | #' data
53 | #' })
54 | #' })
55 | #' }
56 | #' )
57 | #'
58 | #' @name teal_data_module
59 | #' @seealso [`teal.data::teal_data-class`], [teal.code::qenv()]
60 | #'
61 | #' @export
62 | teal_data_module <- function(ui, server, label = "data module", once = TRUE) {
63 | checkmate::assert_function(ui, args = "id", nargs = 1)
64 | checkmate::assert_function(server, args = "id", nargs = 1)
65 | checkmate::assert_string(label)
66 | checkmate::assert_flag(once)
67 | structure(
68 | list(
69 | ui = ui,
70 | server = function(id) {
71 | data_out <- server(id)
72 | decorate_err_msg(
73 | assert_reactive(data_out),
74 | pre = sprintf("From: 'teal_data_module()':\nA 'teal_data_module' with \"%s\" label:", label),
75 | post = "Please make sure that this module returns a 'reactive` object containing 'teal_data' class of object." # nolint: line_length_linter.
76 | )
77 | }
78 | ),
79 | label = label,
80 | class = "teal_data_module",
81 | once = once
82 | )
83 | }
84 |
--------------------------------------------------------------------------------
/R/teal_data_utils.R:
--------------------------------------------------------------------------------
1 | #' `teal_data` utils
2 | #'
3 | #' In `teal` we need to recreate the `teal_data` object due to two operations:
4 | #' - we need to append filter-data code and objects which have been evaluated in `FilteredData` and
5 | #' we want to avoid double-evaluation.
6 | #' - we need to subset `teal_data` to `datanames` used by the module, to shorten obtainable R-code
7 | #'
8 | #' Due to above recreation of `teal_data` object can't be done simply by using public
9 | #' `teal.code` and `teal.data` methods.
10 | #'
11 | #' @param data (`teal_data`)
12 | #' @param code (`character`) code to append to the object's code slot.
13 | #' @param objects (`list`) objects to append to object's environment.
14 | #' @return modified `teal_data`
15 | #' @keywords internal
16 | #' @name teal_data_utilities
17 | NULL
18 |
19 | #' @rdname teal_data_utilities
20 | .append_evaluated_code <- function(data, code) {
21 | checkmate::assert_class(data, "teal_data")
22 | data@code <- c(data@code, code2list(code))
23 | methods::validObject(data)
24 | data
25 | }
26 |
27 | #' @rdname teal_data_utilities
28 | .append_modified_data <- function(data, objects) {
29 | checkmate::assert_class(data, "teal_data")
30 | checkmate::assert_class(objects, "list")
31 | new_env <- list2env(objects, parent = .GlobalEnv)
32 | rlang::env_coalesce(new_env, as.environment(data))
33 | data@.xData <- new_env
34 | data
35 | }
36 |
--------------------------------------------------------------------------------
/R/teal_slices-store.R:
--------------------------------------------------------------------------------
1 | #' Store and restore `teal_slices` object
2 | #'
3 | #' Functions that write a `teal_slices` object to a file in the `JSON` format,
4 | #' and also restore the object from disk.
5 | #'
6 | #' Date and date time objects are stored in the following formats:
7 | #'
8 | #' - `Date` class is converted to the `"ISO8601"` standard (`YYYY-MM-DD`).
9 | #' - `POSIX*t` classes are converted to character by using
10 | #' `format.POSIX*t(usetz = TRUE, tz = "UTC")` (`YYYY-MM-DD HH:MM:SS UTC`, where
11 | #' `UTC` is the `Coordinated Universal Time` timezone short-code).
12 | #'
13 | #' This format is assumed during `slices_restore`. All `POSIX*t` objects in
14 | #' `selected` or `choices` fields of `teal_slice` objects are always printed in
15 | #' `UTC` timezone as well.
16 | #'
17 | #' @param tss (`teal_slices`) object to be stored.
18 | #' @param file (`character(1)`) file path where `teal_slices` object will be
19 | #' saved and restored. The file extension should be `".json"`.
20 | #'
21 | #' @return `slices_store` returns `NULL`, invisibly.
22 | #'
23 | #' @seealso [teal_slices()]
24 | #'
25 | #' @keywords internal
26 | #'
27 | slices_store <- function(tss, file) {
28 | checkmate::assert_class(tss, "teal_slices")
29 | checkmate::assert_path_for_output(file, overwrite = TRUE, extension = "json")
30 |
31 | cat(format(tss, trim_lines = FALSE), "\n", file = file)
32 | }
33 |
34 | #' @rdname slices_store
35 | #' @return `slices_restore` returns a `teal_slices` object restored from the file.
36 | #' @keywords internal
37 | slices_restore <- function(file) {
38 | checkmate::assert_file_exists(file, access = "r", extension = "json")
39 |
40 | tss_json <- jsonlite::fromJSON(file, simplifyDataFrame = FALSE)
41 | tss_json$slices <-
42 | lapply(tss_json$slices, function(slice) {
43 | for (field in c("selected", "choices")) {
44 | if (!is.null(slice[[field]])) {
45 | if (length(slice[[field]]) > 0) {
46 | date_partial_regex <- "^[0-9]{4}-[0-9]{2}-[0-9]{2}"
47 | time_stamp_regex <- paste0(date_partial_regex, "\\s[0-9]{2}:[0-9]{2}:[0-9]{2}\\sUTC$")
48 |
49 | slice[[field]] <-
50 | if (all(grepl(paste0(date_partial_regex, "$"), slice[[field]]))) {
51 | as.Date(slice[[field]])
52 | } else if (all(grepl(time_stamp_regex, slice[[field]]))) {
53 | as.POSIXct(slice[[field]], tz = "UTC")
54 | } else {
55 | slice[[field]]
56 | }
57 | } else {
58 | slice[[field]] <- character(0)
59 | }
60 | }
61 | }
62 | slice
63 | })
64 |
65 | tss_elements <- lapply(tss_json$slices, as.teal_slice)
66 |
67 | do.call(teal_slices, c(tss_elements, tss_json$attributes))
68 | }
69 |
--------------------------------------------------------------------------------
/R/zzz.R:
--------------------------------------------------------------------------------
1 | .onLoad <- function(libname, pkgname) {
2 | # adapted from https://github.com/r-lib/devtools/blob/master/R/zzz.R
3 |
4 | teal_default_options <- list(
5 | teal.show_js_log = FALSE,
6 | teal.lockfile.mode = "auto",
7 | shiny.sanitize.errors = FALSE
8 | )
9 |
10 | op <- options()
11 | toset <- !(names(teal_default_options) %in% names(op))
12 | if (any(toset)) options(teal_default_options[toset])
13 |
14 | # Set up the teal logger instance
15 | teal.logger::register_logger("teal")
16 | teal.logger::register_handlers("teal")
17 |
18 | invisible()
19 | }
20 |
21 | .onAttach <- function(libname, pkgname) {
22 | packageStartupMessage(
23 | "\nYou are using teal version ",
24 | # `system.file` uses the `shim` of `system.file` by `teal`
25 | # we avoid `desc` dependency here to get the version
26 | read.dcf(system.file("DESCRIPTION", package = "teal"))[, "Version"]
27 | )
28 | }
29 |
30 | # This one is here because setdiff_teal_slice should not be exported from teal.slice.
31 | setdiff_teal_slices <- getFromNamespace("setdiff_teal_slices", "teal.slice")
32 | # This one is here because it is needed by c.teal_slices but we don't want it exported from teal.slice.
33 | coalesce_r <- getFromNamespace("coalesce_r", "teal.slice")
34 | # all *Block objects are private in teal.reporter
35 | RcodeBlock <- getFromNamespace("RcodeBlock", "teal.reporter") # nolint: object_name.
36 |
37 | # Use non-exported function(s) from teal.code
38 | # This one is here because lang2calls should not be exported from teal.code
39 | lang2calls <- getFromNamespace("lang2calls", "teal.code")
40 | code2list <- getFromNamespace("code2list", "teal.data")
41 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 | # Security Policy
2 |
3 | ## Reporting Security Issues
4 |
5 | If you believe you have found a security vulnerability in any of the repositories in this organization, please report it to us through coordinated disclosure.
6 |
7 | **Please do not report security vulnerabilities through public GitHub issues, discussions, or pull requests.**
8 |
9 | Instead, please send an email to vulnerability.management[@]roche.com.
10 |
11 | Please include as much of the information listed below as you can to help us better understand and resolve the issue:
12 |
13 | * The type of issue (e.g., buffer overflow, SQL injection, or cross-site scripting)
14 | * Full paths of source file(s) related to the manifestation of the issue
15 | * The location of the affected source code (tag/branch/commit or direct URL)
16 | * Any special configuration required to reproduce the issue
17 | * Step-by-step instructions to reproduce the issue
18 | * Proof-of-concept or exploit code (if possible)
19 | * Impact of the issue, including how an attacker might exploit the issue
20 |
21 | This information will help us triage your report more quickly.
22 |
23 | ## Data Security Standards (DSS)
24 |
25 | Please make sure that while reporting issues in the form a bug, feature, or pull request, *all* sensitive information such as [PII](https://www.dhs.gov/privacy-training/what-personally-identifiable-information), [PHI](https://www.hhs.gov/hipaa/for-professionals/security/laws-regulations/index.html), and [PCI](https://www.pcisecuritystandards.org/pci_security/standards_overview) is completely removed from any text and attachments, including pictures and videos.
26 |
--------------------------------------------------------------------------------
/inst/WORDLIST:
--------------------------------------------------------------------------------
1 | Biomarker
2 | CDISC
3 | Forkers
4 | Hoffmann
5 | MAEs
6 | ORCID
7 | Shinylive
8 | TLG
9 | Transformators
10 | UI
11 | UX
12 | args
13 | bookmarkable
14 | favicon
15 | favicons
16 | funder
17 | lockfile
18 | modularized
19 | omics
20 | pre
21 | quosure
22 | reactively
23 | summarization
24 | tabset
25 | themer
26 | theming
27 | transformator
28 | transformators
29 | ui
30 | uncheck
31 |
--------------------------------------------------------------------------------
/inst/css/custom.css:
--------------------------------------------------------------------------------
1 | /* teal custom css */
2 |
3 | /* per tag */
4 |
5 | body:not(.modal-open) {
6 | padding-right: 0 !important;
7 | overflow: auto !important;
8 | }
9 |
10 | /* teal_data_module modal styling */
11 | body > div:has(~ #shiny-modal-wrapper .fade .blur_background) {
12 | transition: filter 0.3s;
13 | }
14 |
15 | body > div:has(~ #shiny-modal-wrapper .blur_background) {
16 | filter: blur(5px);
17 | }
18 |
19 | #shiny-modal.fade.in:has(.hide_background) {
20 | transition: background-color 0.3s;
21 | }
22 |
23 | #shiny-modal:has(.hide_background) {
24 | background-color: var(--bs-white);
25 | }
26 |
27 | .btn {
28 | --bs-btn-padding-x: 0.7em;
29 | --bs-btn-padding-y: 0.4em;
30 | }
31 |
32 | :root {
33 | --bs-body-font-size: 0.875rem;
34 | }
35 |
36 | .accordion-button {
37 | font-size: 0.875rem;
38 | font-weight: bold;
39 | }
40 |
41 | .teal-body .tabbable > .nav-pills {
42 | width: calc(100% - 5rem);
43 | }
44 |
45 | .teal.bookmark-popup .modal-body {
46 | padding: 0 1.5rem;
47 | }
48 |
49 | .modal-dialog:has(.teal-filter-manager-modal) {
50 | width: fit-content;
51 | }
52 |
53 | .teal-body .bslib-mb-spacing {
54 | --bslib-mb-spacer: 0;
55 | }
56 |
--------------------------------------------------------------------------------
/inst/css/validation.css:
--------------------------------------------------------------------------------
1 | /* adding boarder to the validated input */
2 | .teal_validated:has(.shiny-output-error) {
3 | border: 1px solid red;
4 | border-radius: 4px;
5 | }
6 |
7 | .teal_validated:has(.teal-output-warning) {
8 | border: 1px solid orange;
9 | border-radius: 4px;
10 | }
11 |
12 | .teal_validated .teal-output-warning {
13 | color: #888;
14 | }
15 |
16 | .teal_validated .shiny-output-error,
17 | .teal_validated .teal-output-warning {
18 | margin-top: 0.5em;
19 | }
20 |
21 | .teal_validated .teal-output-warning::before {
22 | content: "\26A0\FE0F";
23 | }
24 |
25 | .teal_validated .shiny-output-error::before {
26 | content: "\1F6A8";
27 | }
28 |
29 | .teal_primary_col .shiny-output-error::before {
30 | content: "\1F6A8";
31 | }
32 |
33 | .teal_primary_col .teal-output-warning::before {
34 | content: "\26A0\FE0F";
35 | }
36 |
37 | .teal_primary_col .teal_validated:has(.shiny-output-error),
38 | .teal_primary_col .teal_validated:has(.teal-output-warning) {
39 | margin: 1em 0 1em 0;
40 | padding: 0.5em 0 0.5em 0.5em;
41 | }
42 |
43 | .teal_primary_col > .teal_validated:has(.teal-output-warning),
44 | .teal_primary_col > .teal_validated:has(.shiny-output-error) {
45 | width: 100%;
46 | background-color: rgba(223, 70, 97, 0.1);
47 | border: 1px solid red;
48 | padding: 1em;
49 | }
50 |
--------------------------------------------------------------------------------
/inst/js/init.js:
--------------------------------------------------------------------------------
1 | // This file contains functions that should be executed at the start of each session,
2 | // not included in the original HTML
3 |
4 | // this code alows the show R code "copy to clipbaord" button to work
5 | var clipboard = new ClipboardJS(".btn[data-clipboard-target]");
6 |
--------------------------------------------------------------------------------
/inst/js/togglePanelItems.js:
--------------------------------------------------------------------------------
1 | // When invoked it adds the setClass and removes the removeClass from the element.
2 | function setAndRemoveClass(element, setClass, removeClass) {
3 | if (typeof element === "string") {
4 | element = document.querySelector(element);
5 | }
6 | element.classList.add(setClass);
7 | element.classList.remove(removeClass);
8 | }
9 |
10 | // When invoked it toggles the class of the element.
11 | function toggleClass(element, class1, class2) {
12 | if (typeof element === "string") {
13 | element = document.querySelector(element);
14 | }
15 | if (element.classList.contains(class1)) {
16 | setAndRemoveClass(element, class2, class1);
17 | } else {
18 | setAndRemoveClass(element, class1, class2);
19 | }
20 | }
21 |
22 | // When invoked it shows the targetSelector element.
23 | function showPanelItem(targeSelector, duration = 400, easing = "slideInTop") {
24 | $(`#${targeSelector}`).show(duration, easing);
25 | $(`#${targeSelector}`).trigger("shown");
26 | }
27 |
28 | // When invoked it hides the targetSelector element.
29 | function hidePanelItem(targeSelector, duration = 400, easing = "slideOutLeft") {
30 | $(`#${targeSelector}`).hide(duration, easing);
31 | }
32 |
33 | // When invoked it hides/shows targetSelectors elements
34 | // and changes class of element from class1 <-> class2
35 | function togglePanelItems(
36 | element,
37 | targetSelectors,
38 | class1,
39 | class2,
40 | duration = 400,
41 | easing = "swing"
42 | ) {
43 | if (!Array.isArray(targetSelectors)) {
44 | targetSelectors = [targetSelectors];
45 | }
46 |
47 | targetSelectors.forEach((targetSelector) => {
48 | if ($(`#${targetSelector}`).is(":visible")) {
49 | hidePanelItem(targetSelector, duration, easing);
50 | } else {
51 | showPanelItem(targetSelector, duration, easing);
52 | }
53 | });
54 |
55 | toggleClass(element, class1, class2);
56 | }
57 |
--------------------------------------------------------------------------------
/man/add_landing_modal.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/teal_modifiers.R
3 | \name{add_landing_modal}
4 | \alias{add_landing_modal}
5 | \title{Add a Landing Popup to \code{teal} Application}
6 | \usage{
7 | add_landing_modal(
8 | x,
9 | title = NULL,
10 | content = NULL,
11 | footer = modalButton("Accept"),
12 | ...
13 | )
14 | }
15 | \arguments{
16 | \item{x}{(\code{teal_app}) A \code{teal_app} object created using the \code{init} function.}
17 |
18 | \item{title}{An optional title for the dialog.}
19 |
20 | \item{content}{(\code{character(1)}, \code{shiny.tag} or \code{shiny.tag.list}) with the content of the popup.}
21 |
22 | \item{footer}{UI for footer. Use \code{NULL} for no footer.}
23 |
24 | \item{...}{Additional arguments to \code{\link[shiny:modalDialog]{shiny::modalDialog()}}.}
25 | }
26 | \description{
27 | Adds a landing popup to the \code{teal} app. This popup will be shown when the app starts.
28 | The dialog must be closed by the app user to proceed to the main application.
29 | }
30 | \examples{
31 | app <- init(
32 | data = teal_data(IRIS = iris, MTCARS = mtcars),
33 | modules = modules(example_module())
34 | ) |>
35 | add_landing_modal(
36 | title = "Welcome",
37 | content = "This is a landing popup.",
38 | buttons = modalButton("Accept")
39 | )
40 |
41 | if (interactive()) {
42 | shinyApp(app$ui, app$server)
43 | }
44 | }
45 | \section{Examples in Shinylive}{
46 | \describe{
47 | \item{example-1}{
48 | \href{https://shinylive.io/r/app/#code=NobwRAdghgtgpmAXGKAHVA6ASmANGAYwHsIAXOMpMAGwEsAjAJykYE8AKcqagSgB0ItMnGYFStAG5wABAB4AtNIBmAVwhjaJdj2kAVLAFUAogIFpUcxUNql2A6dIAmUUlGkBeaV2oB9Z6-YASSxAgGUPaVpGWgBnXGkAWV0AYQBBLHDPGFICFhieXHtpGCJHFWo4GIiSsoqY9jgAD1hUCp8a8rhtfggdAB8APiKoR0cfaigIRyEAc3bS7jsIBwdxUgqIvjAAdThqYngtwuWV4mEyTbBdAAtYyKq3CanZ6VQiVBVMI6KHehVSUgkKpZBbUABC-0BEDsYFSBAIcFQpC2PQcPQEtCU0nYQnIonEUm60hARRitwgrFS6HY5gAJCpaPE6TERFJGD0AL5gDkAXSAA}{Open in Shinylive}
49 | \if{html}{\out{}}
50 | \if{html}{\out{}}
51 | }
52 | }
53 | }
54 |
55 |
--------------------------------------------------------------------------------
/man/append_module.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/modules.R
3 | \name{append_module}
4 | \alias{append_module}
5 | \title{Append a \code{teal_module} to \code{children} of a \code{teal_modules} object}
6 | \usage{
7 | append_module(modules, module)
8 | }
9 | \arguments{
10 | \item{modules}{(\code{teal_modules})}
11 |
12 | \item{module}{(\code{teal_module}) object to be appended onto the children of \code{modules}}
13 | }
14 | \value{
15 | A \code{teal_modules} object with \code{module} appended.
16 | }
17 | \description{
18 | Append a \code{teal_module} to \code{children} of a \code{teal_modules} object
19 | }
20 | \keyword{internal}
21 |
--------------------------------------------------------------------------------
/man/bookmarks_identical.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/module_bookmark_manager.R
3 | \name{bookmarks_identical}
4 | \alias{bookmarks_identical}
5 | \title{Compare bookmarks.}
6 | \usage{
7 | bookmarks_identical(book1, book2)
8 | }
9 | \arguments{
10 | \item{book1, book2}{bookmark directories stored in \verb{shiny_bookmarks/};
11 | default to the two most recently modified directories}
12 | }
13 | \value{
14 | Invisible \code{NULL} if bookmarks are identical or if there are no bookmarks to test.
15 | \code{FALSE} if inconsistencies are detected.
16 | }
17 | \description{
18 | Test if two bookmarks store identical state.
19 | }
20 | \details{
21 | \code{input} environments are compared one variable at a time and if not identical,
22 | values in both bookmarks are reported. States of \code{datatable}s are stripped
23 | of the \code{time} element before comparing because the time stamp is always different.
24 | The contents themselves are not printed as they are large and the contents are not informative.
25 | Elements present in one bookmark and absent in the other are also reported.
26 | Differences are printed as messages.
27 |
28 | \code{values} environments are compared with \code{all.equal}.
29 | }
30 | \section{How to use}{
31 |
32 | Open an application, change relevant inputs (typically, all of them), and create a bookmark.
33 | Then open that bookmark and immediately create a bookmark of that.
34 | If restoring bookmarks occurred properly, the two bookmarks should store the same state.
35 | }
36 |
37 | \keyword{internal}
38 |
--------------------------------------------------------------------------------
/man/build_app_title.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/utils.R
3 | \name{build_app_title}
4 | \alias{build_app_title}
5 | \title{Build app title with favicon}
6 | \usage{
7 | build_app_title(
8 | title = "teal app",
9 | favicon =
10 | "https://raw.githubusercontent.com/insightsengineering/hex-stickers/main/PNG/nest.png"
11 | )
12 | }
13 | \arguments{
14 | \item{title}{(\code{character}) The browser title for the \code{teal} app.}
15 |
16 | \item{favicon}{(\code{character}) The path for the icon for the title.
17 | The image/icon path can be remote or the static path accessible by \code{shiny}, like the \verb{www/}}
18 | }
19 | \value{
20 | A \code{shiny.tag} containing the element that adds the title and logo to the \code{shiny} app.
21 | }
22 | \description{
23 | A helper function to create the browser title along with a logo.
24 | }
25 |
--------------------------------------------------------------------------------
/man/check_filter_datanames.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/utils.R
3 | \name{check_filter_datanames}
4 | \alias{check_filter_datanames}
5 | \title{Check \code{datanames} in filters}
6 | \usage{
7 | check_filter_datanames(filters, datanames)
8 | }
9 | \arguments{
10 | \item{filters}{(\code{teal_slices}) object}
11 |
12 | \item{datanames}{(\code{character}) names of datasets available in the \code{data} object}
13 | }
14 | \value{
15 | A \code{character(1)} containing error message or TRUE if validation passes.
16 | }
17 | \description{
18 | This function checks whether \code{datanames} in filters correspond to those in \code{data},
19 | returning character vector with error messages or \code{TRUE} if all checks pass.
20 | }
21 | \keyword{internal}
22 |
--------------------------------------------------------------------------------
/man/check_modules_datanames.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/utils.R
3 | \name{check_modules_datanames}
4 | \alias{check_modules_datanames}
5 | \alias{check_reserved_datanames}
6 | \alias{check_modules_datanames_html}
7 | \title{Check \code{datanames} in modules}
8 | \usage{
9 | check_modules_datanames(modules, datanames)
10 |
11 | check_reserved_datanames(datanames)
12 |
13 | check_modules_datanames_html(modules, datanames)
14 | }
15 | \arguments{
16 | \item{modules}{(\code{teal_modules}) object}
17 |
18 | \item{datanames}{(\code{character}) names of datasets available in the \code{data} object}
19 | }
20 | \value{
21 | \code{TRUE} if validation passes, otherwise \code{character(1)} or \code{shiny.tag.list}
22 | }
23 | \description{
24 | These functions check if specified \code{datanames} in modules match those in the data object,
25 | returning error messages or \code{TRUE} for successful validation. Two functions return error message
26 | in different forms:
27 | \itemize{
28 | \item \code{check_modules_datanames} returns \code{character(1)} for basic assertion usage
29 | \item \code{check_modules_datanames_html} returns \code{shiny.tag.list} to display it in the app.
30 | }
31 | }
32 | \keyword{internal}
33 |
--------------------------------------------------------------------------------
/man/check_reactive.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/checkmate.R
3 | \name{check_reactive}
4 | \alias{check_reactive}
5 | \alias{test_reactive}
6 | \alias{assert_reactive}
7 | \title{Check that argument is reactive.}
8 | \usage{
9 | check_reactive(x, null.ok = FALSE)
10 |
11 | test_reactive(x, null.ok = FALSE)
12 |
13 | assert_reactive(
14 | x,
15 | null.ok = FALSE,
16 | .var.name = checkmate::vname(x),
17 | add = NULL
18 | )
19 | }
20 | \arguments{
21 | \item{x}{[any]\cr
22 | Object to check.}
23 |
24 | \item{null.ok}{[\code{logical(1)}]\cr
25 | If set to \code{TRUE}, \code{x} may also be \code{NULL}.
26 | In this case only a type check of \code{x} is performed, all additional checks are disabled.}
27 |
28 | \item{.var.name}{[\code{character(1)}]\cr
29 | Name of the checked object to print in assertions. Defaults to
30 | the heuristic implemented in \code{\link[checkmate]{vname}}.}
31 |
32 | \item{add}{[\code{AssertCollection}]\cr
33 | Collection to store assertion messages. See \code{\link[checkmate]{AssertCollection}}.}
34 | }
35 | \value{
36 | Depending on the function prefix:
37 | If the check is successful, the functions
38 | \code{assertClass}/\code{assert_class} return
39 | \code{x} invisibly, whereas
40 | \code{checkClass}/\code{check_class} and
41 | \code{testClass}/\code{test_class} return
42 | \code{TRUE}.
43 | If the check is not successful,
44 | \code{assertClass}/\code{assert_class}
45 | throws an error message,
46 | \code{testClass}/\code{test_class}
47 | returns \code{FALSE},
48 | and \code{checkClass}/\code{check_class}
49 | return a string with the error message.
50 | The function \code{expect_class} always returns an
51 | \code{\link[testthat]{expectation}}.
52 | }
53 | \description{
54 | Check that argument is reactive.
55 | }
56 | \keyword{internal}
57 |
--------------------------------------------------------------------------------
/man/create_app_id.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/utils.R
3 | \name{create_app_id}
4 | \alias{create_app_id}
5 | \title{Application ID}
6 | \usage{
7 | create_app_id(data, modules)
8 | }
9 | \arguments{
10 | \item{data}{(\code{teal_data} or \code{teal_data_module}) as accepted by \code{init}}
11 |
12 | \item{modules}{(\code{teal_modules}) object as accepted by \code{init}}
13 | }
14 | \value{
15 | A single character string.
16 | }
17 | \description{
18 | Creates App ID used to match filter snapshots to application.
19 | }
20 | \details{
21 | Calculate app ID that will be used to stamp filter state snapshots.
22 | App ID is a hash of the app's data and modules.
23 | See "transferring snapshots" section in ?snapshot.
24 | }
25 | \keyword{internal}
26 |
--------------------------------------------------------------------------------
/man/decorate_err_msg.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/checkmate.R
3 | \name{decorate_err_msg}
4 | \alias{decorate_err_msg}
5 | \title{Capture error and decorate error message.}
6 | \usage{
7 | decorate_err_msg(x, pre = character(0), post = character(0))
8 | }
9 | \arguments{
10 | \item{x}{object to evaluate}
11 |
12 | \item{pre}{(\code{character(1)}) A string to prepend to error message}
13 |
14 | \item{post}{(\code{character(1)}) A string to append to error message}
15 | }
16 | \value{
17 | \code{x} if no error, otherwise throws error with decorated message
18 | }
19 | \description{
20 | Capture error and decorate error message.
21 | }
22 | \keyword{internal}
23 |
--------------------------------------------------------------------------------
/man/deep_copy_filter.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/teal_slices.R
3 | \name{deep_copy_filter}
4 | \alias{deep_copy_filter}
5 | \title{Deep copy \code{teal_slices}}
6 | \usage{
7 | deep_copy_filter(filter)
8 | }
9 | \arguments{
10 | \item{filter}{(\code{teal_slices})}
11 | }
12 | \value{
13 | \code{teal_slices}
14 | }
15 | \description{
16 | it's important to create a new copy of \code{teal_slices} when
17 | starting a new \code{shiny} session. Otherwise, object will be shared
18 | by multiple users as it is created in global environment before
19 | \code{shiny} session starts.
20 | }
21 | \keyword{internal}
22 |
--------------------------------------------------------------------------------
/man/dot-add_signature_to_data.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/module_init_data.R
3 | \name{.add_signature_to_data}
4 | \alias{.add_signature_to_data}
5 | \title{Adds signature protection to the \code{datanames} in the data}
6 | \usage{
7 | .add_signature_to_data(data)
8 | }
9 | \arguments{
10 | \item{data}{(\code{teal_data})}
11 | }
12 | \value{
13 | \code{teal_data} with additional code that has signature of the \code{datanames}
14 | }
15 | \description{
16 | Adds signature protection to the \code{datanames} in the data
17 | }
18 | \keyword{internal}
19 |
--------------------------------------------------------------------------------
/man/dot-call_once_when.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/module_nested_tabs.R
3 | \name{.call_once_when}
4 | \alias{.call_once_when}
5 | \title{Calls expression when condition is met}
6 | \usage{
7 | .call_once_when(
8 | eventExpr,
9 | handlerExpr,
10 | event.env = parent.frame(),
11 | handler.env = parent.frame(),
12 | ...
13 | )
14 | }
15 | \arguments{
16 | \item{eventExpr}{A (quoted or unquoted) logical expression that represents the event;
17 | this can be a simple reactive value like input$click, a call to a reactive expression
18 | like dataset(), or even a complex expression inside curly braces.}
19 |
20 | \item{handlerExpr}{The expression to call whenever \code{eventExpr} is
21 | invalidated. This should be a side-effect-producing action (the return
22 | value will be ignored). It will be executed within an \code{\link[shiny:isolate]{isolate()}}
23 | scope.}
24 |
25 | \item{event.env}{The parent environment for the reactive expression. By default,
26 | this is the calling environment, the same as when defining an ordinary
27 | non-reactive expression. If \code{eventExpr} is a quosure and \code{event.quoted} is \code{TRUE},
28 | then \code{event.env} is ignored.}
29 |
30 | \item{handler.env}{The parent environment for the reactive expression. By default,
31 | this is the calling environment, the same as when defining an ordinary
32 | non-reactive expression. If \code{handlerExpr} is a quosure and \code{handler.quoted} is \code{TRUE},
33 | then \code{handler.env} is ignored.}
34 |
35 | \item{...}{additional arguments passed to \code{observeEvent} with the exception of \code{eventExpr} that is not allowed.}
36 | }
37 | \value{
38 | An observer.
39 | }
40 | \description{
41 | Function postpones \code{handlerExpr} to the moment when \code{eventExpr} (condition) returns \code{TRUE},
42 | otherwise nothing happens.
43 | }
44 | \keyword{internal}
45 |
--------------------------------------------------------------------------------
/man/dot-get_hashes_code.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/module_init_data.R
3 | \name{.get_hashes_code}
4 | \alias{.get_hashes_code}
5 | \title{Get code that tests the integrity of the reproducible data}
6 | \usage{
7 | .get_hashes_code(data, datanames = names(data))
8 | }
9 | \arguments{
10 | \item{data}{(\code{teal_data}) object holding the data}
11 |
12 | \item{datanames}{(\code{character}) names of \code{datasets}}
13 | }
14 | \value{
15 | A character vector with the code lines.
16 | }
17 | \description{
18 | Get code that tests the integrity of the reproducible data
19 | }
20 | \keyword{internal}
21 |
--------------------------------------------------------------------------------
/man/dot-smart_rbind.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/utils.R
3 | \name{.smart_rbind}
4 | \alias{.smart_rbind}
5 | \title{Smart \code{rbind}}
6 | \usage{
7 | .smart_rbind(...)
8 | }
9 | \arguments{
10 | \item{...}{(\code{data.frame})}
11 | }
12 | \description{
13 | Combine \code{data.frame} objects which have different columns
14 | }
15 | \keyword{internal}
16 |
--------------------------------------------------------------------------------
/man/dot-teal_favicon.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/utils.R
3 | \docType{data}
4 | \name{.teal_favicon}
5 | \alias{.teal_favicon}
6 | \title{The default favicon for the teal app.}
7 | \format{
8 | An object of class \code{character} of length 1.
9 | }
10 | \usage{
11 | .teal_favicon
12 | }
13 | \description{
14 | The default favicon for the teal app.
15 | }
16 | \keyword{internal}
17 |
--------------------------------------------------------------------------------
/man/example_module.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/dummy_functions.R
3 | \name{example_module}
4 | \alias{example_module}
5 | \title{An example \code{teal} module}
6 | \usage{
7 | example_module(
8 | label = "example teal module",
9 | datanames = "all",
10 | transformators = list(),
11 | decorators = list()
12 | )
13 | }
14 | \arguments{
15 | \item{label}{(\code{character(1)}) Label shown in the navigation item for the module or module group.
16 | For \code{modules()} defaults to \code{"root"}. See \code{Details}.}
17 |
18 | \item{datanames}{(\code{character}) Names of the datasets relevant to the item.
19 | There are 2 reserved values that have specific behaviors:
20 | \itemize{
21 | \item The keyword \code{"all"} includes all datasets available in the data passed to the teal application.
22 | \item \code{NULL} hides the sidebar panel completely.
23 | \item If \code{transformators} are specified, their \code{datanames} are automatically added to this \code{datanames}
24 | argument.
25 | }}
26 |
27 | \item{transformators}{(\code{list} of \code{teal_transform_module}) that will be applied to transform module's data input.
28 | To learn more check \code{vignette("transform-input-data", package = "teal")}.}
29 |
30 | \item{decorators}{\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#experimental}{\figure{lifecycle-experimental.svg}{options: alt='[Experimental]'}}}{\strong{[Experimental]}} (\code{list} of \code{teal_transform_module}) optional,
31 | decorator for \code{object} included in the module.}
32 | }
33 | \value{
34 | A \code{teal} module which can be included in the \code{modules} argument to \code{\link[=init]{init()}}.
35 | }
36 | \description{
37 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#experimental}{\figure{lifecycle-experimental.svg}{options: alt='[Experimental]'}}}{\strong{[Experimental]}}
38 | }
39 | \details{
40 | This module creates an object called \code{object} that can be modified with decorators.
41 | The \code{object} is determined by what's selected in \verb{Choose a dataset} input in UI.
42 | The object can be anything that can be handled by \code{renderPrint()}.
43 | See the \code{vignette("transform-module-output", package = "teal")} or \code{\link{teal_transform_module}}
44 | to read more about decorators.
45 | }
46 | \examples{
47 | app <- init(
48 | data = teal_data(IRIS = iris, MTCARS = mtcars),
49 | modules = example_module()
50 | )
51 | if (interactive()) {
52 | shinyApp(app$ui, app$server)
53 | }
54 | }
55 | \section{Examples in Shinylive}{
56 | \describe{
57 | \item{example-1}{
58 | \href{https://shinylive.io/r/app/#code=NobwRAdghgtgpmAXGKAHVA6ASmANGAYwHsIAXOMpMAGwEsAjAJykYE8AKcqagSgB0ItMnGYFStAG5wABAB4AtNIBmAVwhjaJdj2kAVLAFUAogIFpUcxUNql2A6dIAmUUlGkBeaV2oB9Z6-YASSxAgGUPaVpGWgBnXGkAWV0AYQBBLHDPGFICFhieXHtpGCJHFWo4GIi4AA9YVAqfErKK7QF+QSVpdiFyUXEpbR0QIpiACyFWVPR2cwASFVp4+ZiRKUYOgF8wTYBdIA}{Open in Shinylive}
59 | \if{html}{\out{}}
60 | \if{html}{\out{}}
61 | }
62 | }
63 | }
64 |
65 |
--------------------------------------------------------------------------------
/man/extract_transformators.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/teal_transform_module.R
3 | \name{extract_transformators}
4 | \alias{extract_transformators}
5 | \title{Extract all \code{transformators} from \code{modules}.}
6 | \usage{
7 | extract_transformators(modules)
8 | }
9 | \arguments{
10 | \item{modules}{\code{teal_modules} or \code{teal_module}}
11 | }
12 | \value{
13 | A list of \code{teal_transform_module} nested in the same way as input \code{modules}.
14 | }
15 | \description{
16 | Extract all \code{transformators} from \code{modules}.
17 | }
18 | \keyword{internal}
19 |
--------------------------------------------------------------------------------
/man/figures/filterpanel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/insightsengineering/teal/3d6b93310c969e0a6fecab41102846c94d99d4f1/man/figures/filterpanel.png
--------------------------------------------------------------------------------
/man/figures/lifecycle-archived.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/man/figures/lifecycle-defunct.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/man/figures/lifecycle-deprecated.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/man/figures/lifecycle-experimental.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/man/figures/lifecycle-maturing.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/man/figures/lifecycle-questioning.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/man/figures/lifecycle-soft-deprecated.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/man/figures/lifecycle-stable.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/man/figures/lifecycle-superseded.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/man/figures/readme_app.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/insightsengineering/teal/3d6b93310c969e0a6fecab41102846c94d99d4f1/man/figures/readme_app.webp
--------------------------------------------------------------------------------
/man/figures/reporter.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/insightsengineering/teal/3d6b93310c969e0a6fecab41102846c94d99d4f1/man/figures/reporter.jpg
--------------------------------------------------------------------------------
/man/figures/showrcode.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/insightsengineering/teal/3d6b93310c969e0a6fecab41102846c94d99d4f1/man/figures/showrcode.jpg
--------------------------------------------------------------------------------
/man/get_client_timezone.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/utils.R
3 | \name{get_client_timezone}
4 | \alias{get_client_timezone}
5 | \title{Get client timezone}
6 | \usage{
7 | get_client_timezone(ns)
8 | }
9 | \arguments{
10 | \item{ns}{(\code{function}) namespace function passed from the \code{session} object in the \code{shiny} server.
11 | For \code{shiny} modules this will allow for proper name spacing of the registered input.}
12 | }
13 | \value{
14 | \code{NULL}, invisibly.
15 | }
16 | \description{
17 | User timezone in the browser may be different to the one on the server.
18 | This script can be run to register a \code{shiny} input which contains information about the timezone in the browser.
19 | }
20 | \keyword{internal}
21 |
--------------------------------------------------------------------------------
/man/get_unique_labels.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/utils.R
3 | \name{get_unique_labels}
4 | \alias{get_unique_labels}
5 | \title{Get unique labels}
6 | \usage{
7 | get_unique_labels(labels)
8 | }
9 | \arguments{
10 | \item{labels}{(\code{character}) vector of labels}
11 | }
12 | \value{
13 | (\code{character}) vector of unique labels
14 | }
15 | \description{
16 | Get unique labels for the modules to avoid namespace conflicts.
17 | }
18 | \keyword{internal}
19 |
--------------------------------------------------------------------------------
/man/include_css_files.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/include_css_js.R
3 | \name{include_css_files}
4 | \alias{include_css_files}
5 | \title{Include \code{CSS} files from \verb{/inst/css/} package directory to application header}
6 | \usage{
7 | include_css_files(pattern = "*")
8 | }
9 | \arguments{
10 | \item{pattern}{(\code{character}) pattern of files to be included}
11 | }
12 | \value{
13 | HTML code that includes \code{CSS} files.
14 | }
15 | \description{
16 | \code{system.file} should not be used to access files in other packages, it does
17 | not work with \code{devtools}. Therefore, we redefine this method in each package
18 | as needed. Thus, we do not export this method.
19 | }
20 | \keyword{internal}
21 |
--------------------------------------------------------------------------------
/man/include_js_files.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/include_css_js.R
3 | \name{include_js_files}
4 | \alias{include_js_files}
5 | \title{Include \code{JS} files from \verb{/inst/js/} package directory to application header}
6 | \usage{
7 | include_js_files(pattern = NULL, except = NULL)
8 | }
9 | \arguments{
10 | \item{pattern}{(\code{character}) pattern of files to be included, passed to \code{system.file}}
11 |
12 | \item{except}{(\code{character}) vector of basename filenames to be excluded}
13 | }
14 | \value{
15 | HTML code that includes \code{JS} files.
16 | }
17 | \description{
18 | \code{system.file} should not be used to access files in other packages, it does
19 | not work with \code{devtools}. Therefore, we redefine this method in each package
20 | as needed. Thus, we do not export this method
21 | }
22 | \keyword{internal}
23 |
--------------------------------------------------------------------------------
/man/include_teal_css_js.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/include_css_js.R
3 | \name{include_teal_css_js}
4 | \alias{include_teal_css_js}
5 | \title{Code to include \code{teal} \code{CSS} and \code{JavaScript} files}
6 | \usage{
7 | include_teal_css_js()
8 | }
9 | \value{
10 | A \code{shiny.tag.list}.
11 | }
12 | \description{
13 | This is useful when you want to use the same \code{JavaScript} and \code{CSS} files that are
14 | used with the \code{teal} application.
15 | This is also useful for running standalone modules in \code{teal} with the correct
16 | styles.
17 | Also initializes \code{shinyjs} so you can use it.
18 | }
19 | \details{
20 | Simply add \code{include_teal_css_js()} as one of the UI elements.
21 | }
22 | \keyword{internal}
23 |
--------------------------------------------------------------------------------
/man/is_arg_used.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/modules.R
3 | \name{is_arg_used}
4 | \alias{is_arg_used}
5 | \title{Does the object make use of the \code{arg}}
6 | \usage{
7 | is_arg_used(modules, arg)
8 | }
9 | \arguments{
10 | \item{modules}{(\code{teal_module} or \code{teal_modules}) object}
11 |
12 | \item{arg}{(\code{character(1)}) names of the arguments to be checked against formals of \code{teal} modules.}
13 | }
14 | \value{
15 | \code{logical} whether the object makes use of \code{arg}.
16 | }
17 | \description{
18 | Does the object make use of the \code{arg}
19 | }
20 | \keyword{internal}
21 |
--------------------------------------------------------------------------------
/man/landing_popup_module.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/landing_popup_module.R
3 | \name{landing_popup_module}
4 | \alias{landing_popup_module}
5 | \title{Landing popup module}
6 | \usage{
7 | landing_popup_module(
8 | label = "Landing Popup",
9 | title = NULL,
10 | content = NULL,
11 | buttons = modalButton("Accept")
12 | )
13 | }
14 | \arguments{
15 | \item{label}{(\code{character(1)}) Label of the module.}
16 |
17 | \item{title}{(\code{character(1)}) Text to be displayed as popup title.}
18 |
19 | \item{content}{(\code{character(1)}, \code{shiny.tag} or \code{shiny.tag.list}) with the content of the popup.
20 | Passed to \code{...} of \code{shiny::modalDialog}. See examples.}
21 |
22 | \item{buttons}{(\code{shiny.tag} or \code{shiny.tag.list}) Typically a \code{modalButton} or \code{actionButton}. See examples.}
23 | }
24 | \value{
25 | A \code{teal_module} (extended with \code{teal_landing_module} class) to be used in \code{teal} applications.
26 | }
27 | \description{
28 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} Creates a landing welcome popup for \code{teal} applications.
29 |
30 | This module is used to display a popup dialog when the application starts.
31 | The dialog blocks access to the application and must be closed with a button before the application can be viewed.
32 | This function is deprecated, please use \code{add_landing_modal()} on the teal app object instead.
33 | }
34 |
--------------------------------------------------------------------------------
/man/make_teal_transform_server.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/teal_transform_module.R
3 | \name{make_teal_transform_server}
4 | \alias{make_teal_transform_server}
5 | \title{Make teal_transform_module's server}
6 | \usage{
7 | make_teal_transform_server(expr)
8 | }
9 | \arguments{
10 | \item{expr}{(\code{language})
11 | An R call which will be evaluated within \code{\link[teal.data:teal_data]{teal.data::teal_data}} environment.}
12 | }
13 | \value{
14 | \verb{function(id, data)} returning \code{shiny} module
15 | }
16 | \description{
17 | A factory function to simplify creation of a \code{\link{teal_transform_module}}'s server. Specified \code{expr}
18 | is wrapped in a shiny module function and output can be passed to the \code{server} argument in
19 | \code{\link[=teal_transform_module]{teal_transform_module()}} call. Such a server function can be linked with ui and values from the
20 | inputs can be used in the expression. Object names specified in the expression will be substituted
21 | with the value of the respective input (matched by the name) - for example in
22 | \code{expression(graph <- graph + ggtitle(title))} object \code{title} will be replaced with the value of
23 | \code{input$title}.
24 | }
25 | \examples{
26 |
27 | trim_iris <- teal_transform_module(
28 | label = "Simplified interactive transformator for iris",
29 | datanames = "iris",
30 | ui = function(id) {
31 | ns <- NS(id)
32 | numericInput(ns("n_rows"), "Subset n rows", value = 6, min = 1, max = 150, step = 1)
33 | },
34 | server = make_teal_transform_server(expression(iris <- head(iris, n_rows)))
35 | )
36 |
37 | app <- init(
38 | data = teal_data(iris = iris),
39 | modules = example_module(transformators = trim_iris)
40 | )
41 | if (interactive()) {
42 | shinyApp(app$ui, app$server)
43 | }
44 |
45 | }
46 | \section{Examples in Shinylive}{
47 | \describe{
48 | \item{example-1}{
49 | \href{https://shinylive.io/r/app/#code=NobwRAdghgtgpmAXGKAHVA6ASmANGAYwHsIAXOMpMAGwEsAjAJykYE8AKcqagSgB0ItMnGYFStAG5wABAB4AtNIBmAVwhjaJdj2kAVLAFUAogNNlGtGAH1aFgM5zFXaldLMIdpUUbWYRACYq1HDsAtLS1FD0cNTSALzSfGAAypaodEq0cP7SQuSi4lLSblAeXj5QpN7K1ba0dkm4YdL+laWwcA4JSXUNeM0qtPHKahpatP46IM3hHo7SAHLJ7BP8EOGzKvAWBACSEKgqpOweoZBWjEQA7n08uIkpKvR2cKTS65c3jdIS3CoyCQAbPcYEJhgBGEFQAAeEIArAAGe52cioCFrcIAXya62kL0YUkYwxgUAA1nBXHBuK53J5vNZ8YT2HBoahGJ07JoICt7PMABZU-w8+r3CAXa52HhSgRrARoNEKXKCY7NVqkKDDZxWNVQYVdXL2O7NPyBYL6lmwdIUk1BEIlMr0yrefVuSw2Q0ygS0JTSFbCAqSEJS6TTXF2PlCVgAQXQ7HlABJBvcE4yRGtMQIwJiALpAA}{Open in Shinylive}
50 | \if{html}{\out{}}
51 | \if{html}{\out{}}
52 | }
53 | }
54 | }
55 |
56 |
--------------------------------------------------------------------------------
/man/module_bookmark_manager.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/module_bookmark_manager.R
3 | \name{module_bookmark_manager}
4 | \alias{module_bookmark_manager}
5 | \alias{bookmark}
6 | \alias{bookmark_manager}
7 | \alias{bookmark_manager_module}
8 | \alias{ui_bookmark_panel}
9 | \alias{srv_bookmark_panel}
10 | \alias{get_bookmarking_option}
11 | \alias{need_bookmarking}
12 | \title{App state management.}
13 | \usage{
14 | ui_bookmark_panel(id, modules)
15 |
16 | srv_bookmark_panel(id, modules)
17 |
18 | get_bookmarking_option()
19 |
20 | need_bookmarking(modules)
21 | }
22 | \arguments{
23 | \item{id}{(\code{character(1)}) \code{shiny} module instance id.}
24 |
25 | \item{modules}{(\code{teal_modules})
26 | \code{teal_modules} object. These are the specific output modules which
27 | will be displayed in the \code{teal} application. See \code{\link[=modules]{modules()}} and \code{\link[=module]{module()}} for
28 | more details.}
29 | }
30 | \value{
31 | Invisible \code{NULL}.
32 | }
33 | \description{
34 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#experimental}{\figure{lifecycle-experimental.svg}{options: alt='[Experimental]'}}}{\strong{[Experimental]}}
35 |
36 | Capture and restore the global (app) input state.
37 | }
38 | \details{
39 | This module introduces bookmarks into \code{teal} apps: the \code{shiny} bookmarking mechanism becomes enabled
40 | and server-side bookmarks can be created.
41 |
42 | The bookmark manager presents a button with the bookmark icon and is placed in the tab-bar.
43 | When clicked, the button creates a bookmark and opens a modal which displays the bookmark URL.
44 |
45 | \code{teal} does not guarantee that all modules (\code{teal_module} objects) are bookmarkable.
46 | Those that are, have a \code{teal_bookmarkable} attribute set to \code{TRUE}. If any modules are not bookmarkable,
47 | the bookmark manager modal displays a warning and the bookmark button displays a flag.
48 | In order to communicate that a external module is bookmarkable, the module developer
49 | should set the \code{teal_bookmarkable} attribute to \code{TRUE}.
50 | }
51 | \section{Server logic}{
52 |
53 | A bookmark is a URL that contains the app address with a \verb{/?_state_id_=} suffix.
54 | \verb{} is a directory created on the server, where the state of the application is saved.
55 | Accessing the bookmark URL opens a new session of the app that starts in the previously saved state.
56 | }
57 |
58 | \section{Note}{
59 |
60 | To enable bookmarking use either:
61 | \itemize{
62 | \item \code{shiny} app by using \code{shinyApp(..., enableBookmarking = "server")} (not supported in \code{shinytest2})
63 | \item set \code{options(shiny.bookmarkStore = "server")} before running the app
64 | }
65 | }
66 |
67 | \keyword{internal}
68 |
--------------------------------------------------------------------------------
/man/module_data_summary.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/module_data_summary.R
3 | \name{module_data_summary}
4 | \alias{module_data_summary}
5 | \alias{ui_data_summary}
6 | \alias{srv_data_summary}
7 | \alias{get_filter_overview_wrapper}
8 | \alias{get_filter_overview}
9 | \alias{get_filter_overview_array}
10 | \alias{get_filter_overview_MultiAssayExperiment}
11 | \title{Data summary}
12 | \usage{
13 | ui_data_summary(id)
14 |
15 | srv_data_summary(id, data)
16 |
17 | get_filter_overview_wrapper(teal_data)
18 |
19 | get_filter_overview(current_data, initial_data, dataname, subject_keys)
20 |
21 | get_filter_overview_array(current_data, initial_data, dataname, subject_keys)
22 |
23 | get_filter_overview_MultiAssayExperiment(current_data, initial_data, dataname)
24 | }
25 | \arguments{
26 | \item{id}{(\code{character(1)}) \code{shiny} module instance id.}
27 |
28 | \item{data}{(\code{reactive} returning \code{teal_data})}
29 |
30 | \item{current_data}{(\code{object}) current object (after filtering and transforming).}
31 |
32 | \item{initial_data}{(\code{object}) initial object.}
33 |
34 | \item{dataname}{(\code{character(1)})}
35 |
36 | \item{subject_keys}{(\code{character}) names of the columns which determine a single unique subjects}
37 | }
38 | \value{
39 | \code{NULL}.
40 | }
41 | \description{
42 | Module and its utils to display the number of rows and subjects in the filtered and unfiltered data.
43 | }
44 | \details{
45 | Handling different data classes:
46 | \code{get_filter_overview()} is a pseudo S3 method which has variants for:
47 | \itemize{
48 | \item \code{array} (\code{data.frame}, \code{DataFrame}, \code{array}, \code{Matrix} and \code{SummarizedExperiment}): Method variant
49 | can be applied to any two-dimensional objects on which \code{\link[=ncol]{ncol()}} can be used.
50 | \item \code{MultiAssayExperiment}: for which summary contains counts for \code{colData} and all \code{experiments}.
51 | \item For other data types module displays data name with warning icon and no more details.
52 | }
53 |
54 | Module includes also "Show/Hide unsupported" button to toggle rows of the summary table
55 | containing datasets where number of observations are not calculated.
56 | }
57 | \keyword{internal}
58 |
--------------------------------------------------------------------------------
/man/module_filter_data.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/module_filter_data.R
3 | \name{module_filter_data}
4 | \alias{module_filter_data}
5 | \alias{ui_filter_data}
6 | \alias{srv_filter_data}
7 | \alias{.make_filtered_teal_data}
8 | \alias{.observe_active_filter_changed}
9 | \alias{.get_filter_expr}
10 | \title{Filter panel module in teal}
11 | \usage{
12 | ui_filter_data(id)
13 |
14 | srv_filter_data(id, datasets, active_datanames, data, is_active)
15 |
16 | .make_filtered_teal_data(modules, data, datasets = NULL, datanames)
17 |
18 | .observe_active_filter_changed(datasets, is_active, active_datanames, data)
19 |
20 | .get_filter_expr(datasets, datanames)
21 | }
22 | \arguments{
23 | \item{id}{(\code{character(1)}) \code{shiny} module instance id.}
24 |
25 | \item{datasets}{(\code{reactive} returning \code{FilteredData} or \code{NULL})
26 | When \code{datasets} is passed from the parent module (\code{srv_teal}) then \code{dataset} is a singleton
27 | which implies in filter-panel to be "global". When \code{NULL} then filter-panel is "module-specific".}
28 |
29 | \item{active_datanames}{(\code{reactive} returning \code{character}) this module's data names}
30 |
31 | \item{data}{(\code{reactive} returning \code{teal_data})}
32 |
33 | \item{modules}{(\code{teal_modules})
34 | \code{teal_modules} object. These are the specific output modules which
35 | will be displayed in the \code{teal} application. See \code{\link[=modules]{modules()}} and \code{\link[=module]{module()}} for
36 | more details.}
37 | }
38 | \value{
39 | A \code{eventReactive} containing \code{teal_data} containing filtered objects and filter code.
40 | \code{eventReactive} triggers only if all conditions are met:
41 | \itemize{
42 | \item tab is selected (\code{is_active})
43 | \item when filters are changed (\code{get_filter_expr} is different than previous)
44 | }
45 | }
46 | \description{
47 | Creates filter panel module from \code{teal_data} object and returns \code{teal_data}. It is build in a way
48 | that filter panel changes and anything what happens before (e.g. \code{\link{module_init_data}}) is triggering
49 | further reactive events only if something has changed and if the module is visible. Thanks to
50 | this special implementation all modules' data are recalculated only for those modules which are
51 | currently displayed.
52 | }
53 | \keyword{internal}
54 |
--------------------------------------------------------------------------------
/man/module_filter_manager.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/module_filter_manager.R
3 | \docType{class}
4 | \encoding{UTF-8}
5 | \name{module_filter_manager}
6 | \alias{module_filter_manager}
7 | \alias{ui_filter_manager_panel}
8 | \alias{srv_filter_manager_panel}
9 | \alias{ui_filter_manager}
10 | \alias{srv_filter_manager}
11 | \alias{srv_module_filter_manager}
12 | \alias{.slicesGlobal-class}
13 | \alias{.slicesGlobal}
14 | \title{Manage multiple \code{FilteredData} objects}
15 | \usage{
16 | ui_filter_manager_panel(id)
17 |
18 | srv_filter_manager_panel(id, slices_global)
19 |
20 | ui_filter_manager(id)
21 |
22 | srv_filter_manager(id, slices_global)
23 |
24 | srv_module_filter_manager(id, module_fd, slices_global)
25 | }
26 | \arguments{
27 | \item{id}{(\code{character(1)})
28 | \code{shiny} module instance id.}
29 |
30 | \item{slices_global}{(\code{reactiveVal})
31 | containing \code{teal_slices}.}
32 |
33 | \item{module_fd}{(\code{FilteredData})
34 | Object containing the data to be filtered in a single \code{teal} module.}
35 | }
36 | \value{
37 | Module returns a \code{slices_global} (\code{reactiveVal}) containing a \code{teal_slices} object with mapping.
38 | }
39 | \description{
40 | Oversee filter states across the entire application.
41 | }
42 |
43 | \section{Slices global}{
44 |
45 | The key role in maintaining the module-specific filter states is played by the \code{.slicesGlobal}
46 | object. It is a reference class that holds the following fields:
47 | \itemize{
48 | \item \code{all_slices} (\code{reactiveVal}) - reactive value containing all filters registered in an app.
49 | \item \code{module_slices_api} (\code{reactiveValues}) - reactive field containing references to each modules'
50 | \code{FilteredData} object methods. At this moment it is used only in \code{srv_filter_manager} to display
51 | the filter states in a table combining informations from \code{all_slices} and from
52 | \code{FilteredData$get_available_teal_slices()}.
53 | }
54 |
55 | During a session only new filters are added to \code{all_slices} unless \code{\link{module_snapshot_manager}} is
56 | used to restore previous state. Filters from \code{all_slices} can be activated or deactivated in a
57 | module which is linked (both ways) by \code{attr(, "mapping")} so that:
58 | \itemize{
59 | \item If module's filter is added or removed in its \code{FilteredData} object, this information is passed
60 | to \code{SlicesGlobal} which updates \code{attr(, "mapping")} accordingly.
61 | \item When mapping changes in a \code{SlicesGlobal}, filters are set or removed from module's
62 | \code{FilteredData}.
63 | }
64 | }
65 |
66 | \section{Filter manager}{
67 |
68 | Filter-manager is split into two parts:
69 | \enumerate{
70 | \item \code{ui/srv_filter_manager_panel} - Called once for the whole app. This module observes changes in
71 | the filters in \code{slices_global} and displays them in a table utilizing information from \code{mapping}:
72 | }
73 | \itemize{
74 | \item (\code{TRUE}) - filter is active in the module
75 | \item (\code{FALSE}) - filter is inactive in the module
76 | \item (\code{NA}) - filter is not available in the module
77 | }
78 | \enumerate{
79 | \item \code{ui/srv_module_filter_manager} - Called once for each \code{teal_module}. Handling filter states
80 | for of single module and keeping module \code{FilteredData} consistent with \code{slices_global}, so that
81 | local filters are always reflected in the \code{slices_global} and its mapping and vice versa.
82 | }
83 | }
84 |
85 | \keyword{internal}
86 |
--------------------------------------------------------------------------------
/man/module_init_data.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/module_init_data.R
3 | \name{module_init_data}
4 | \alias{module_init_data}
5 | \alias{ui_init_data}
6 | \alias{srv_init_data}
7 | \title{Data Module for teal}
8 | \usage{
9 | ui_init_data(id)
10 |
11 | srv_init_data(id, data)
12 | }
13 | \arguments{
14 | \item{id}{(\code{character(1)}) \code{shiny} module instance id.}
15 |
16 | \item{data}{(\code{teal_data}, \code{teal_data_module}, or \code{reactive} returning \code{teal_data})
17 | The data which application will depend on.}
18 | }
19 | \value{
20 | A \code{reactive} object that returns:
21 | Output of the \code{data}. If \code{data} fails then returned error is handled (after \code{\link[=tryCatch]{tryCatch()}}) so that
22 | rest of the application can respond to this respectively.
23 | }
24 | \description{
25 | This module manages the \code{data} argument for \code{srv_teal}. The \code{teal} framework uses \code{\link[teal.data:teal_data]{teal.data::teal_data()}},
26 | which can be provided in various ways:
27 | \enumerate{
28 | \item Directly as a \code{\link[teal.data:teal_data]{teal.data::teal_data()}} object. This will automatically convert it into a \code{reactive} \code{teal_data}.
29 | \item As a \code{reactive} object that returns a \code{\link[teal.data:teal_data]{teal.data::teal_data()}} object.
30 | }
31 | }
32 | \details{
33 | \subsection{Reactive \code{teal_data}:}{
34 |
35 | The data in the application can be reactively updated, prompting \code{\link[=srv_teal]{srv_teal()}} to rebuild the
36 | content accordingly. There are two methods for creating interactive \code{teal_data}:
37 | \enumerate{
38 | \item Using a \code{reactive} object provided from outside the \code{teal} application. In this scenario,
39 | reactivity is controlled by an external module, and \code{srv_teal} responds to changes.
40 | \item Using \code{\link[=teal_data_module]{teal_data_module()}}, which is embedded within the \code{teal} application, allowing data to
41 | be resubmitted by the user as needed.
42 | }
43 |
44 | Since the server of \code{\link[=teal_data_module]{teal_data_module()}} must return a \code{reactive} \code{teal_data} object, both
45 | methods (1 and 2) produce the same reactive behavior within a \code{teal} application. The distinction
46 | lies in data control: the first method involves external control, while the second method
47 | involves control from a custom module within the app.
48 |
49 | For more details, see \code{\link{module_teal_data}}.
50 | }
51 | }
52 | \keyword{internal}
53 |
--------------------------------------------------------------------------------
/man/module_labels.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/modules.R
3 | \name{module_labels}
4 | \alias{module_labels}
5 | \title{Retrieve labels from \code{teal_modules}}
6 | \usage{
7 | module_labels(modules)
8 | }
9 | \arguments{
10 | \item{modules}{(\code{teal_modules})}
11 | }
12 | \value{
13 | A \code{list} containing the labels of the modules. If the modules are nested,
14 | the function returns a nested \code{list} of labels.
15 | }
16 | \description{
17 | Retrieve labels from \code{teal_modules}
18 | }
19 | \keyword{internal}
20 |
--------------------------------------------------------------------------------
/man/module_management.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/modules.R
3 | \name{extract_module}
4 | \alias{extract_module}
5 | \alias{drop_module}
6 | \title{Extract/Remove module(s) of specific class}
7 | \usage{
8 | extract_module(modules, class)
9 |
10 | drop_module(modules, class)
11 | }
12 | \arguments{
13 | \item{modules}{(\code{teal_modules})}
14 |
15 | \item{class}{The class name of \code{teal_module} to be extracted or dropped.}
16 | }
17 | \value{
18 | \itemize{
19 | \item For \code{extract_module}, a \code{teal_module} of class \code{class} or \code{teal_modules} containing modules of class \code{class}.
20 | \item For \code{drop_module}, the opposite, which is all \code{teal_modules} of class other than \code{class}.
21 | }
22 |
23 | \code{teal_modules}
24 | }
25 | \description{
26 | Given a \code{teal_module} or a \code{teal_modules}, return the elements of the structure according to \code{class}.
27 | }
28 | \keyword{internal}
29 |
--------------------------------------------------------------------------------
/man/module_session_info.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/module_session_info.R
3 | \name{module_session_info}
4 | \alias{module_session_info}
5 | \alias{ui_session_info}
6 | \alias{srv_session_info}
7 | \title{\code{teal} user session info module}
8 | \usage{
9 | ui_session_info(id)
10 |
11 | srv_session_info(id)
12 | }
13 | \arguments{
14 | \item{id}{(\code{character(1)}) \code{shiny} module instance id.}
15 | }
16 | \value{
17 | \code{NULL} invisibly
18 | }
19 | \description{
20 | Module to display the user session info popup and to download a lockfile. Module is included
21 | when running \code{\link[=init]{init()}} but skipped when using \code{\link{module_teal}}. Please be aware that session info
22 | contains R session information, so multiple module's calls will share the same information.
23 | }
24 | \examples{
25 | ui <- fluidPage(
26 | ui_session_info("session_info")
27 | )
28 |
29 | server <- function(input, output, session) {
30 | srv_session_info("session_info")
31 | }
32 |
33 | if (interactive()) {
34 | shinyApp(ui, server)
35 | }
36 |
37 | }
38 | \section{Examples in Shinylive}{
39 | \describe{
40 | \item{example-1}{
41 | \href{https://shinylive.io/r/app/#code=NobwRAdghgtgpmAXGKAHVA6ASmANGAYwHsIAXOMpMAGwEsAjAJykYE8AKcqagSgB0ItMnGYFStAG5wABAB4AtNIBmAVwhjaJdj2kAVLAFUAogIEracxUurmAJgAUoAczjsB06eYD6AZzg+fTQgvISUiNzA-AKCQiDC+MH4IJIE-RilGS2U1DS0hVBVSXGkiQoKi6SjAkh0Qd0r0339q4NDwhKqYtoSkgF9TQSVpdiFyUXEpbVr6nwALIVYAQXR2c2K0jL6BMF6AXSA}{Open in Shinylive}
42 | \if{html}{\out{}}
43 | \if{html}{\out{}}
44 | }
45 | }
46 | }
47 |
48 |
--------------------------------------------------------------------------------
/man/module_teal.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/module_teal.R
3 | \name{module_teal}
4 | \alias{module_teal}
5 | \alias{ui_teal}
6 | \alias{srv_teal}
7 | \title{\code{teal} main module}
8 | \usage{
9 | ui_teal(id, modules)
10 |
11 | srv_teal(id, data, modules, filter = teal_slices())
12 | }
13 | \arguments{
14 | \item{id}{(\code{character(1)}) \code{shiny} module instance id.}
15 |
16 | \item{modules}{(\code{teal_modules})
17 | \code{teal_modules} object. These are the specific output modules which
18 | will be displayed in the \code{teal} application. See \code{\link[=modules]{modules()}} and \code{\link[=module]{module()}} for
19 | more details.}
20 |
21 | \item{data}{(\code{teal_data}, \code{teal_data_module}, or \code{reactive} returning \code{teal_data})
22 | The data which application will depend on.}
23 |
24 | \item{filter}{(\code{teal_slices}) Optionally,
25 | specifies the initial filter using \code{\link[=teal_slices]{teal_slices()}}.}
26 | }
27 | \value{
28 | \code{NULL} invisibly
29 | }
30 | \description{
31 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#stable}{\figure{lifecycle-stable.svg}{options: alt='[Stable]'}}}{\strong{[Stable]}}
32 | Module to create a \code{teal} app as a Shiny Module.
33 | }
34 | \details{
35 | This module can be used instead of \code{\link[=init]{init()}} in custom Shiny applications. Unlike \code{\link[=init]{init()}}, it doesn't
36 | automatically include \code{\link{module_session_info}}.
37 |
38 | Module is responsible for creating the main \code{shiny} app layout and initializing all the necessary
39 | components. This module establishes reactive connection between the input \code{data} and every other
40 | component in the app. Reactive change of the \code{data} passed as an argument, reloads the app and
41 | possibly keeps all input settings the same so the user can continue where one left off.
42 | \subsection{data flow in \code{teal} application}{
43 |
44 | This module supports multiple data inputs but eventually, they are all converted to \code{reactive}
45 | returning \code{teal_data} in this module. On this \verb{reactive teal_data} object several actions are
46 | performed:
47 | \itemize{
48 | \item data loading in \code{\link{module_init_data}}
49 | \item data filtering in \code{\link{module_filter_data}}
50 | \item data transformation in \code{\link{module_transform_data}}
51 | }
52 | }
53 |
54 | \subsection{Fallback on failure}{
55 |
56 | \code{teal} is designed in such way that app will never crash if the error is introduced in any
57 | custom \code{shiny} module provided by app developer (e.g. \code{\link[=teal_data_module]{teal_data_module()}}, \code{\link[=teal_transform_module]{teal_transform_module()}}).
58 | If any module returns a failing object, the app will halt the evaluation and display a warning message.
59 | App user should always have a chance to fix the improper input and continue without restarting the session.
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/man/module_teal_data.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/module_teal_data.R
3 | \name{module_teal_data}
4 | \alias{module_teal_data}
5 | \alias{ui_teal_data_module}
6 | \alias{ui_teal_data}
7 | \alias{srv_teal_data_module}
8 | \alias{srv_teal_data}
9 | \alias{ui_validate_reactive_teal_data}
10 | \alias{srv_validate_reactive_teal_data}
11 | \title{Execute and validate \code{teal_data_module}}
12 | \usage{
13 | ui_teal_data_module(id, data_module = function(id) NULL)
14 |
15 | srv_teal_data_module(
16 | id,
17 | data_module = function(id) NULL,
18 | modules = NULL,
19 | validate_shiny_silent_error = TRUE,
20 | is_transform_failed = reactiveValues()
21 | )
22 |
23 | ui_validate_reactive_teal_data(id)
24 |
25 | srv_validate_reactive_teal_data(
26 | id,
27 | data,
28 | modules = NULL,
29 | validate_shiny_silent_error = FALSE,
30 | hide_validation_error = reactive(FALSE)
31 | )
32 | }
33 | \arguments{
34 | \item{id}{(\code{character(1)}) \code{shiny} module instance id.}
35 |
36 | \item{data_module}{(\code{teal_data_module})}
37 |
38 | \item{modules}{(\code{teal_modules} or \code{teal_module}) For \code{datanames} validation purpose}
39 |
40 | \item{validate_shiny_silent_error}{(\code{logical}) If \code{TRUE}, then \code{shiny.silent.error} is validated and}
41 |
42 | \item{is_transform_failed}{(\code{reactiveValues}) contains \code{logical} flags named after each transformator.
43 | Help to determine if any previous transformator failed, so that following transformators can be disabled
44 | and display a generic failure message.}
45 |
46 | \item{data}{(\code{reactive} returning \code{teal_data})}
47 | }
48 | \value{
49 | \code{reactive} \code{teal_data}
50 | }
51 | \description{
52 | This is a low level module to handle \code{teal_data_module} execution and validation.
53 | \code{\link[=teal_transform_module]{teal_transform_module()}} inherits from \code{\link[=teal_data_module]{teal_data_module()}} so it is handled by this module too.
54 | \code{\link[=srv_teal]{srv_teal()}} accepts various \code{data} objects and eventually they are all transformed to \code{reactive}
55 | \code{\link[teal.data:teal_data]{teal.data::teal_data()}} which is a standard data class in whole \code{teal} framework.
56 | }
57 | \note{
58 | \code{ui_teal_data_module} was renamed from \code{ui_teal_data}.
59 |
60 | \code{srv_teal_data_module} was renamed from \code{srv_teal_data}.
61 | }
62 | \section{data validation}{
63 |
64 |
65 | Executed \code{\link[=teal_data_module]{teal_data_module()}} is validated and output is validated for consistency.
66 | Output \code{data} is invalid if:
67 | \enumerate{
68 | \item \code{\link[=teal_data_module]{teal_data_module()}} is invalid if server doesn't return \code{reactive}. \strong{Immediately crashes an app!}
69 | \item \code{reactive} throws a \code{shiny.error} - happens when module creating \code{\link[teal.data:teal_data]{teal.data::teal_data()}} fails.
70 | \item \code{reactive} returns \code{qenv.error} - happens when \code{\link[teal.data:teal_data]{teal.data::teal_data()}} evaluates a failing code.
71 | \item \code{reactive} object doesn't return \code{\link[teal.data:teal_data]{teal.data::teal_data()}}.
72 | \item \code{\link[teal.data:teal_data]{teal.data::teal_data()}} object lacks any \code{datanames} specified in the \code{modules} argument.
73 | }
74 |
75 | \code{teal} (observers in \code{srv_teal}) always waits to render an app until \code{reactive} \code{teal_data} is
76 | returned. If error 2-4 occurs, relevant error message is displayed to the app user. Once the issue is
77 | resolved, the app will continue to run. \code{teal} guarantees that errors in data don't crash the app
78 | (except error 1).
79 | }
80 |
81 | \keyword{internal}
82 |
--------------------------------------------------------------------------------
/man/module_teal_lockfile.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/module_teal_lockfile.R
3 | \name{module_teal_lockfile}
4 | \alias{module_teal_lockfile}
5 | \alias{ui_teal_lockfile}
6 | \alias{srv_teal_lockfile}
7 | \alias{.teal_lockfile_process_invoke}
8 | \alias{.renv_snapshot}
9 | \alias{.is_lockfile_deps_installed}
10 | \alias{.is_disabled_lockfile_scenario}
11 | \title{Generate lockfile for application's environment reproducibility}
12 | \usage{
13 | ui_teal_lockfile(id)
14 |
15 | srv_teal_lockfile(id)
16 |
17 | .teal_lockfile_process_invoke(lockfile_path)
18 |
19 | .renv_snapshot(lockfile_path)
20 |
21 | .is_lockfile_deps_installed()
22 |
23 | .is_disabled_lockfile_scenario()
24 | }
25 | \arguments{
26 | \item{id}{(\code{character(1)}) \code{shiny} module instance id.}
27 |
28 | \item{lockfile_path}{(\code{character}) path to the lockfile.}
29 | }
30 | \value{
31 | \code{NULL}
32 | }
33 | \description{
34 | Generate lockfile for application's environment reproducibility
35 | }
36 | \section{Different ways of creating lockfile}{
37 |
38 | \code{teal} leverages \code{\link[renv:snapshot]{renv::snapshot()}}, which offers multiple methods for lockfile creation.
39 | \itemize{
40 | \item \strong{Working directory lockfile}: \code{teal}, by default, will create an \code{implicit} type lockfile that uses
41 | \code{renv::dependencies()} to detect all R packages in the current project's working directory.
42 | \item \strong{\code{DESCRIPTION}-based lockfile}: To generate a lockfile based on a \code{DESCRIPTION} file in your working
43 | directory, set \code{renv::settings$snapshot.type("explicit")}. The naming convention for \code{type} follows
44 | \code{renv::snapshot()}. For the \code{"explicit"} type, refer to \code{renv::settings$package.dependency.fields()} for the
45 | \code{DESCRIPTION} fields included in the lockfile.
46 | \item \strong{Custom files-based lockfile}: To specify custom files as the basis for the lockfile, set
47 | \code{renv::settings$snapshot.type("custom")} and configure the \code{renv.snapshot.filter} option.
48 | }
49 | }
50 |
51 | \section{lockfile usage}{
52 |
53 | After creating the lockfile, you can restore the application's environment using \code{renv::restore()}.
54 | }
55 |
56 | \seealso{
57 | \code{\link[renv:snapshot]{renv::snapshot()}}, \code{\link[renv:restore]{renv::restore()}}.
58 | }
59 | \keyword{internal}
60 |
--------------------------------------------------------------------------------
/man/module_teal_with_splash.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/module_teal_with_splash.R
3 | \name{module_teal_with_splash}
4 | \alias{module_teal_with_splash}
5 | \alias{ui_teal_with_splash}
6 | \alias{srv_teal_with_splash}
7 | \title{UI and server modules of \code{teal}}
8 | \usage{
9 | ui_teal_with_splash(
10 | id,
11 | data,
12 | modules,
13 | title = build_app_title(),
14 | header = tags$p(),
15 | footer = tags$p()
16 | )
17 |
18 | srv_teal_with_splash(id, data, modules, filter = teal_slices())
19 | }
20 | \arguments{
21 | \item{id}{(\code{character(1)}) \code{shiny} module instance id.}
22 |
23 | \item{data}{(\code{teal_data}, \code{teal_data_module}, or \code{reactive} returning \code{teal_data})
24 | The data which application will depend on.}
25 |
26 | \item{modules}{(\code{teal_modules})
27 | \code{teal_modules} object. These are the specific output modules which
28 | will be displayed in the \code{teal} application. See \code{\link[=modules]{modules()}} and \code{\link[=module]{module()}} for
29 | more details.}
30 |
31 | \item{title}{(\code{shiny.tag} or \code{character(1)}) \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} Optionally,
32 | the browser window title. Defaults to a title "teal app" with the icon of NEST.
33 | Can be created using the \code{build_app_title()} or
34 | by passing a valid \code{shiny.tag} which is a head tag with title and link tag.
35 | This parameter is no longer supported. Use \code{modify_title()} on the teal app object instead.}
36 |
37 | \item{header}{(\code{shiny.tag} or \code{character(1)}) \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} Optionally,
38 | the header of the app.
39 | This parameter is no longer supported. Use \code{modify_header()} on the teal app object instead.}
40 |
41 | \item{footer}{(\code{shiny.tag} or \code{character(1)}) \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} Optionally,
42 | the footer of the app.
43 | This parameter is no longer supported. Use \code{modify_footer()} on the teal app object instead.}
44 |
45 | \item{filter}{(\code{teal_slices}) Optionally,
46 | specifies the initial filter using \code{\link[=teal_slices]{teal_slices()}}.}
47 | }
48 | \value{
49 | Returns a \code{reactive} expression containing a \code{teal_data} object when data is loaded or \code{NULL} when it is not.
50 | }
51 | \description{
52 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}}
53 | Please use \code{\link{module_teal}} instead.
54 | }
55 |
--------------------------------------------------------------------------------
/man/module_transform_data.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/module_transform_data.R
3 | \name{module_transform_data}
4 | \alias{module_transform_data}
5 | \alias{ui_transform_teal_data}
6 | \alias{srv_transform_teal_data}
7 | \title{Module to transform \code{reactive} \code{teal_data}}
8 | \usage{
9 | ui_transform_teal_data(id, transformators, class = "well")
10 |
11 | srv_transform_teal_data(
12 | id,
13 | data,
14 | transformators,
15 | modules = NULL,
16 | is_transform_failed = reactiveValues()
17 | )
18 | }
19 | \arguments{
20 | \item{id}{(\code{character(1)}) \code{shiny} module instance id.}
21 |
22 | \item{transformators}{(\code{list} of \code{teal_transform_module}) that will be applied to transform module's data input.
23 | To learn more check \code{vignette("transform-input-data", package = "teal")}.}
24 |
25 | \item{class}{(character(1)) CSS class to be added in the \code{div} wrapper tag.}
26 |
27 | \item{data}{(\code{reactive} returning \code{teal_data})}
28 |
29 | \item{modules}{(\code{teal_modules} or \code{teal_module}) For \code{datanames} validation purpose}
30 |
31 | \item{is_transform_failed}{(\code{reactiveValues}) contains \code{logical} flags named after each transformator.
32 | Help to determine if any previous transformator failed, so that following transformators can be disabled
33 | and display a generic failure message.}
34 | }
35 | \value{
36 | \code{reactive} \code{teal_data}
37 | }
38 | \description{
39 | Module calls \code{\link[=teal_transform_module]{teal_transform_module()}} in sequence so that \verb{reactive teal_data} output
40 | from one module is handed over to the following module's input.
41 | }
42 |
--------------------------------------------------------------------------------
/man/modules_bookmarkable.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/modules.R
3 | \name{modules_bookmarkable}
4 | \alias{modules_bookmarkable}
5 | \title{Retrieve \code{teal_bookmarkable} attribute from \code{teal_modules}}
6 | \usage{
7 | modules_bookmarkable(modules)
8 | }
9 | \arguments{
10 | \item{modules}{(\code{teal_modules} or \code{teal_module}) object}
11 | }
12 | \value{
13 | named list of the same structure as \code{modules} with \code{TRUE} or \code{FALSE} values indicating
14 | whether the module is bookmarkable.
15 | }
16 | \description{
17 | Retrieve \code{teal_bookmarkable} attribute from \code{teal_modules}
18 | }
19 | \keyword{internal}
20 |
--------------------------------------------------------------------------------
/man/modules_depth.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/modules.R
3 | \name{modules_depth}
4 | \alias{modules_depth}
5 | \title{Get module depth}
6 | \usage{
7 | modules_depth(modules, depth = 0L)
8 | }
9 | \arguments{
10 | \item{modules}{(\code{list} or \code{teal_modules} or \code{teal_module})
11 | Nested list of \code{teal_modules} or \code{teal_module} objects or a single
12 | \code{teal_modules} or \code{teal_module} object. These are the specific output modules which
13 | will be displayed in the \code{teal} application. See \code{\link[=modules]{modules()}} and \code{\link[=module]{module()}} for
14 | more details.}
15 |
16 | \item{depth}{optional integer determining current depth level}
17 | }
18 | \value{
19 | Depth level for given module.
20 | }
21 | \description{
22 | Depth starts at 0, so a single \code{teal.module} has depth 0.
23 | Nesting it increases overall depth by 1.
24 | }
25 | \keyword{internal}
26 |
--------------------------------------------------------------------------------
/man/pluralize.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/utils.R
3 | \name{pluralize}
4 | \alias{pluralize}
5 | \title{Pluralize a word depending on the size of the input}
6 | \usage{
7 | pluralize(x, singular, plural = NULL)
8 | }
9 | \arguments{
10 | \item{x}{(\code{object}) to check length for plural.}
11 |
12 | \item{singular}{(\code{character}) singular form of the word.}
13 |
14 | \item{plural}{(optional \code{character}) plural form of the word. If not given an "s"
15 | is added to the singular form.}
16 | }
17 | \value{
18 | A \code{character} that correctly represents the size of the \code{x} argument.
19 | }
20 | \description{
21 | Pluralize a word depending on the size of the input
22 | }
23 | \keyword{internal}
24 |
--------------------------------------------------------------------------------
/man/report_card_template.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/utils.R
3 | \name{report_card_template}
4 | \alias{report_card_template}
5 | \title{Template function for \code{TealReportCard} creation and customization}
6 | \usage{
7 | report_card_template(
8 | title,
9 | label,
10 | description = NULL,
11 | with_filter,
12 | filter_panel_api
13 | )
14 | }
15 | \arguments{
16 | \item{title}{(\code{character(1)}) title of the card (unless overwritten by label)}
17 |
18 | \item{label}{(\code{character(1)}) label provided by the user when adding the card}
19 |
20 | \item{description}{(\code{character(1)}) optional, additional description}
21 |
22 | \item{with_filter}{(\code{logical(1)}) flag indicating to add filter state}
23 |
24 | \item{filter_panel_api}{(\code{FilterPanelAPI}) object with API that allows the generation
25 | of the filter state in the report}
26 | }
27 | \value{
28 | (\code{TealReportCard}) populated with a title, description and filter state.
29 | }
30 | \description{
31 | This function generates a report card with a title,
32 | an optional description, and the option to append the filter state list.
33 | }
34 |
--------------------------------------------------------------------------------
/man/reporter_previewer_module.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/reporter_previewer_module.R
3 | \name{reporter_previewer_module}
4 | \alias{reporter_previewer_module}
5 | \title{Create a \code{teal} module for previewing a report}
6 | \usage{
7 | reporter_previewer_module(label = "Report previewer", server_args = list())
8 | }
9 | \arguments{
10 | \item{label}{(\code{character(1)}) Label shown in the navigation item for the module or module group.
11 | For \code{modules()} defaults to \code{"root"}. See \code{Details}.}
12 |
13 | \item{server_args}{(named \code{list})
14 | Arguments passed to \code{\link[teal.reporter:reporter_previewer]{teal.reporter::reporter_previewer_srv()}}.}
15 | }
16 | \value{
17 | \code{teal_module} (extended with \code{teal_module_previewer} class) containing the \code{teal.reporter} previewer functionality.
18 | }
19 | \description{
20 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#experimental}{\figure{lifecycle-experimental.svg}{options: alt='[Experimental]'}}}{\strong{[Experimental]}}
21 |
22 | This function wraps \code{\link[teal.reporter:reporter_previewer]{teal.reporter::reporter_previewer_ui()}} and
23 | \code{\link[teal.reporter:reporter_previewer]{teal.reporter::reporter_previewer_srv()}} into a \code{teal_module} to be
24 | used in \code{teal} applications.
25 |
26 | If you are creating a \code{teal} application using \code{\link[=init]{init()}} then this
27 | module will be added to your application automatically if any of your \code{teal_modules}
28 | support report generation.
29 | }
30 |
--------------------------------------------------------------------------------
/man/restoreValue.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/module_bookmark_manager.R
3 | \name{restoreValue}
4 | \alias{restoreValue}
5 | \title{Restore value from bookmark.}
6 | \usage{
7 | restoreValue(value, default)
8 | }
9 | \arguments{
10 | \item{value}{(\code{character(1)}) name of value to restore}
11 |
12 | \item{default}{fallback value}
13 | }
14 | \value{
15 | In an application restored from a server-side bookmark,
16 | the variable specified by \code{value} from the \code{values} environment.
17 | Otherwise \code{default}.
18 | }
19 | \description{
20 | Get value from bookmark or return default.
21 | }
22 | \details{
23 | Bookmarks can store not only inputs but also arbitrary values.
24 | These values are stored by \code{onBookmark} callbacks and restored by \code{onBookmarked} callbacks,
25 | and they are placed in the \code{values} environment in the \code{session$restoreContext} field.
26 | Using \code{teal_data_module} makes it impossible to run the callbacks
27 | because the app becomes ready before modules execute and callbacks are registered.
28 | In those cases the stored values can still be recovered from the \code{session} object directly.
29 |
30 | Note that variable names in the \code{values} environment are prefixed with module name space names,
31 | therefore, when using this function in modules, \code{value} must be run through the name space function.
32 | }
33 | \keyword{internal}
34 |
--------------------------------------------------------------------------------
/man/run_js_files.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/include_css_js.R
3 | \name{run_js_files}
4 | \alias{run_js_files}
5 | \title{Run \code{JS} file from \verb{/inst/js/} package directory}
6 | \usage{
7 | run_js_files(files)
8 | }
9 | \arguments{
10 | \item{files}{(\code{character}) vector of filenames.}
11 | }
12 | \value{
13 | \code{NULL}, invisibly.
14 | }
15 | \description{
16 | This is triggered from the server to execute on the client
17 | rather than triggered directly on the client.
18 | Unlike \code{include_js_files} which includes \code{JavaScript} functions,
19 | the \code{run_js} actually executes \code{JavaScript} functions.
20 | }
21 | \details{
22 | \code{system.file} should not be used to access files in other packages, it does
23 | not work with \code{devtools}. Therefore, we redefine this method in each package
24 | as needed. Thus, we do not export this method.
25 | }
26 | \keyword{internal}
27 |
--------------------------------------------------------------------------------
/man/show_rcode_modal.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/show_rcode_modal.R
3 | \name{show_rcode_modal}
4 | \alias{show_rcode_modal}
5 | \title{Show \code{R} code modal}
6 | \usage{
7 | show_rcode_modal(title = NULL, rcode, session = getDefaultReactiveDomain())
8 | }
9 | \arguments{
10 | \item{title}{(\code{character(1)})
11 | Title of the modal, displayed in the first comment of the \code{R} code.}
12 |
13 | \item{rcode}{(\code{character})
14 | vector with \code{R} code to show inside the modal.}
15 |
16 | \item{session}{(\code{ShinySession}) optional
17 | \code{shiny} session object, defaults to \code{\link[shiny:domains]{shiny::getDefaultReactiveDomain()}}.}
18 | }
19 | \description{
20 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}}
21 |
22 | Use the \code{\link[shiny:showModal]{shiny::showModal()}} function to show the \code{R} code inside.
23 | }
24 | \references{
25 | \code{\link[shiny:showModal]{shiny::showModal()}}
26 | }
27 |
--------------------------------------------------------------------------------
/man/slices_store.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/teal_slices-store.R
3 | \name{slices_store}
4 | \alias{slices_store}
5 | \alias{slices_restore}
6 | \title{Store and restore \code{teal_slices} object}
7 | \usage{
8 | slices_store(tss, file)
9 |
10 | slices_restore(file)
11 | }
12 | \arguments{
13 | \item{tss}{(\code{teal_slices}) object to be stored.}
14 |
15 | \item{file}{(\code{character(1)}) file path where \code{teal_slices} object will be
16 | saved and restored. The file extension should be \code{".json"}.}
17 | }
18 | \value{
19 | \code{slices_store} returns \code{NULL}, invisibly.
20 |
21 | \code{slices_restore} returns a \code{teal_slices} object restored from the file.
22 | }
23 | \description{
24 | Functions that write a \code{teal_slices} object to a file in the \code{JSON} format,
25 | and also restore the object from disk.
26 | }
27 | \details{
28 | Date and date time objects are stored in the following formats:
29 | \itemize{
30 | \item \code{Date} class is converted to the \code{"ISO8601"} standard (\code{YYYY-MM-DD}).
31 | \item \code{POSIX*t} classes are converted to character by using
32 | \code{format.POSIX*t(usetz = TRUE, tz = "UTC")} (\verb{YYYY-MM-DD HH:MM:SS UTC}, where
33 | \code{UTC} is the \verb{Coordinated Universal Time} timezone short-code).
34 | }
35 |
36 | This format is assumed during \code{slices_restore}. All \code{POSIX*t} objects in
37 | \code{selected} or \code{choices} fields of \code{teal_slice} objects are always printed in
38 | \code{UTC} timezone as well.
39 | }
40 | \seealso{
41 | \code{\link[=teal_slices]{teal_slices()}}
42 | }
43 | \keyword{internal}
44 |
--------------------------------------------------------------------------------
/man/tdata.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/tdata.R
3 | \name{tdata}
4 | \alias{tdata}
5 | \alias{new_tdata}
6 | \alias{tdata2env}
7 | \alias{get_code_tdata}
8 | \alias{join_keys.tdata}
9 | \alias{get_metadata}
10 | \alias{as_tdata}
11 | \title{Create a \code{tdata} object}
12 | \usage{
13 | new_tdata(...)
14 |
15 | tdata2env(...)
16 |
17 | get_code_tdata(...)
18 |
19 | \method{join_keys}{tdata}(...)
20 |
21 | get_metadata(...)
22 |
23 | as_tdata(...)
24 | }
25 | \arguments{
26 | \item{...}{ignored}
27 | }
28 | \value{
29 | nothing
30 | }
31 | \description{
32 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#superseded}{\figure{lifecycle-superseded.svg}{options: alt='[Superseded]'}}}{\strong{[Superseded]}}
33 |
34 | Recent changes in \code{teal} cause modules to fail because modules expect a \code{tdata} object
35 | to be passed to the \code{data} argument but instead they receive a \code{teal_data} object,
36 | which is additionally wrapped in a reactive expression in the server functions.
37 | In order to easily adapt such modules without a proper refactor,
38 | use this function to downgrade the \code{data} argument.
39 | }
40 |
--------------------------------------------------------------------------------
/man/teal-package.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/teal.R
3 | \docType{package}
4 | \name{teal-package}
5 | \alias{teal}
6 | \alias{teal-package}
7 | \title{\code{teal}: Interactive exploration of clinical trials data}
8 | \description{
9 | The \code{teal} package provides a \code{shiny} based framework for creating an
10 | interactive data analysis environment.
11 | }
12 | \details{
13 | To learn mode about the package, visit the \href{https://insightsengineering.github.io/teal/latest-tag/}{project website}
14 | or read the \code{\link[=init]{init()}} manual page.
15 | }
16 | \seealso{
17 | Useful links:
18 | \itemize{
19 | \item \url{https://insightsengineering.github.io/teal/}
20 | \item \url{https://github.com/insightsengineering/teal/}
21 | \item Report bugs at \url{https://github.com/insightsengineering/teal/issues}
22 | }
23 |
24 | }
25 | \author{
26 | \strong{Maintainer}: Dawid Kaledkowski \email{dawid.kaledkowski@roche.com} (\href{https://orcid.org/0000-0001-9533-457X}{ORCID})
27 |
28 | Authors:
29 | \itemize{
30 | \item Pawel Rucki \email{pawel.rucki@roche.com}
31 | \item Aleksander Chlebowski \email{aleksander.chlebowski@contractors.roche.com} (\href{https://orcid.org/0000-0001-5018-6294}{ORCID})
32 | \item Andre Verissimo \email{andre.verissimo@roche.com} (\href{https://orcid.org/0000-0002-2212-339X}{ORCID})
33 | \item Kartikeya Kirar \email{kartikeya.kirar@businesspartner.roche.com}
34 | \item Vedha Viyash \email{vedha.viyash@roche.com}
35 | \item Marcin Kosinski \email{marcin.kosinski.mk1@roche.com}
36 | \item Adrian Waddell \email{adrian.waddell@gene.com}
37 | \item Nikolas Burkoff
38 | \item Mahmoud Hallal
39 | \item Maciej Nasinski
40 | \item Konrad Pagacz
41 | \item Junlue Zhao
42 | \item Tadeusz Lewandowski
43 | }
44 |
45 | Other contributors:
46 | \itemize{
47 | \item Chendi Liao \email{chendi.liao@roche.com} [reviewer]
48 | \item Dony Unardi \email{unardid@gene.com} [reviewer]
49 | \item F. Hoffmann-La Roche AG [copyright holder, funder]
50 | \item Maximilian Mordig [contributor]
51 | }
52 |
53 | }
54 | \keyword{internal}
55 |
--------------------------------------------------------------------------------
/man/teal_data_to_filtered_data.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/utils.R
3 | \name{teal_data_to_filtered_data}
4 | \alias{teal_data_to_filtered_data}
5 | \title{Create a \code{FilteredData}}
6 | \usage{
7 | teal_data_to_filtered_data(x, datanames = names(x))
8 | }
9 | \arguments{
10 | \item{x}{(\code{teal_data}) object}
11 |
12 | \item{datanames}{(\code{character}) vector of data set names to include; must be subset of \code{names(x)}}
13 | }
14 | \value{
15 | A \code{FilteredData} object.
16 | }
17 | \description{
18 | Create a \code{FilteredData} object from a \code{teal_data} object.
19 | }
20 | \keyword{internal}
21 |
--------------------------------------------------------------------------------
/man/teal_data_utilities.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/teal_data_utils.R
3 | \name{teal_data_utilities}
4 | \alias{teal_data_utilities}
5 | \alias{.append_evaluated_code}
6 | \alias{.append_modified_data}
7 | \title{\code{teal_data} utils}
8 | \usage{
9 | .append_evaluated_code(data, code)
10 |
11 | .append_modified_data(data, objects)
12 | }
13 | \arguments{
14 | \item{data}{(\code{teal_data})}
15 |
16 | \item{code}{(\code{character}) code to append to the object's code slot.}
17 |
18 | \item{objects}{(\code{list}) objects to append to object's environment.}
19 | }
20 | \value{
21 | modified \code{teal_data}
22 | }
23 | \description{
24 | In \code{teal} we need to recreate the \code{teal_data} object due to two operations:
25 | \itemize{
26 | \item we need to append filter-data code and objects which have been evaluated in \code{FilteredData} and
27 | we want to avoid double-evaluation.
28 | \item we need to subset \code{teal_data} to \code{datanames} used by the module, to shorten obtainable R-code
29 | }
30 | }
31 | \details{
32 | Due to above recreation of \code{teal_data} object can't be done simply by using public
33 | \code{teal.code} and \code{teal.data} methods.
34 | }
35 | \keyword{internal}
36 |
--------------------------------------------------------------------------------
/man/teal_extend_server.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/teal_modifiers.R
3 | \name{teal_extend_server}
4 | \alias{teal_extend_server}
5 | \title{Add a Custom Server Logic to \code{teal} Application}
6 | \usage{
7 | teal_extend_server(x, custom_server, module_id = character(0))
8 | }
9 | \arguments{
10 | \item{x}{(\code{teal_app}) A \code{teal_app} object created using the \code{init} function.}
11 |
12 | \item{custom_server}{(\verb{function(input, output, session)} or \verb{function(id, ...)})
13 | The custom server function or server module to set.}
14 |
15 | \item{module_id}{(\code{character(1)}) The ID of the module when a module server function is passed.}
16 | }
17 | \description{
18 | Adds a custom server function to the \code{teal} app. This function can define additional server logic.
19 | }
20 | \keyword{internal}
21 |
--------------------------------------------------------------------------------
/man/validate_app_title_tag.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/utils.R
3 | \name{validate_app_title_tag}
4 | \alias{validate_app_title_tag}
5 | \title{Function for validating the title parameter of \code{teal::init}}
6 | \usage{
7 | validate_app_title_tag(shiny_tag)
8 | }
9 | \arguments{
10 | \item{shiny_tag}{(\code{shiny.tag}) Object to validate for a valid title.}
11 | }
12 | \description{
13 | Checks if the input of the title from \code{teal::init} will create a valid title and favicon tag.
14 | }
15 | \keyword{internal}
16 |
--------------------------------------------------------------------------------
/man/validate_has_data.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/validations.R
3 | \name{validate_has_data}
4 | \alias{validate_has_data}
5 | \title{Validate that dataset has a minimum number of observations}
6 | \usage{
7 | validate_has_data(
8 | x,
9 | min_nrow = NULL,
10 | complete = FALSE,
11 | allow_inf = TRUE,
12 | msg = NULL
13 | )
14 | }
15 | \arguments{
16 | \item{x}{(\code{data.frame})}
17 |
18 | \item{min_nrow}{(\code{numeric(1)}) Minimum allowed number of rows in \code{x}.}
19 |
20 | \item{complete}{(\code{logical(1)}) Flag specifying whether to check only complete cases. Defaults to \code{FALSE}.}
21 |
22 | \item{allow_inf}{(\code{logical(1)}) Flag specifying whether to allow infinite values. Defaults to \code{TRUE}.}
23 |
24 | \item{msg}{(\code{character(1)}) Additional message to display alongside the default message.}
25 | }
26 | \description{
27 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#stable}{\figure{lifecycle-stable.svg}{options: alt='[Stable]'}}}{\strong{[Stable]}}
28 | }
29 | \details{
30 | This function is a wrapper for \code{shiny::validate}.
31 | }
32 | \examples{
33 | library(teal)
34 | ui <- fluidPage(
35 | sliderInput("len", "Max Length of Sepal",
36 | min = 4.3, max = 7.9, value = 5
37 | ),
38 | plotOutput("plot")
39 | )
40 |
41 | server <- function(input, output) {
42 | output$plot <- renderPlot({
43 | iris_df <- iris[iris$Sepal.Length <= input$len, ]
44 | validate_has_data(
45 | iris_df,
46 | min_nrow = 10,
47 | complete = FALSE,
48 | msg = "Please adjust Max Length of Sepal"
49 | )
50 |
51 | hist(iris_df$Sepal.Length, breaks = 5)
52 | })
53 | }
54 | if (interactive()) {
55 | shinyApp(ui, server)
56 | }
57 |
58 | }
59 | \section{Examples in Shinylive}{
60 | \describe{
61 | \item{example-1}{
62 | \href{https://shinylive.io/r/app/#code=NobwRAdghgtgpmAXGKAHVA6ASmANGAYwHsIAXOMpMAGwEsAjAJykYE8AKcqagSgB0ItMnGYFStAG5wABAB4AtNIBmAVwhjaJdj2kAVLAFUAogIF0mLDl14CVtOYqXU7AEwAKUAOZx2A6dIBnOhcRAEkIVBVSXxoKPjxpeIBZKAAPaQAZCk9SAAtpIiVpAGU4VG543D9-aRghaQBeaQAWDABmXFq0xukAdgwATk6JbhUZJoBWap4qiH9UaiJSAHkoyOj4haX4-ghdgQCRKUYHZTUNLSF1zqI1qJ0QatvSdYASLdJTxgoQxjdF6KPOY1WiMWgBAD6LiKCmkoPBwHhAVepXK1AwWQgOXysiaVyir2oFE6AF1qv4RsEoOQIbkoJCXNSoL5gTU4WCGUpZmz-HUIBCIIwiAB3HoARgADNyecQYAs4OQegAxACCGWKRmlbJgAU8PXi-zg9JkUBcACsVAFPil0pjsQUiqiKmBydJ9qzpLlwdEkVClCiytwMdk8p0mEaANYBHoTXb+AC+u3jAloRXYQnIonEUm0D2qAS9EFYKvQ7DsnUOjGOSYEYHjJKAA}{Open in Shinylive}
63 | \if{html}{\out{}}
64 | \if{html}{\out{}}
65 | }
66 | }
67 | }
68 |
69 |
--------------------------------------------------------------------------------
/man/validate_has_elements.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/validations.R
3 | \name{validate_has_elements}
4 | \alias{validate_has_elements}
5 | \title{Validates that vector has length greater than 0}
6 | \usage{
7 | validate_has_elements(x, msg)
8 | }
9 | \arguments{
10 | \item{x}{vector}
11 |
12 | \item{msg}{message to display}
13 | }
14 | \description{
15 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#stable}{\figure{lifecycle-stable.svg}{options: alt='[Stable]'}}}{\strong{[Stable]}}
16 | }
17 | \details{
18 | This function is a wrapper for \code{shiny::validate}.
19 | }
20 | \examples{
21 | data <- data.frame(
22 | id = c(1:10, 11:20, 1:10),
23 | strata = rep(c("A", "B"), each = 15)
24 | )
25 | ui <- fluidPage(
26 | selectInput("ref1", "Select strata1 to compare",
27 | choices = c("A", "B", "C"), selected = "A"
28 | ),
29 | selectInput("ref2", "Select strata2 to compare",
30 | choices = c("A", "B", "C"), selected = "B"
31 | ),
32 | verbatimTextOutput("arm_summary")
33 | )
34 |
35 | server <- function(input, output) {
36 | output$arm_summary <- renderText({
37 | sample_1 <- data$id[data$strata == input$ref1]
38 | sample_2 <- data$id[data$strata == input$ref2]
39 |
40 | validate_has_elements(sample_1, "No subjects in strata1.")
41 | validate_has_elements(sample_2, "No subjects in strata2.")
42 |
43 | paste0(
44 | "Number of samples in: strata1=", length(sample_1),
45 | " comparions strata2=", length(sample_2)
46 | )
47 | })
48 | }
49 | if (interactive()) {
50 | shinyApp(ui, server)
51 | }
52 | }
53 | \section{Examples in Shinylive}{
54 | \describe{
55 | \item{example-1}{
56 | \href{https://shinylive.io/r/app/#code=NobwRAdghgtgpmAXGKAHVA6ASmANGAYwHsIAXOMpMAGwEsAjAJykYE8AKcqagSgB0ItMnGYFStAG5wABAB4AtNIBmAVwhjaJdj2kAVLAFUAogIEATKKShzFFqxiXN47AdOm0z0gLzSC7AIyI-gAMuNL+gQBMoeFBwTy4rtIAzqTMVt7SjHCo7H58YACCBWEFAEIFCdJwUAQAFpn+AKz8EK0qtDbK1B1mAApQAOZwLhBuyXDUcGIAkhCoKqQuYNlK-iXSBQDKk9OkKWmWUP7SpES+RDCoLHAlSW71RLQEcMmZ+UUb5V9gAMKVYQmUzEcE8PgKxTASQSSSBezmCyWBVWkR+O2B+1S6SgkVO52IVxudzGbl8dSeLzePg+kNKYAqeE2fwBKV2ILBTIZ0MSJKkjHolloMF0cAAHqQAPKLRHLFgwAD6yRUMBgLFYlQErQEE0YfK6qnU4i0QkRYSI0sWOhASXNpERABI5Yrlaq2F1shAzCIReL2NaSeNYKgpvKTgppHYoPaPMBI-asUdvD4TYt7at-ABde4pIMh3HhuMxuMJjJeZPzVMorMQbMSbgeSxweV1KDJeW7eBkZLsZK5pv+OkAOXOSvoACs9m8hAdsf4MBqA9I63Q7E2W22OxRSN3e1c80ORypx5P3GMSzj52AtYvrqk4MFRqTSQVB8r6CJpEQlDm969T4gZyOfwvA2KYIEGUg6h7PtQxhRc3AKC5CUYTQIDec9IhAxkwIgqDd2DJtIlaJ9iOkABfVoyIEWhv3YIRyFEcQpG0K1YTqIRWEKdB2A6QERD5SiwDIjMgA}{Open in Shinylive}
57 | \if{html}{\out{}}
58 | \if{html}{\out{}}
59 | }
60 | }
61 | }
62 |
63 |
--------------------------------------------------------------------------------
/man/validate_has_variable.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/validations.R
3 | \name{validate_has_variable}
4 | \alias{validate_has_variable}
5 | \title{Validates that dataset contains specific variable}
6 | \usage{
7 | validate_has_variable(data, varname, msg)
8 | }
9 | \arguments{
10 | \item{data}{(\code{data.frame})}
11 |
12 | \item{varname}{(\code{character(1)}) name of variable to check for in \code{data}}
13 |
14 | \item{msg}{(\code{character(1)}) message to display if \code{data} does not include \code{varname}}
15 | }
16 | \description{
17 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#stable}{\figure{lifecycle-stable.svg}{options: alt='[Stable]'}}}{\strong{[Stable]}}
18 | }
19 | \details{
20 | This function is a wrapper for \code{shiny::validate}.
21 | }
22 | \examples{
23 | data <- data.frame(
24 | one = rep("a", length.out = 20),
25 | two = rep(c("a", "b"), length.out = 20)
26 | )
27 | ui <- fluidPage(
28 | selectInput(
29 | "var",
30 | "Select variable",
31 | choices = c("one", "two", "three", "four"),
32 | selected = "one"
33 | ),
34 | verbatimTextOutput("summary")
35 | )
36 |
37 | server <- function(input, output) {
38 | output$summary <- renderText({
39 | validate_has_variable(data, input$var)
40 | paste0("Selected treatment variables: ", paste(input$var, collapse = ", "))
41 | })
42 | }
43 | if (interactive()) {
44 | shinyApp(ui, server)
45 | }
46 | }
47 | \section{Examples in Shinylive}{
48 | \describe{
49 | \item{example-1}{
50 | \href{https://shinylive.io/r/app/#code=NobwRAdghgtgpmAXGKAHVA6ASmANGAYwHsIAXOMpMAGwEsAjAJykYE8AKcqagSgB0ItMnGYFStAG5wABAB4AtNIBmAVwhjaJdj2kAVLAFUAogIEATKKShzFFqxiXN47AdOkkZAXmmM4qFyh8eNLUFADmpAAWGEQqpNLeAEwADDy4rtKkAO5ECT5+7AQBUEG40kH0QWkh4VExcXkp-BDNKrQ2ytRtZgAKUGFwLhBuAM5woWIAkhCocUNubkESLKUZi2AAyuNwYtLLjLRQ9KGrwwsEkUS0BHAjeUVBHqXlYNlEz0FRvnAfYEqxjCq6TOo22YjgZjyjwgPzAGTSGSkjHolloMF0cAAHqQAPJxWakAIjFQwGAsVhVATNARjRhIjqqdTiLRCAllWKkAk6EAZDkEgAkxNJ5I6vggZhEGOx7B5IL23FodjgAH1IlARsr9odjoM7FAyqy4vz9s0FtJUOryMkAlsJuRIaRfJZ4GR5QcjqERogXmULSNyOxDaRjSwysRqNQ0GMocEqqbpABfZoJgS0JTSQPCUTiKTabkZEaRISsACC6HYbTKtKRybACYAukA}{Open in Shinylive}
51 | \if{html}{\out{}}
52 | \if{html}{\out{}}
53 | }
54 | }
55 | }
56 |
57 |
--------------------------------------------------------------------------------
/man/validate_in.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/validations.R
3 | \name{validate_in}
4 | \alias{validate_in}
5 | \title{Validates that vector includes all expected values}
6 | \usage{
7 | validate_in(x, choices, msg)
8 | }
9 | \arguments{
10 | \item{x}{Vector of values to test.}
11 |
12 | \item{choices}{Vector to test against.}
13 |
14 | \item{msg}{(\code{character(1)}) Error message to display if some elements of \code{x} are not elements of \code{choices}.}
15 | }
16 | \description{
17 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#stable}{\figure{lifecycle-stable.svg}{options: alt='[Stable]'}}}{\strong{[Stable]}}
18 | }
19 | \details{
20 | This function is a wrapper for \code{shiny::validate}.
21 | }
22 | \examples{
23 | ui <- fluidPage(
24 | selectInput(
25 | "species",
26 | "Select species",
27 | choices = c("setosa", "versicolor", "virginica", "unknown species"),
28 | selected = "setosa",
29 | multiple = FALSE
30 | ),
31 | verbatimTextOutput("summary")
32 | )
33 |
34 | server <- function(input, output) {
35 | output$summary <- renderPrint({
36 | validate_in(input$species, iris$Species, "Species does not exist.")
37 | nrow(iris[iris$Species == input$species, ])
38 | })
39 | }
40 | if (interactive()) {
41 | shinyApp(ui, server)
42 | }
43 |
44 | }
45 | \section{Examples in Shinylive}{
46 | \describe{
47 | \item{example-1}{
48 | \href{https://shinylive.io/r/app/#code=NobwRAdghgtgpmAXGKAHVA6ASmANGAYwHsIAXOMpMAGwEsAjAJykYE8AKcqagSgB0ItMnGYFStAG5wABAB4AtNIBmAVwhjaJdj2kAVLAFUAogIEracxUurmAJgAUoAczjsB06QGc41OGICSEKgqpG4QHh58YJ6ofrRwnlG47hFRAMo+fqResQTxiXgpHgQAFkS0BAnSALzSBG7RcKREnlBJ0lFSjJ4VRNREjO2dtIxOQhVteB1gagDWEEQA7uExcQlRPMnhEd6+YnC2NdPeza1JRdIwKtTiqL5HAGIAggAyaSbbmyld9FDiMLo4AAPUgAeRCwVCUU8KhgMBYrA2An4EAE3kYXUsyjUGi0QkhuGkRAhIR0IBSxNIkIAJDC4QisYwKLYRPZGEJQuTth4JNxaLY-nAAPpCdj4kK03L5QkjWiealpKUJQnpJWeaS2IhVBbZYFy0gYJHc6QQRhLMXszzAWXyxVrdXVWri0iS+2EgC6KI8AF8Ud6BLQlNIxcJROIpNoySlPCUhKwnuh2OZCeiun6BGBve6gA}{Open in Shinylive}
49 | \if{html}{\out{}}
50 | \if{html}{\out{}}
51 | }
52 | }
53 | }
54 |
55 |
--------------------------------------------------------------------------------
/man/validate_one_row_per_id.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/validations.R
3 | \name{validate_one_row_per_id}
4 | \alias{validate_one_row_per_id}
5 | \title{Validate that dataset has unique rows for key variables}
6 | \usage{
7 | validate_one_row_per_id(x, key = c("USUBJID", "STUDYID"))
8 | }
9 | \arguments{
10 | \item{x}{(\code{data.frame})}
11 |
12 | \item{key}{(\code{character}) Vector of ID variables from \code{x} that identify unique records.}
13 | }
14 | \description{
15 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#stable}{\figure{lifecycle-stable.svg}{options: alt='[Stable]'}}}{\strong{[Stable]}}
16 | }
17 | \details{
18 | This function is a wrapper for \code{shiny::validate}.
19 | }
20 | \examples{
21 | iris$id <- rep(1:50, times = 3)
22 | ui <- fluidPage(
23 | selectInput(
24 | inputId = "species",
25 | label = "Select species",
26 | choices = c("setosa", "versicolor", "virginica"),
27 | selected = "setosa",
28 | multiple = TRUE
29 | ),
30 | plotOutput("plot")
31 | )
32 | server <- function(input, output) {
33 | output$plot <- renderPlot({
34 | iris_f <- iris[iris$Species \%in\% input$species, ]
35 | validate_one_row_per_id(iris_f, key = c("id"))
36 |
37 | hist(iris_f$Sepal.Length, breaks = 5)
38 | })
39 | }
40 | if (interactive()) {
41 | shinyApp(ui, server)
42 | }
43 |
44 | }
45 | \section{Examples in Shinylive}{
46 | \describe{
47 | \item{example-1}{
48 | \href{https://shinylive.io/r/app/#code=NobwRAdghgtgpmAXGKAHVA6ASmANGAYwHsIAXOMpMAGwEsAjAJykYE8AKcqagSgB0ItMnGYFStAG5wABAB4AtNIBmAVwhjaJdj2kAVLAFUAogIG1GtAM4ASWgBM5ixnFTsAjIgCsABlzTx8JbSALzSAMz8ECq0jsrU0XYAClAA5nDsAtLSlnDUcGIAkhCoKqQZEFlZQiWkBQ6hfGCWqPm0cJaNuJmV1FD0uSHSjQDKufmk2S0EbR143VkEABZEtATtgwQZTXCkRJZQnUNgUoyWq0TURIyHjRLmKUKrB2A8XRWVOXlicPVHObv7TrzaQwFTUcSoPKDfTGbqvbqQoikADypRqW0RpEakUiOUYJ1iqnU4i01VKfiIaNKOhA3UppBq1kxsWcEDsIkSlzKtPeVQslgA+kpYuYrMBRTZhlMZtIAKRCWXSMmkazNVrtPwAXWBEm49ig5AFJDgAsYRAA7gKWowBfZ2BKhX4ANZwVgbLb2bGRYGLKxlB1KayjVDcDAAGQoKVIiz8TDgUCdQVCnkiWQAvpE02ZhfbhKJxFJtDTupZfRBWABBdDsaJ+PEnTMCMBpzVAA}{Open in Shinylive}
49 | \if{html}{\out{}}
50 | \if{html}{\out{}}
51 | }
52 | }
53 | }
54 |
55 |
--------------------------------------------------------------------------------
/revdep/.gitignore:
--------------------------------------------------------------------------------
1 | checks
2 | library
3 | checks.noindex
4 | library.noindex
5 | cloud.noindex
6 | data.sqlite
7 | *.html
8 |
--------------------------------------------------------------------------------
/staged_dependencies.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | current_repo:
3 | repo: insightsengineering/teal
4 | host: https://github.com
5 | upstream_repos:
6 | insightsengineering/roxy.shinylive:
7 | repo: insightsengineering/roxy.shinylive
8 | host: https://github.com
9 | insightsengineering/teal.widgets:
10 | repo: insightsengineering/teal.widgets
11 | host: https://github.com
12 | insightsengineering/teal.code:
13 | repo: insightsengineering/teal.code
14 | host: https://github.com
15 | insightsengineering/teal.data:
16 | repo: insightsengineering/teal.data
17 | host: https://github.com
18 | insightsengineering/teal.slice:
19 | repo: insightsengineering/teal.slice
20 | host: https://github.com
21 | insightsengineering/teal.logger:
22 | repo: insightsengineering/teal.logger
23 | host: https://github.com
24 | insightsengineering/teal.reporter:
25 | repo: insightsengineering/teal.reporter
26 | host: https://github.com
27 | downstream_repos:
28 | insightsengineering/teal.modules.general:
29 | repo: insightsengineering/teal.modules.general
30 | host: https://github.com
31 | insightsengineering/teal.modules.clinical:
32 | repo: insightsengineering/teal.modules.clinical
33 | host: https://github.com
34 | insightsengineering/teal.osprey:
35 | repo: insightsengineering/teal.osprey
36 | host: https://github.com
37 | insightsengineering/teal.goshawk:
38 | repo: insightsengineering/teal.goshawk
39 | host: https://github.com
40 | insightsengineering/teal.modules.hermes:
41 | repo: insightsengineering/teal.modules.hermes
42 | host: https://github.com
43 | insightsengineering/teal.modules.helios:
44 | repo: insightsengineering/teal.modules.helios
45 | host: https://github.com
46 |
--------------------------------------------------------------------------------
/teal.Rproj:
--------------------------------------------------------------------------------
1 | Version: 1.0
2 |
3 | RestoreWorkspace: Default
4 | SaveWorkspace: Default
5 | AlwaysSaveHistory: Default
6 |
7 | EnableCodeIndexing: Yes
8 | UseSpacesForTab: Yes
9 | NumSpacesForTab: 2
10 | Encoding: UTF-8
11 |
12 | RnwWeave: Sweave
13 | LaTeX: pdfLaTeX
14 |
15 | AutoAppendNewline: Yes
16 | StripTrailingWhitespace: Yes
17 |
18 | BuildType: Package
19 | PackageUseDevtools: Yes
20 | PackageInstallArgs: --no-multiarch --with-keep.source
21 | PackageBuildBinaryArgs: --no-build-vignettes
22 | PackageCheckArgs: --as-cran
23 | PackageRoxygenize: rd,collate,namespace
24 |
--------------------------------------------------------------------------------
/tests/testthat.R:
--------------------------------------------------------------------------------
1 | pkg_name <- "teal"
2 | library(pkg_name, character.only = TRUE)
3 | testthat::test_check(pkg_name)
4 | unlink(".renv")
5 | unlink("BiocManager")
6 |
--------------------------------------------------------------------------------
/tests/testthat/helper-shinytest2.R:
--------------------------------------------------------------------------------
1 | simple_teal_data <- function() {
2 | data <- within(teal_data(), {
3 | iris <- iris
4 | mtcars <- mtcars
5 | })
6 | data
7 | }
8 |
9 | report_module <- function(label = "example teal module") {
10 | module(
11 | label = label,
12 | server = function(id, data, reporter) {
13 | moduleServer(id, function(input, output, session) {
14 | teal.reporter::simple_reporter_srv(
15 | id = "reporter",
16 | reporter = reporter,
17 | card_fun = function(card) card
18 | )
19 | updateSelectInput(session, "dataname", choices = isolate(names(data())))
20 | output$dataset <- renderPrint({
21 | req(input$dataname)
22 | data()[[input$dataname]]
23 | })
24 | })
25 | },
26 | ui = function(id) {
27 | ns <- NS(id)
28 | sidebarLayout(
29 | sidebarPanel(
30 | teal.reporter::simple_reporter_ui(ns("reporter")),
31 | selectInput(ns("dataname"), "Choose a dataset", choices = NULL)
32 | ),
33 | mainPanel(verbatimTextOutput(ns("dataset")))
34 | )
35 | }
36 | )
37 | }
38 |
--------------------------------------------------------------------------------
/tests/testthat/setup-logger.R:
--------------------------------------------------------------------------------
1 | logger::log_appender(function(...) NULL, namespace = "teal")
2 |
--------------------------------------------------------------------------------
/tests/testthat/setup-options.R:
--------------------------------------------------------------------------------
1 | # `opts_partial_match_old` is left for exclusions due to partial matching in dependent packages (i.e. not fixable here)
2 | # it might happen that it is not used right now, but it is left for possible future use
3 | # use with: `withr::with_options(opts_partial_match_old, { ... })` inside the test
4 | opts_partial_match_old <- list(
5 | warnPartialMatchDollar = getOption("warnPartialMatchDollar"),
6 | warnPartialMatchArgs = getOption("warnPartialMatchArgs"),
7 | warnPartialMatchAttr = getOption("warnPartialMatchAttr")
8 | )
9 | opts_partial_match_new <- list(
10 | warnPartialMatchDollar = TRUE,
11 | warnPartialMatchArgs = TRUE,
12 | warnPartialMatchAttr = TRUE
13 | )
14 |
15 | if (isFALSE(getFromNamespace("on_cran", "testthat")()) && requireNamespace("withr", quietly = TRUE)) {
16 | withr::local_options(
17 | opts_partial_match_new,
18 | .local_envir = testthat::teardown_env()
19 | )
20 | }
21 |
--------------------------------------------------------------------------------
/tests/testthat/setup-testing_depth.R:
--------------------------------------------------------------------------------
1 | #' Returns testing depth set by session option or by environmental variable.
2 | #'
3 | #' @details Looks for the session option `TESTING_DEPTH` first.
4 | #' If not set, takes the system environmental variable `TESTING_DEPTH`.
5 | #' If neither is set, then returns 3 by default.
6 | #' If the value of `TESTING_DEPTH` is not a numeric of length 1, then returns 3.
7 | #'
8 | #' @return `numeric(1)` the testing depth.
9 | #'
10 | get_testing_depth <- function() {
11 | default_depth <- 3
12 | depth <- getOption("TESTING_DEPTH", Sys.getenv("TESTING_DEPTH", default_depth))
13 | depth <- tryCatch(
14 | as.numeric(depth),
15 | error = function(error) default_depth,
16 | warning = function(warning) default_depth
17 | )
18 | if (length(depth) != 1) depth <- default_depth
19 | depth
20 | }
21 |
22 | #' Skipping tests in the testthat pipeline under specific scope
23 | #' @description This function should be used per each `testthat::test_that` call.
24 | #' Each of the call should specify an appropriate depth value.
25 | #' The depth value will set the appropriate scope so more/less time consuming tests could be recognized.
26 | #' The environment variable `TESTING_DEPTH` is used for changing the scope of `testthat` pipeline.
27 | #' `TESTING_DEPTH` interpretation for each possible value:
28 | #' \itemize{
29 | #' \item{0}{no tests at all}
30 | #' \item{1}{fast - small scope - executed on every commit}
31 | #' \item{3}{medium - medium scope - daily integration pipeline}
32 | #' \item{5}{slow - all tests - daily package tests}
33 | #' }
34 | #' @param depth `numeric` the depth of the testing evaluation,
35 | #' has opposite interpretation to environment variable `TESTING_DEPTH`.
36 | #' So e.g. `0` means run it always and `5` means a heavy test which should be run rarely.
37 | #' If the `depth` argument is larger than `TESTING_DEPTH` then the test is skipped.
38 | #' @importFrom testthat skip
39 | #' @return `NULL` or invoke an error produced by `testthat::skip`
40 | #' @note By default `TESTING_DEPTH` is equal to 3 if there is no environment variable for it.
41 | #' By default `depth` argument lower or equal to 3 will not be skipped because by default `TESTING_DEPTH`
42 | #' is equal to 3. To skip <= 3 depth tests then the environment variable has to be lower than 3 respectively.
43 | skip_if_too_deep <- function(depth) { # nolintr
44 | checkmate::assert_numeric(depth, len = 1, lower = 0, upper = 5)
45 | testing_depth <- get_testing_depth() # by default 3 if there are no env variable
46 | if (testing_depth < depth) {
47 | testthat::skip(paste("testing depth", testing_depth, "is below current testing specification", depth))
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/tests/testthat/test-module_session_info.R:
--------------------------------------------------------------------------------
1 | testthat::describe("srv_session_info lockfile", {
2 | testthat::it(paste0(
3 | "creation process is invoked for teal.lockfile.mode = \"enabled\" ",
4 | "and snapshot is copied to teal_app.lock and removed after session ended"
5 | ), {
6 | testthat::skip_if_not_installed("mirai")
7 | testthat::skip_if_not_installed("renv")
8 | withr::with_options(
9 | list(teal.lockfile.mode = "enabled"),
10 | {
11 | renv_filename <- "teal_app.lock"
12 | shiny::testServer(
13 | app = srv_session_info,
14 | args = list(id = "test"),
15 | expr = {
16 | iter <- 1
17 | while (!file.exists(renv_filename) && iter <= 1000) {
18 | Sys.sleep(0.5)
19 | iter <- iter + 1 # max wait time is 500 seconds
20 | }
21 | testthat::expect_true(file.exists(renv_filename))
22 | }
23 | )
24 | testthat::expect_false(file.exists(renv_filename))
25 | }
26 | )
27 | })
28 | testthat::it("creation process is not invoked for teal.lockfile.mode = \"disabled\"", {
29 | testthat::skip_if_not_installed("mirai")
30 | testthat::skip_if_not_installed("renv")
31 | withr::with_options(
32 | list(teal.lockfile.mode = "disabled"),
33 | {
34 | renv_filename <- "teal_app.lock"
35 | shiny::testServer(
36 | app = srv_session_info,
37 | args = list(id = "test"),
38 | expr = {
39 | testthat::expect_false(file.exists(renv_filename))
40 | }
41 | )
42 | }
43 | )
44 | })
45 | })
46 |
--------------------------------------------------------------------------------
/tests/testthat/test-report_previewer_module.R:
--------------------------------------------------------------------------------
1 | testthat::test_that("report_previewer_module has specific classes", {
2 | testthat::expect_s3_class(
3 | reporter_previewer_module(),
4 | c("teal_module_previewer", "teal_module")
5 | )
6 | })
7 |
8 | testthat::test_that("report_previewer_module throws error if label is not string", {
9 | testthat::expect_error(
10 | reporter_previewer_module(label = 5), "Assertion on 'label' failed: Must be of type 'string'"
11 | )
12 | testthat::expect_error(
13 | reporter_previewer_module(label = c("A", "B")), "Assertion on 'label' failed: Must have length 1."
14 | )
15 | })
16 |
17 | testthat::test_that("report_previewer_module throws no error and stores label if label is string", {
18 | testthat::expect_no_error(r_p_m <- reporter_previewer_module(label = "My label"))
19 | testthat::expect_equal(r_p_m$label, "My label")
20 | })
21 |
22 | testthat::test_that("report_previewer_module default label is Report previewer ", {
23 | r_p_m <- reporter_previewer_module()
24 | testthat::expect_equal(r_p_m$label, "Report previewer")
25 | })
26 |
27 | testthat::test_that(
28 | "report_previewer_module does not accept server_args out of formals(teal.reporter::reporter_previewer_srv) ",
29 | {
30 | error_pattern <- ".*Assertion on \\'all\\(names\\(server_args"
31 | testthat::expect_error(
32 | reporter_previewer_module(server_args = list(x = "A")),
33 | error_pattern
34 | )
35 | testthat::expect_error(
36 | reporter_previewer_module(server_args = list(reporter = "A", global_knitr = 5, d = 1)),
37 | error_pattern
38 | )
39 | }
40 | )
41 |
--------------------------------------------------------------------------------
/tests/testthat/test-shinytest2-init.R:
--------------------------------------------------------------------------------
1 | testthat::skip_if_not_installed("shinytest2")
2 | testthat::skip_if_not_installed("rvest")
3 |
4 | testthat::test_that("e2e: teal app initializes with no errors", {
5 | testthat::skip("chromium")
6 | skip_if_too_deep(5)
7 | app <- TealAppDriver$new(
8 | data = simple_teal_data(),
9 | modules = example_module(label = "Example Module")
10 | )
11 | app$expect_no_shiny_error()
12 | app$stop()
13 | })
14 |
15 | testthat::test_that("e2e: teal app initializes with sessionInfo modal", {
16 | testthat::skip("chromium")
17 | skip_if_too_deep(5)
18 | app <- TealAppDriver$new(
19 | data = simple_teal_data(),
20 | modules = example_module(label = "Example Module")
21 | )
22 |
23 | # Check if button exists.
24 | button_selector <- "#teal-footer-session_info-sessionInfo-button"
25 | testthat::expect_equal(
26 | app$get_text(button_selector),
27 | "Session Info"
28 | )
29 |
30 | app$click(selector = button_selector)
31 |
32 | # Check header and title content.
33 | testthat::expect_equal(
34 | app$get_text("#shiny-modal > div > div > div.modal-header > h4"),
35 | "SessionInfo"
36 | )
37 |
38 | # There are two Copy buttons with similar id and the same label.
39 | testthat::expect_setequal(
40 | testthat::expect_length(
41 | app$get_text(
42 | "#shiny-modal [id^='teal-footer-session_info-sessionInfo-copy_button']"
43 | ),
44 | 2
45 | ),
46 | "Copy to Clipboard"
47 | )
48 | # There are two Dismiss buttons with similar id and the same label.
49 | testthat::expect_setequal(
50 | testthat::expect_length(
51 | app$get_text("#shiny-modal button[data-dismiss]"),
52 | 2
53 | ),
54 | "Dismiss"
55 | )
56 |
57 | # Check session info output.
58 | session_info <- app$get_text("#teal-footer-session_info-sessionInfo-verbatim_content")
59 |
60 | testthat::expect_match(session_info, "R version", fixed = TRUE)
61 | testthat::expect_match(session_info, "attached base packages:", fixed = TRUE)
62 | testthat::expect_match(session_info, "loaded via a namespace (and not attached):", fixed = TRUE)
63 |
64 | testthat::expect_match(session_info, "shiny", fixed = TRUE)
65 | testthat::expect_match(session_info, "teal.slice", fixed = TRUE)
66 | testthat::expect_match(session_info, "teal.reporter", fixed = TRUE)
67 |
68 | app$stop()
69 | })
70 |
71 | testthat::test_that("e2e: init creates UI containing specified title, favicon, header and footer", {
72 | testthat::skip("chromium")
73 | skip_if_too_deep(5)
74 | app <- TealAppDriver$new(
75 | data = simple_teal_data(),
76 | modules = example_module(label = "Example Module"),
77 | title_args = list(
78 | title = "Custom Teal App Title",
79 | something_else = "asdfsdf",
80 | favicon = "https://raw.githubusercontent.com/insightsengineering/hex-stickers/main/PNG/teal.png"
81 | ),
82 | header = "Custom Teal App Header",
83 | footer = "Custom Teal App Footer"
84 | )
85 |
86 | testthat::expect_equal(
87 | app$get_text("head > title")[1],
88 | "Custom Teal App Title"
89 | )
90 | testthat::expect_equal(
91 | rvest::html_attr(
92 | rvest::html_elements(app$get_html_rvest("head > link[rel='icon']"), "link"),
93 | "href"
94 | ),
95 | "https://raw.githubusercontent.com/insightsengineering/hex-stickers/main/PNG/teal.png"
96 | )
97 | testthat::expect_match(
98 | app$get_text("header"),
99 | "Custom Teal App Header"
100 | )
101 | testthat::expect_match(
102 | app$get_text("footer"),
103 | "Custom Teal App Footer"
104 | )
105 | app$stop()
106 | })
107 |
--------------------------------------------------------------------------------
/tests/testthat/test-shinytest2-module_bookmark_manager.R:
--------------------------------------------------------------------------------
1 | testthat::skip_if_not_installed("shinytest2")
2 | testthat::skip_if_not_installed("rvest")
3 |
4 | testthat::test_that("bookmark_manager_button is not rendered by default", {
5 | testthat::skip("chromium")
6 | skip_if_too_deep(5)
7 | app <- TealAppDriver$new(
8 | data = simple_teal_data(),
9 | modules = example_module(label = "Example Module"),
10 | options = list()
11 | )
12 | on.exit(app$stop())
13 | testthat::expect_null(
14 | app$get_html(".bookmark_manager_button")
15 | )
16 | })
17 |
18 |
19 | testthat::test_that("bookmark_manager_button is not rendered when enableBookmarking = 'url'", {
20 | testthat::skip("chromium")
21 | skip_if_too_deep(5)
22 | app <- TealAppDriver$new(
23 | data = simple_teal_data(),
24 | modules = example_module(label = "Example Module"),
25 | options = list(shiny.bookmarkStore = "url")
26 | )
27 | on.exit(app$stop())
28 | testthat::expect_null(
29 | app$get_html(".bookmark_manager_button")
30 | )
31 | })
32 |
33 |
34 | testthat::test_that("bookmark_manager_button is rendered when enableBookmarking = 'server'", {
35 | testthat::skip("chromium")
36 | skip_if_too_deep(5)
37 | app <- TealAppDriver$new(
38 | data = simple_teal_data(),
39 | modules = example_module(label = "Example Module"),
40 | options = list(shiny.bookmarkStore = "server")
41 | )
42 | on.exit(app$stop())
43 | testthat::expect_true(!is.null(app$get_html(".bookmark_manager_button")))
44 | })
45 |
46 | testthat::test_that("bookmark_manager_button shows modal with url containing state_id when clicked", {
47 | testthat::skip("chromium")
48 | skip_if_too_deep(5)
49 | app <- TealAppDriver$new(
50 | data = simple_teal_data(),
51 | modules = example_module(label = "Example Module"),
52 | options = list(shiny.bookmarkStore = "server")
53 | )
54 | bookmark_button_id <- app$get_attr(".bookmark_manager_button", "id")
55 | app$click(bookmark_button_id)
56 |
57 | testthat::expect_match(
58 | rvest::html_text(app$get_html_rvest("div[id$=bookmark_modal] pre")),
59 | "_state_id_"
60 | )
61 | })
62 |
--------------------------------------------------------------------------------
/tests/testthat/test-shinytest2-modules.R:
--------------------------------------------------------------------------------
1 | testthat::skip_if_not_installed("shinytest2")
2 | testthat::skip_if_not_installed("rvest")
3 |
4 | testthat::test_that("e2e: the module server logic is only triggered when the teal module becomes active", {
5 | testthat::skip("chromium")
6 | skip_if_too_deep(5)
7 | value_export_module <- function(label = "custom module") {
8 | module(
9 | label = label,
10 | server = function(id, data) {
11 | moduleServer(id, function(input, output, session) {
12 | shiny::exportTestValues(
13 | value = rnorm(1)
14 | )
15 | })
16 | },
17 | ui = function(id) {
18 | ns <- NS(id)
19 | h1("Module that exports a random value for testing")
20 | }
21 | )
22 | }
23 |
24 | app <- TealAppDriver$new(
25 | data = simple_teal_data(),
26 | modules = modules(
27 | value_export_module(label = "Module 1"),
28 | value_export_module(label = "Module 2")
29 | )
30 | )
31 |
32 | test_exports <- app$get_values()$export
33 |
34 | expect_equal(length(test_exports), 1)
35 |
36 | app$navigate_teal_tab("Module 2")
37 | test_exports <- app$get_values()$export
38 |
39 | expect_equal(length(test_exports), 2)
40 | app$stop()
41 | })
42 |
43 |
44 | testthat::test_that("e2e: filter panel only shows the data supplied using datanames", {
45 | testthat::skip("chromium")
46 | skip_if_too_deep(5)
47 | app <- TealAppDriver$new(
48 | data = simple_teal_data(),
49 | modules = modules(
50 | example_module(label = "mtcars", datanames = "mtcars")
51 | )
52 | )
53 |
54 | testthat::expect_identical(
55 | app$get_active_filter_vars(),
56 | "mtcars"
57 | )
58 | app$stop()
59 | })
60 |
61 | testthat::test_that("e2e: filter panel shows all the datasets when datanames is all", {
62 | testthat::skip("chromium")
63 | skip_if_too_deep(5)
64 | app <- TealAppDriver$new(
65 | data = simple_teal_data(),
66 | modules = modules(
67 | example_module(label = "all", datanames = "all")
68 | )
69 | )
70 |
71 | testthat::expect_identical(
72 | app$get_active_filter_vars(),
73 | c("iris", "mtcars")
74 | )
75 | app$stop()
76 | })
77 |
78 |
79 | testthat::test_that("e2e: all the nested teal modules are initiated as expected", {
80 | testthat::skip("chromium")
81 | skip_if_too_deep(5)
82 | app <- TealAppDriver$new(
83 | data = simple_teal_data(),
84 | modules = modules(
85 | example_module(label = "Example Module"),
86 | modules(
87 | label = "Nested Modules",
88 | example_module(label = "Nested 1"),
89 | example_module(label = "Nested 2"),
90 | modules(
91 | label = "Sub Nested Modules",
92 | example_module(label = "Nested 1"),
93 | example_module(label = "Nested 1")
94 | )
95 | )
96 | )
97 | )
98 | app_modules <- app$get_text(selector = "ul.shiny-bound-input li a")
99 | testthat::expect_identical(
100 | app_modules,
101 | c(
102 | "Example Module", "Nested Modules", "Nested 1", "Nested 2",
103 | "Sub Nested Modules", "Nested 1", "Nested 1"
104 | )
105 | )
106 | app$stop()
107 | })
108 |
--------------------------------------------------------------------------------
/tests/testthat/test-shinytest2-reporter.R:
--------------------------------------------------------------------------------
1 | testthat::skip_if_not_installed("shinytest2")
2 | testthat::skip_if_not_installed("rvest")
3 |
4 | testthat::test_that("e2e: reporter tab is created when a module has reporter", {
5 | testthat::skip("chromium")
6 | skip_if_too_deep(5)
7 | app <- TealAppDriver$new(
8 | data = simple_teal_data(),
9 | modules = report_module(label = "Module with Reporter")
10 | )
11 |
12 | teal_tabs <- rvest::html_elements(app$get_html_rvest(selector = "#teal-teal_modules-active_tab"), "a")
13 | tab_names <- setNames(
14 | rvest::html_attr(teal_tabs, "data-value"),
15 | rvest::html_text(teal_tabs)
16 | )
17 | testthat::expect_identical(
18 | tab_names,
19 | c("Module with Reporter" = "module_with_reporter", "Report previewer" = "report_previewer")
20 | )
21 |
22 | app$stop()
23 | })
24 |
25 | testthat::test_that("e2e: reporter tab is not created when a module has no reporter", {
26 | testthat::skip("chromium")
27 | skip_if_too_deep(5)
28 | app <- TealAppDriver$new(
29 | data = simple_teal_data(),
30 | modules = example_module(label = "Example Module")
31 | )
32 | teal_tabs <- rvest::html_elements(
33 | app$get_html_rvest(selector = "#teal-teal_modules-active_tab"),
34 | "a"
35 | )
36 | tab_names <- setNames(
37 | rvest::html_attr(teal_tabs, "data-value"),
38 | rvest::html_text(teal_tabs)
39 | )
40 |
41 | testthat::expect_identical(
42 | tab_names,
43 | c("Example Module" = "example_module")
44 | )
45 |
46 | app$stop()
47 | })
48 |
49 | testthat::test_that("e2e: adding a report card in a module adds it in the report previewer tab", {
50 | testthat::skip("chromium")
51 | skip_if_too_deep(5)
52 | app <- TealAppDriver$new(
53 | data = simple_teal_data(),
54 | modules = report_module(label = "Module with Reporter")
55 | )
56 |
57 | app$click(NS(app$active_module_ns(), "reporter-add_report_card_simple-add_report_card_button"))
58 |
59 | app$set_input(
60 | NS(app$active_module_ns(), "reporter-add_report_card_simple-label"),
61 | "Card name"
62 | )
63 | app$set_input(
64 | NS(app$active_module_ns(), "reporter-add_report_card_simple-comment"),
65 | "Card comment"
66 | )
67 |
68 | app$click(NS(app$active_module_ns(), "reporter-add_report_card_simple-add_card_ok"))
69 |
70 | app$navigate_teal_tab("Report previewer")
71 |
72 | accordian_selector <- sprintf("#%s-pcards .accordion-toggle", app$active_module_ns())
73 | app$click(selector = accordian_selector)
74 |
75 |
76 | testthat::expect_match(
77 | app$get_text(selector = accordian_selector),
78 | "Card 1: Card name"
79 | )
80 |
81 | testthat::expect_match(
82 | app$get_text(selector = "#card1 pre"),
83 | "Card comment"
84 | )
85 |
86 | app$stop()
87 | })
88 |
89 | testthat::test_that("e2e: reporter_previewer_module do not show data_summary nor filter_panel", {
90 | testthat::skip("chromium")
91 | skip_if_too_deep(5)
92 | app <- teal:::TealAppDriver$new(
93 | data = simple_teal_data(),
94 | modules = report_module(label = "Module with Reporter")
95 | )
96 |
97 | app$navigate_teal_tab("Report previewer")
98 |
99 | testthat::expect_null(app$is_visible(app$active_data_summary_element("table")))
100 |
101 | testthat::expect_null(app$get_active_filter_vars())
102 |
103 | app$stop()
104 | })
105 |
--------------------------------------------------------------------------------
/tests/testthat/test-shinytest2-show-rcode.R:
--------------------------------------------------------------------------------
1 | testthat::skip_if_not_installed("shinytest2")
2 | testthat::skip_if_not_installed("rvest")
3 |
4 | testthat::test_that("e2e: teal app initializes with Show R Code modal", {
5 | testthat::skip("chromium")
6 | skip_if_too_deep(5)
7 | app <- TealAppDriver$new(
8 | data = simple_teal_data(),
9 | modules = example_module(label = "Example Module")
10 | )
11 |
12 | # Check if button exists.
13 | button_selector <- app$active_module_element("rcode-button")
14 | testthat::expect_equal(
15 | app$get_text(button_selector),
16 | "Show R code"
17 | )
18 |
19 | app$click(selector = button_selector)
20 |
21 | # Check header and title content.
22 | testthat::expect_equal(
23 | app$get_text("#shiny-modal div.modal-header > h4"),
24 | "Example Code"
25 | )
26 |
27 | # There are two Dismiss buttons with similar id and the same label.
28 | testthat::expect_setequal(
29 | testthat::expect_length(
30 | app$get_text("#shiny-modal button[data-dismiss]"),
31 | 2
32 | ),
33 | "Dismiss"
34 | )
35 | # Check for Copy buttons.
36 | testthat::expect_equal(
37 | app$get_text(app$active_module_element("rcode-copy_button1")),
38 | "Copy to Clipboard"
39 | )
40 | testthat::expect_equal(
41 | app$get_text(app$active_module_element("rcode-copy_button2")),
42 | "Copy to Clipboard"
43 | )
44 |
45 | # Check R code output.
46 | testthat::expect_setequal(
47 | strsplit(app$get_text(app$active_module_element("rcode-verbatim_content")), "\n")[[1]],
48 | c(
49 | "iris <- iris",
50 | "mtcars <- mtcars",
51 | sprintf('stopifnot(rlang::hash(iris) == "%s") # @linksto iris', rlang::hash(iris)),
52 | sprintf('stopifnot(rlang::hash(mtcars) == "%s") # @linksto mtcars', rlang::hash(mtcars)),
53 | ".raw_data <- list2env(list(iris = iris, mtcars = mtcars))",
54 | "lockEnvironment(.raw_data) # @linksto .raw_data",
55 | "object <- iris",
56 | "object"
57 | )
58 | )
59 |
60 | app$stop()
61 | })
62 |
--------------------------------------------------------------------------------
/tests/testthat/test-shinytest2-wunder_bar.R:
--------------------------------------------------------------------------------
1 | testthat::skip_if_not_installed("shinytest2")
2 | testthat::skip_if_not_installed("rvest")
3 |
4 | testthat::test_that("wunder_bar_srv clicking filter icon opens filter-manager modal", {
5 | testthat::skip("chromium")
6 | skip_if_too_deep(5)
7 | app <- TealAppDriver$new(
8 | data = simple_teal_data(),
9 | modules = example_module(label = "Example Module")
10 | )
11 |
12 | filter_manager_btn_id <- grep(
13 | "filter_manager",
14 | x = app$get_attr(".wunder_bar_button", "id"),
15 | value = TRUE
16 | )
17 |
18 | testthat::expect_true(is.null(app$get_text(".teal-filter-manager-modal")))
19 | app$click(filter_manager_btn_id)
20 | testthat::expect_true(!is.null(app$get_text(".teal-filter-manager-modal")))
21 | })
22 |
23 |
24 | testthat::test_that("wunder_bar_srv clicking snapshot icon opens snapshot-manager modal", {
25 | testthat::skip("chromium")
26 | skip_if_too_deep(5)
27 | app <- TealAppDriver$new(
28 | data = simple_teal_data(),
29 | modules = example_module(label = "Example Module")
30 | )
31 |
32 | snapshot_manager_btn_id <- grep(
33 | "snapshot_manager",
34 | x = app$get_attr(".wunder_bar_button", "id"),
35 | value = TRUE
36 | )
37 |
38 | testthat::expect_true(is.null(app$get_text(".snapshot_manager_modal")))
39 | app$click(snapshot_manager_btn_id)
40 | testthat::expect_true(!is.null(app$get_text(".snapshot_manager_modal")))
41 | })
42 |
--------------------------------------------------------------------------------
/tests/testthat/test-teal_data_module.R:
--------------------------------------------------------------------------------
1 | testthat::test_that("teal_data_module returns teal_data_module", {
2 | testthat::expect_s3_class(
3 | teal_data_module(ui = function(id) tags$div(), server = function(id) NULL),
4 | "teal_data_module"
5 | )
6 | })
7 |
8 | testthat::test_that("teal_data_module throws when ui has other formals than id only", {
9 | testthat::expect_error(
10 | teal_data_module(ui = function(id, x) tags$div(), server = function(id) NULL),
11 | "Must have exactly 1 formal arguments"
12 | )
13 | })
14 |
15 | testthat::test_that("teal_data_module throws when server has other formals than id only", {
16 | testthat::expect_error(
17 | teal_data_module(ui = function(id) tags$div(), server = function(id, x) NULL),
18 | ".*exactly 1 formal.*"
19 | )
20 | testthat::expect_error(
21 | teal_data_module(ui = function(id) tags$div(), server = function(id, x) NULL),
22 | ".*formal arguments.*"
23 | )
24 | })
25 |
--------------------------------------------------------------------------------
/tests/testthat/test-teal_transform_module.R:
--------------------------------------------------------------------------------
1 | testthat::describe("make_teal_transform_server produces a valid teal_transform_module", {
2 | testthat::it("expression", {
3 | label <- "output_decorator"
4 | output_decorator <- teal_transform_module(
5 | label = label,
6 | server = make_teal_transform_server(
7 | expression(data1 <- rev(data1))
8 | )
9 | )
10 |
11 | shiny::testServer(
12 | app = srv_transform_teal_data,
13 | args = list(
14 | id = "test",
15 | data = reactive(teal.data::teal_data(data1 = iris, data2 = mtcars)),
16 | transformators = output_decorator
17 | ),
18 | expr = {
19 | session$flushReact()
20 | testthat::expect_identical(module_output()[["data1"]], rev(iris))
21 | }
22 | )
23 | })
24 |
25 | testthat::it("quote", {
26 | label <- "output_decorator"
27 | output_decorator <- teal_transform_module(
28 | label = label,
29 | server = make_teal_transform_server(
30 | quote(data1 <- rev(data1))
31 | )
32 | )
33 |
34 | shiny::testServer(
35 | app = srv_transform_teal_data,
36 | args = list(
37 | id = "test",
38 | data = reactive(teal.data::teal_data(data1 = iris, data2 = mtcars)),
39 | transformators = output_decorator
40 | ),
41 | expr = {
42 | session$flushReact()
43 | testthat::expect_identical(module_output()[["data1"]], rev(iris))
44 | }
45 | )
46 | })
47 | })
48 |
49 | testthat::test_that(
50 | "ui_transform_teal_data and srv_transform_teal_data have the same namespace for transform module",
51 | {
52 | ttm <- teal_transform_module(
53 | ui = function(id) tags$div(id = NS(id, "a_div"), "a div"),
54 | server = function(id, data) {
55 | moduleServer(id, function(input, output, session) {
56 | full_id <- session$ns("a_div")
57 | reactive(within(data(), id <- full_id, full_id = full_id))
58 | })
59 | }
60 | )
61 |
62 | initial_id <- "a-path-to-an-inner-namespace"
63 | ui <- ui_transform_teal_data(initial_id, ttm)
64 | # Find element that ends in "-a_div"
65 | expected_id <- unname(unlist(ui)[grepl(".*-a_div$", unlist(ui))][[1]])
66 |
67 | testServer(
68 | app = srv_transform_teal_data,
69 | args = list(
70 | id = initial_id,
71 | data = reactive(within(teal_data(), iris <- iris)),
72 | transformators = ttm
73 | ),
74 | expr = {
75 | session$flushReact()
76 | testthat::expect_equal(module_output()$id, expected_id)
77 | }
78 | )
79 | }
80 | )
81 |
--------------------------------------------------------------------------------
/tests/testthat/test-validate_has_data.R:
--------------------------------------------------------------------------------
1 | data <- data.frame(x = 1:10, y = c(1:9, NA), z = c(Inf, 2:10))
2 |
3 | testthat::test_that("validate_has_data throws no error when data has at least as many rows as min_nrow", {
4 | testthat::expect_silent(validate_has_data(data, 10))
5 | testthat::expect_silent(validate_has_data(data, 5))
6 | })
7 |
8 | testthat::test_that("validate_has_data throws error when min_nrow > #rows of data", {
9 | testthat::expect_error(validate_has_data(data, 11))
10 | })
11 |
12 | testthat::test_that("validate_has_data accepts logical complete argument", {
13 | testthat::expect_silent(validate_has_data(data[, c("x", "z")], 10, complete = TRUE))
14 | testthat::expect_silent(validate_has_data(data[, c("x", "z")], 10, complete = FALSE))
15 | })
16 |
17 | testthat::test_that("validate_has_data throws error when data has NA and complete is set to TRUE", {
18 | testthat::expect_error(validate_has_data(data[, c("x", "y")], 10, complete = TRUE))
19 | })
20 |
21 | testthat::test_that("validate_has_data accepts logical allow_inf argument", {
22 | testthat::expect_silent(validate_has_data(data[, c("x", "y")], 10, allow_inf = FALSE))
23 | testthat::expect_error(validate_has_data(data[, c("x", "y")], 10, complete = TRUE, allow_inf = FALSE))
24 | })
25 |
26 | testthat::test_that("validate_has_data accepts throws error when data has Inf values and allow_inf is set to FALSE", {
27 | testthat::expect_error(validate_has_data(data[, c("x", "z")], 10, allow_inf = FALSE))
28 | })
29 |
30 | testthat::test_that("validate_has_data accepts throws error when data has Inf values and allow_inf is set to FALSE", {
31 | testthat::expect_error(validate_has_data(data[, c("x", "z")], 10, allow_inf = FALSE))
32 | testthat::expect_error(validate_has_data(data[, c("x", "z")], 10, complete = TRUE, allow_inf = FALSE))
33 | })
34 |
35 | testthat::test_that("validate_has_data allow_inf argument ignores non-numeric columns", {
36 | data <- data.frame(x = 3:5, w = c("A", "B", "C"), z = c(Inf, 4, 5))
37 | testthat::expect_silent(validate_has_data(data[, c("x", "w")], 3, allow_inf = FALSE))
38 | testthat::expect_error(validate_has_data(data, 3, allow_inf = FALSE))
39 | })
40 |
41 | testthat::test_that("validate_has_data returns message when msg argument is set", {
42 | testthat::expect_error(
43 | validate_has_data(data, 11, msg = "Check data."),
44 | "Minimum number of records not met: >= 11 records required.\nCheck data."
45 | )
46 | })
47 |
48 | testthat::test_that("validate_has_data returns message msg argument is set and complete is set to TRUE", {
49 | testthat::expect_error(
50 | validate_has_data(data[, c("x", "y")], 11, complete = TRUE, msg = "Check data."),
51 | "Number of complete cases is less than: 11\nCheck data."
52 | )
53 | })
54 |
55 | testthat::test_that("validate_has_data returns throws error with non-character msg input", {
56 | testthat::expect_error(
57 | validate_has_data(data, 10, msg = 1),
58 | "Assertion on 'msg' failed: Must be of type 'string' \\(or 'NULL'\\), not 'double'"
59 | )
60 |
61 | testthat::expect_error(
62 | validate_has_data(data, 10, msg = TRUE),
63 | "Assertion on 'msg' failed: Must be of type 'string' \\(or 'NULL'\\), not 'logical'."
64 | )
65 | })
66 |
--------------------------------------------------------------------------------
/vignettes/.gitignore:
--------------------------------------------------------------------------------
1 | *.html
2 | *.R
3 |
--------------------------------------------------------------------------------
/vignettes/blueprint/_setup.Rmd:
--------------------------------------------------------------------------------
1 |
2 | ```{css, echo=FALSE}
3 | pre.mermaid {
4 | background: transparent;
5 | }
6 | ```
7 |
8 | ```{r, echo=FALSE}
9 | shiny::tags$script(type = "module", "import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid/+esm'")
10 | ```
11 |
--------------------------------------------------------------------------------
/vignettes/blueprint/dataflow.Rmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Data Flow"
3 | author: "NEST CoreDev"
4 | output: rmarkdown::html_vignette
5 | vignette: >
6 | %\VignetteIndexEntry{Data Flow}
7 | %\VignetteEngine{knitr::rmarkdown}
8 | %\VignetteEncoding{UTF-8}
9 | ---
10 |
11 | ```{r, child="_setup.Rmd"}
12 | ```
13 |
14 | ```{r dataflow_mermaid1, echo=FALSE}
15 | shiny::pre(
16 | class = "mermaid",
17 | "
18 | %% This is a mermaid diagram, if you see this the plot failed to render. Sorry.
19 | sequenceDiagram;
20 | autonumber
21 | participant data
22 | participant filters
23 | participant filtered data
24 | participant teal module
25 | data->filters: gets
26 | filters->>filtered data: becomes
27 | filtered data->>teal module: sent to
28 | "
29 | )
30 | ```
31 |
32 | The sequence diagram above illustrates the different stages that data goes through within the `teal` framework, supported by the `teal.slice` package:
33 |
34 | 1. Data is created and loaded into `teal` app;
35 | - Data sets are wrapped in a `teal_data` before being passed to the app;
36 | - The [`teal_data` class](input_data.html) facilitates reproducibility;
37 | 2. Data is passed to the filter panel;
38 | - Users _(or app developers)_ can specify filters to apply;
39 | - Filters can be specified globally, for the whole app, or for specific modules;
40 | - Filtering code is appended to the data;
41 | - See the [Filter panel vignette](filter_panel.html) for details;
42 | 3. Filtered data is sent to `teal` modules for analysis;
43 | - Each module receives a `teal_data` object so analysis code applied to the data is tracked _(and can be used to reproduce the whole analysis)_;
44 |
45 | Whenever filters are added or removed, the data coming into modules is re-computed, providing the `teal` module with new filtered data to conduct the required analysis.
46 |
--------------------------------------------------------------------------------
/vignettes/blueprint/filter_panel.Rmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Filter Panel"
3 | author: "NEST CoreDev"
4 | output: rmarkdown::html_vignette
5 | vignette: >
6 | %\VignetteIndexEntry{Filter Panel}
7 | %\VignetteEngine{knitr::rmarkdown}
8 | %\VignetteEncoding{UTF-8}
9 | ---
10 |
11 | ## Introduction
12 |
13 |
14 |
15 |
16 |
17 | The `teal.slice` package provides `teal` applications with the **filter panel**, a powerful tool for exploring and analyzing data, and a key component of the `teal` framework.
18 |
19 | One of the great things about the filter panel is that it comes built-in with `teal`, requiring no programming knowledge to use.
20 |
21 | The filter panel provides a convenient way for users to subset their data, simplifying the process of exploration and comprehension.
22 | Moreover, users can activate or deactivate filter states interactively, either individually or globally, using the filter panel.
23 |
24 |
25 |
26 |
27 | ## Filter flow
28 |
29 | ```{r, child="_setup.Rmd"}
30 | ```
31 |
32 | ```{r dataflow_mermaid1, echo=FALSE}
33 | shiny::pre(
34 | class = "mermaid",
35 | "
36 | %% This is a mermaid diagram, if you see this the plot failed to render. Sorry.
37 | sequenceDiagram
38 | autonumber
39 | data->teal.slice: processed by
40 | teal.slice->>shiny inputs: creates
41 | Note over teal.slice,shiny inputs: based on data type
42 | shiny inputs->>reactive dataset: updates
43 | reactive dataset->>teal modules: processed by
44 | "
45 | )
46 | ```
47 |
48 | The filter panel creates subsets of data. Subsetting is achieved by creating filter states, each of which holds a logical predicate (filter condition) that is applied to single variables. These filter conditions are composed into a single expression, a call to a particular function (e.g. `dplyr::filter`), and that expression is evaluated to create a filtered data subset.
49 |
50 | The process is entirely interactive. Filter states can be created, removed, and changed at will, however, the app developer may choose to constrain or even restrict them.
51 |
52 | When a filter state is created, the filter panel generates a _filter card_ with `shiny` inputs appropriate to the type of the variable, e.g. range selectors for numeric columns and sets of checkboxes or drop-down menus for categorical ones.
53 |
54 | As users interact with the filter cards, the subsetting complete expression is updated and filtered data is recomputed.
55 |
56 | The filtered data is passed to `teal` modules for downstream analysis. The subsetting expression is returned along with the data, ensuring an unbroken track record of the entire analysis. Signature of the data are also stored to ensure reproducible results.
57 |
58 |
--------------------------------------------------------------------------------
/vignettes/blueprint/in_app_data.Rmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "In-App Data"
3 | author: "NEST CoreDev"
4 | output: rmarkdown::html_vignette
5 | vignette: >
6 | %\VignetteIndexEntry{In-App Data}
7 | %\VignetteEngine{knitr::rmarkdown}
8 | %\VignetteEncoding{UTF-8}
9 | ---
10 |
11 | ## Building data in the App
12 |
13 | Typically the data that is passed into a `teal` application is available before the app is run.
14 | However, this is not always true and in some cases the data will be built only after the app has started.
15 | A good example is pulling the data from an external repository, like a database, or uploading a file.
16 | Additional authentication may be required.
17 |
18 | ### `teal_data_module`
19 |
20 | Preprocessing actions can be performed in-app using the `teal_data_module`.
21 | Rather than passing a `teal_data` object to the app, one may pass a _`shiny` module_ that _returns_ a `teal_data` object (wrapped in a reactive expression).
22 | This allows the app developer to include user actions data creation, fetching, and even pre-filtering modification.
23 |
24 | ## Further reading
25 |
26 | A complete explanation of using the `teal_data_module` can be found in [this `teal` vignette](../data-as-shiny-module.html)
27 |
--------------------------------------------------------------------------------
/vignettes/blueprint/index.Rmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "About Technical Blueprint"
3 | author: "NEST CoreDev"
4 | output: rmarkdown::html_vignette
5 | vignette: >
6 | %\VignetteIndexEntry{About Technical Blueprint}
7 | %\VignetteEngine{knitr::rmarkdown}
8 | %\VignetteEncoding{UTF-8}
9 | ---
10 |
11 | Welcome to `teal` Technical Blueprint documentation!
12 |
13 | The purpose of this material is to aid new developer's comprehension of the fundamental principles of the `teal` framework.
14 | We will explore crucial `teal` concepts such as data flow, actors, and filter panel, among others.
15 |
16 | While this material will be presented at a high-level, we will direct you to our vignettes for a more in-depth understanding.
17 |
18 | Our hope is that this resource will provide new developers with a strong grasp of `teal` products, enabling them to contribute to code with confidence.
19 |
--------------------------------------------------------------------------------
/vignettes/blueprint/input_data.Rmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Input Data"
3 | author: "NEST CoreDev"
4 | output: rmarkdown::html_vignette
5 | vignette: >
6 | %\VignetteIndexEntry{Input Data}
7 | %\VignetteEngine{knitr::rmarkdown}
8 | %\VignetteEncoding{UTF-8}
9 | ---
10 |
11 | ## Introduction
12 |
13 | Reproducibility is paramount in the pharmaceutical industry.
14 | Accurate and consistent results are essential to ensure high-quality research and the safety of patients.
15 | By prioritizing reproducibility, researchers can validate their methods, confirm their findings, and contribute to the advancement of the field.
16 |
17 | The `teal.code` package provides the [`qenv` class](https://insightsengineering.github.io/teal.code/latest-tag/articles/qenv.html) that facilitates code reproducibility.
18 | Code is passed to a `qenv` object, where is evaluated in a specific environment.
19 | `qenv` also stores the code so that it can be retrieved on request.
20 |
21 | The `teal_data` class, which serves as the primary data interface for `teal` applications, inherits this code tracking behavior from `qenv`.
22 |
23 | ## Preparing data for a `teal` application
24 |
25 | All `teal` applications run on data provided in a `teal_data` object.
26 | Data objects are stored and modified within the environment of the `teal_data` object and all `R` code used is tracked, which allows for the code to be evaluated and executed in the `teal` application, and reproduced outside the `teal` application.
27 | This includes data loading, preprocessing, filtering, transformations, and plotting, etc.
28 |
29 | The `teal_data` object makes it easy for users to reproduce and validate the results of their analyses.
30 |
31 | ```{dot teal_data_dot_diagram, echo=FALSE}
32 | digraph G {
33 | teal_data [label = "teal_data"];
34 | node [shape=box];
35 | teal_modules [label = "teal modules analysis R code"];
36 | library [label = "R library() calls"];
37 | filter_states [label = "filter states R code"];
38 | data [label = "data preprocessing R code"];
39 | teal_modules -> teal_data;
40 | library -> teal_data;
41 | edge [dir="back"];
42 | teal_data -> filter_states;
43 | teal_data -> data;
44 | }
45 | ```
46 |
47 | Learn more about the use of `teal_data` in the [`teal.data` package vignettes](https://insightsengineering.github.io/teal.data/latest-tag/articles).
48 |
49 | ## `Show R Code` and `Reporter`
50 |
51 | In both the `teal.modules.clinical` and `teal.modules.general` packages, you'll find that most modules include a convenient `Show R Code` button.
52 | When this button is clicked, a modal window appears, revealing the `R` code responsible for generating the module's output.
53 | This functionality is achieved by inspecting the `teal_data` object and retrieving code from it.
54 | With the `Show R Code` button, users can easily copy and independently run the code to reproduce the analysis presented in the teal module.
55 |
56 | {width=50%}
57 |
58 | The Reporter feature also leverages the `teal_data` object in its operation.
59 | Much like the `Show R Code` mechanism, the code displayed in a Reporter Card is extracted from the `teal_data` object.
60 |
61 | {width=50%}
62 |
63 | To learn more about the `Reporter` feature, please visit the [`teal.reporter` documentation](https://insightsengineering.github.io/teal.reporter/latest-tag/index.html).
64 |
65 | Overall, `qenv` from `teal.code` and its child class, `teal_data`, are powerful tools for ensuring code reproducibility and promoting high-quality research in the `R` programming language.
66 |
--------------------------------------------------------------------------------
/vignettes/blueprint/intro.Rmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Introduction"
3 | author: "NEST CoreDev"
4 | output: rmarkdown::html_vignette
5 | vignette: >
6 | %\VignetteIndexEntry{Introduction}
7 | %\VignetteEngine{knitr::rmarkdown}
8 | %\VignetteEncoding{UTF-8}
9 | ---
10 |
11 | `teal` is an interactive data exploration framework based on `shiny`, designed primarily to analyze CDISC clinical trial data.
12 |
13 | A `shiny` Application created with `teal` offers users the ability to:
14 |
15 | - Import data from external sources;
16 | - Dynamically filter data for analysis;
17 | - Generate reproducible code for future analysis;
18 | - Create and download reports of analysis results _(for analysis modules that support reporting)_.
19 |
20 | Moreover, the `teal` framework provides application developers with a wide range of customizable standard analysis modules to integrate into their applications, along with a logging framework that facilitates debugging.
21 | Additionally, advanced users of the framework can develop new analysis modules and easily integrate them into any `teal` application.
22 |
23 | The `teal` framework's functionality draws heavily from the following packages:
24 |
25 | | R package | Description |
26 | |----------------------|:------------------------------------------------------------------------|
27 | |[`teal`](https://insightsengineering.github.io/teal) | `shiny`-based interactive exploration framework for analyzing data|
28 | |[`teal.widgets`](https://insightsengineering.github.io/teal.widgets) | `shiny` UI components used within `teal`|
29 | |[`teal.data`](https://insightsengineering.github.io/teal.data) | provides the data structure used in all `teal` applications|
30 | |[`teal.slice`](https://insightsengineering.github.io/teal.slice) | provides the filter panel to allow dynamic filtering of data|
31 | |[`teal.code`](https://insightsengineering.github.io/teal.code) | provides a mechanism for tracking code to reproduce an analysis|
32 | |[`teal.logger`](https://insightsengineering.github.io/teal.logger) | standardizes logging within `teal` framework|
33 | |[`teal.reporter`](https://insightsengineering.github.io/teal.reporter) | allows `teal` applications to generate reports|
34 |
35 | Although these packages are mentioned in the material, we strongly recommend visiting their vignettes to learn more about them.
36 |
37 | Learn on how to make your first `teal` application [here](../getting-started-with-teal.html)!
38 |
--------------------------------------------------------------------------------
/vignettes/blueprint/module_encapsulation.Rmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Module Encapsulation"
3 | author: "NEST CoreDev"
4 | output: rmarkdown::html_vignette
5 | vignette: >
6 | %\VignetteIndexEntry{Module Encapsulation}
7 | %\VignetteEngine{knitr::rmarkdown}
8 | %\VignetteEncoding{UTF-8}
9 | ---
10 |
11 | ## Introduction
12 |
13 | The `teal` framework leverages the [`shiny` module concept](https://rstudio.github.io/shiny/reference/moduleServer.html) to enable encapsulation of analytical actions in `teal` modules, while maintaining seamless communication between the modules and the application.
14 |
15 |
16 | ## Benefits
17 |
18 | By implementing the modular app technique from the `shiny` module into the creation of the `teal` module, several benefits are realized:
19 |
20 | 1. Streamlined maintenance
21 | The development of the `teal` module becomes more manageable, as it can function independently from the `teal` framework.
22 | This separation allows developers to maintain the module with ease. This approach has been successfully applied in `R` packages dedicated to `teal` module development, such as `teal.modules.general` and `teal.modules.clinical`.
23 |
24 | 1. Enhanced focus on output
25 | `teal` module developers can concentrate solely on refining parameters or encoding, and output aspects (such as data summarization and visualization) without the need to concern themselves with the intricacies of the `teal` framework.
26 | When developed correctly, the module seamlessly integrates with `teal`.
27 |
28 | 1. Facilitated collaboration
29 | `teal` module development becomes an accessible entry point for developers interested in collaborating.
30 | This approach encourages user collaboration for the improvement of `teal` modules, as developers gain a deeper understanding of the mechanics of the `teal` framework.
31 |
--------------------------------------------------------------------------------
/vignettes/blueprint/product_map.Rmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Product Map"
3 | author: "NEST CoreDev"
4 | output: rmarkdown::html_vignette
5 | vignette: >
6 | %\VignetteIndexEntry{Product Map}
7 | %\VignetteEngine{knitr::rmarkdown}
8 | %\VignetteEncoding{UTF-8}
9 | ---
10 |
11 | ```{r, child="_setup.Rmd"}
12 | ```
13 |
14 | ```{r, echo=FALSE}
15 | shiny::pre(
16 | class = "mermaid",
17 | "
18 | %% This is a mermaid diagram, if you see this the plot failed to render. Sorry.
19 | flowchart RL
20 | teal
21 | subgraph features
22 | direction LR
23 | teal.data
24 | teal.slice
25 | teal.code
26 | teal.logger
27 | teal.widgets
28 | end
29 | subgraph modules
30 | direction RL
31 | teal.modules.general
32 | teal.modules.clinical
33 | teal.osprey
34 | teal.goshawk
35 | teal.modules.hermes
36 | end
37 | teal--has-->features
38 | features--builds-->modules
39 | modules--creates-->teal
40 | subgraph modules
41 | teal.modules.general
42 | teal.modules.clinical
43 | teal.osprey
44 | teal.goshawk
45 | teal.modules.hermes
46 | end
47 | subgraph calculations
48 | direction RL
49 | tern
50 | osprey
51 | goshawk
52 | hermes
53 | end
54 | tern--supports-->teal.modules.clinical
55 | osprey--supports-->teal.osprey
56 | goshawk--supports-->teal.goshawk
57 | hermes--supports-->teal.modules.hermes
58 | style teal fill:lightblue
59 | style features fill:lightgreen
60 | style modules fill:pink
61 | "
62 | )
63 | ```
64 |
65 | `teal` is a modular framework that relies on a suite of related packages, as illustrated in the above diagram, to provide a wide range of functionalities.
66 |
67 | `teal`'s primary function is to create web app for analyzing clinical trial data but it **has** a multitude of features distributed across various packages.
68 |
69 | Developers can selectively leverage these packages, such as `teal.widgets`, `teal.code`, and `teal.logger`, to **build** `teal` modules for a `teal` app.
70 | This approach gives the developers the tools that speed up their work and avoid re-implementing existing logic and UI elements.
71 |
72 | The `teal` modules utilize various packages such as `tern`, `osprey`, and `goshawk` to perform calculations and analyses.
73 | These packages provide **support** to the `teal` modules by performing all computations while the modules only have to focus on how to wrap the input options and the output.
74 |
75 | Once developed, new and existing modules can be integrated into `teal` to **create** a functional `teal` app.
76 |
77 | ## Why so many packages?
78 |
79 | By breaking down `teal` features, modules, and calculations into dedicated packages, maintenance is made significantly more manageable.
80 |
--------------------------------------------------------------------------------
/vignettes/images/bs-corners.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/insightsengineering/teal/3d6b93310c969e0a6fecab41102846c94d99d4f1/vignettes/images/bs-corners.png
--------------------------------------------------------------------------------
/vignettes/images/bs-final.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/insightsengineering/teal/3d6b93310c969e0a6fecab41102846c94d99d4f1/vignettes/images/bs-final.png
--------------------------------------------------------------------------------
/vignettes/images/bs-font-size.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/insightsengineering/teal/3d6b93310c969e0a6fecab41102846c94d99d4f1/vignettes/images/bs-font-size.png
--------------------------------------------------------------------------------
/vignettes/images/bs-launch.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/insightsengineering/teal/3d6b93310c969e0a6fecab41102846c94d99d4f1/vignettes/images/bs-launch.png
--------------------------------------------------------------------------------
/vignettes/images/bs-theme-set.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/insightsengineering/teal/3d6b93310c969e0a6fecab41102846c94d99d4f1/vignettes/images/bs-theme-set.png
--------------------------------------------------------------------------------
/vignettes/images/custom_app.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/insightsengineering/teal/3d6b93310c969e0a6fecab41102846c94d99d4f1/vignettes/images/custom_app.png
--------------------------------------------------------------------------------
/vignettes/images/reporter.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/insightsengineering/teal/3d6b93310c969e0a6fecab41102846c94d99d4f1/vignettes/images/reporter.jpg
--------------------------------------------------------------------------------
/vignettes/images/show_code_prepro_missing.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/insightsengineering/teal/3d6b93310c969e0a6fecab41102846c94d99d4f1/vignettes/images/show_code_prepro_missing.png
--------------------------------------------------------------------------------
/vignettes/images/show_code_prepro_present.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/insightsengineering/teal/3d6b93310c969e0a6fecab41102846c94d99d4f1/vignettes/images/show_code_prepro_present.png
--------------------------------------------------------------------------------
/vignettes/teal-as-a-shiny-module.Rmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Teal as a Shiny Module"
3 | author: "NEST CoreDev"
4 | output:
5 | rmarkdown::html_vignette:
6 | toc: true
7 | vignette: >
8 | %\VignetteIndexEntry{Teal as a Shiny Module}
9 | %\VignetteEngine{knitr::rmarkdown}
10 | %\VignetteEncoding{UTF-8}
11 | ---
12 |
13 | ## Introduction
14 |
15 | A `shiny` developer can embed a `teal` application into their own `shiny` app by using `shiny` module components of `teal`: `ui_teal()` and `srv_teal()`.
16 | This approach differs from using `init()` and offers greater flexibility. While `init()` includes a session info footer automatically,
17 | when using `teal` as a `shiny` module you can optionally add it manually with `ui_session_info()` and `srv_session_info()`.
18 | Using `teal` as a `shiny` module offers several advantages:
19 |
20 | - Embedding one or more `teal` applications within a larger `shiny` app
21 | - Creating `teal` applications with dynamically generated components (initial data, modules, filters)
22 |
23 | ## Example
24 |
25 | The following example demonstrates embedding `teal` as a `shiny` module within a larger `shiny` application.
26 | Users can select dataset names which are passed to the embedded `teal` component.
27 | On the server side, `srv_teal()` is called with a reactive `teal_data` object passed from the parent app's server.
28 |
29 | ```{r setup, include=FALSE}
30 | library(teal)
31 | ```
32 | ```{r app}
33 | library(teal)
34 |
35 | data <- teal_data() |> within({
36 | iris <- iris
37 | mtcars <- mtcars
38 | df <- data.frame(a = 1:10, b = letters[1:10])
39 | })
40 |
41 | mods <- modules(
42 | example_module("mod1"),
43 | example_module("mod2")
44 | )
45 |
46 | ui_app <- fluidPage(
47 | title = "Your app with teal as a module",
48 | selectInput("datasets", "Select datasets", choices = c("iris", "mtcars", "df"), selected = "iris", multiple = TRUE),
49 | ui_teal("teal", mods),
50 | ui_session_info("session_info")
51 | )
52 |
53 | srv_app <- function(input, output, session) {
54 | data_subset <- reactive(data[input$datasets])
55 | srv_teal("teal", data = data_subset, modules = mods)
56 | srv_session_info("session_info")
57 | }
58 |
59 | if (interactive()) {
60 | shinyApp(ui_app, srv_app)
61 | }
62 | ```
63 |
64 | ```{r shinylive_iframe, echo = FALSE, out.width = '150%', out.extra = 'style = "position: relative; z-index:1"', eval = requireNamespace("roxy.shinylive", quietly = TRUE) && knitr::is_html_output() && identical(Sys.getenv("IN_PKGDOWN"), "true")}
65 | code <- paste0(c(
66 | "interactive <- function() TRUE",
67 | knitr::knit_code$get("app")
68 | ), collapse = "\n")
69 |
70 | url <- roxy.shinylive::create_shinylive_url(code)
71 | knitr::include_url(url, height = "800px")
72 | ```
73 |
--------------------------------------------------------------------------------