diff --git a/DESCRIPTION b/DESCRIPTION index 59fe3948e9..35244237a1 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -71,7 +71,9 @@ LazyData: true Roxygen: list(markdown = TRUE) RoxygenNote: 7.2.3 Collate: - 'ddl.R' + 'ddl-class.R' + 'ddl-modules.R' + 'ddl-run.R' 'dummy_functions.R' 'get_rcode_utils.R' 'include_css_js.R' diff --git a/R/ddl-class.R b/R/ddl-class.R new file mode 100644 index 0000000000..413c7cbc4d --- /dev/null +++ b/R/ddl-class.R @@ -0,0 +1,143 @@ +#' DDL object +#' +#' Object to execute custom DDL code in the shiny session. +#' +#' @section Creating reproducible data: +#' `ddl` object can be used to create reproducible data in the shiny session. `ddl$server` function +#' can execute any R code and return [`teal.data::teal_data-class`]. For reproducibility purposes, +#' we recommend to initialize empty `teal_data` object and evaluate necessary code with `eval_code` or `within`. +#' ```r +#' function(id, ...) { +#' moduleServer(id, function(input, output, session) { +#' eventReactive(input$submit, { +#' data <- teal_data() |> within({ +#' # code to be run when app user presses submit +#' }) +#' }) +#' }) +#' } +#' ``` +#' Obtained data is passed further in the `teal` app with `code` which can be used to recreate the objects. +#' +#' @section Code masking: +#' `ddl` object can be used in a way that evaluated code is different than the code +#' returned in `teal_data` object. Typically occurs when app user is asked to input a +#' password and we'd like to skip this input in the reproducible code. Possibly, users password +#' could be substituted with `askpass::askpass()` call, so the returned code is still executable but secure. +#' `ddl` developer must understand that this is a security risk and should be handled with care. +#' To make sure that the code is reproducible, `ddl` object should be used with `input_mask` argument. +#' `teal` provides convenience function [ddl_run()] which handles evaluation of the code, masking +#' and creating `teal_data` object. Such `server` function could look like this: +#' +#' ``` +#' server = function(id, ...) { +#' moduleServer(id, function(input, output, session) { +#' reactive({ +#' ddl_run(input = input, ...) +#' }) +#' }) +#' } +#' ``` +#' +#' If `ddl` developer values more control, then might be interested in using `...` explicitly, +#' and create `teal_data` object manually. +#' +#' @param ui (`shiny.tag`)\cr +#' `shiny` user-interface module containing inputs whose `id` correspond to the arguments in the `code`. +#' +#' @param server (`function`)\cr +#' `shiny` server module [`teal.data::teal_data-class`] possibly wrapped in a [reactive()]. +#' `server` function should have `id` and `...` as formals. Where: +#' - `id` is a `shiny` module id, and +#' - `...` passes arguments from the `ddl` object (`code`, `input_mask`, `datanames`, `join_keys`). +#' See section `Code masking`. +#' +#' @param expr (optional `expression`)\cr +#' Syntactically valid R expression to be executed in the shiny session. +#' Shouldn't be specified when `code` is specified. +#' +#' @param code (optional `character` or `language`)\cr +#' Object containing (defused) syntactically valid R expression to be executed in the shiny session. +#' Shouldn't be specified when `expr` is specified. +#' +#' @param input_mask (optional `named list`)\cr +#' arguments to be substituted in the `code`. These (named) list elements are going to replace +#' symbols in the code prefixed with `input$` or `input[["`. Typically `input_mask` is used +#' to mask username or password with `list(password = quote(askpass::askpass()))`. +#' See section `code masking` for more details. +#' +#' @param datanames (optional `character`)\cr +#' Names of the datasets created by evaluation of the `code`. By default, `datanames` +#' are obtained from the `join_keys` or from results of the `code` evaluation. +#' If `code` evaluation creates objects which are not considered as datasets, they +#' should be omitted from `datanames` to avoid errors. +#' +#' @inheritParams teal.data::teal_data +#' +#' @export +ddl <- function(expr, + code, + input_mask = list(), + ui = submit_button_ui, + server = submit_button_server, + join_keys = teal.data::join_keys(), + datanames = names(join_keys$get())) { + checkmate::assert_list(input_mask) + checkmate::check_function(ui, args = "id") + checkmate::check_function(server, args = c("id", "...")) + checkmate::check_class(join_keys, "JoinKeys") + checkmate::check_character(datanames, min.len = 1) + + out <- structure( + list(ui = ui, server = server), + input_mask = input_mask, + datanames = datanames, + join_keys = join_keys, + class = "ddl" + ) + + if (!missing(expr) || !missing(code)) { + # this is intended to be used with input mask + # but in the same time we can't forbid user to use it + # without input_mask. Some users might prefer to use ddl_run + # to automaticaly handle their code. + # Q: can NEST bear responsibility for reproducibility of the masked code? + if (!missing(expr)) { + code <- substitute(expr) + } + if (is.character(code)) { + code <- parse(text = code) + } + attr(out, "code") <- code + } + + out +} + +# methods from teal.data ---- +# to be removed soon + +#' Get data names from `ddl` +#' @rdname get_dataname +#' @param x (`ddl`) object +#' @export +get_dataname.ddl <- function(x) { + attr(x, "datanames") +} + +#' @rdname get_join_keys +#' @export +get_join_keys.ddl <- function(data) { + attr(data, "join_keys") +} + +# todo: to remove before merge ------------- +#' @export +open_conn <- function(username, password) { + if (password != "pass") stop("Invalid credentials. 'pass' is the password") else TRUE +} +#' @export +close_conn <- function(conn) { + message("closed") + return(NULL) +} diff --git a/R/ddl-modules.R b/R/ddl-modules.R new file mode 100644 index 0000000000..f402d75cba --- /dev/null +++ b/R/ddl-modules.R @@ -0,0 +1,59 @@ +#' Run code and mask inputs +#' +#' Delayed Data Loading module with login and password input. +#' +#' @name submit_button_module +#' +#' +#' @param id (`character`) `shiny` module id. +#' @param ... (`list`) arguments passed to `ddl_run` function. +#' @return `shiny` module +NULL + +#' @rdname submit_button_module +#' @export +submit_button_ui <- function(id) { + ns <- NS(id) + actionButton(inputId = ns("submit"), label = "Submit") +} + +#' @rdname submit_button_module +#' @export +submit_button_server <- function(id, ...) { + moduleServer(id, function(input, output, session) { + tdata <- eventReactive(input$submit, { + ddl_run(input = input, ...) + }) + + # would need to make sure we handle reactivity correctly here as teal::init expects not reactive teal_data... + return(tdata) + }) +} + +#' Wrapper for `ui` and `server` in `ddl` object +#' +#' Convenience wrapper for `ui` and `server` functions in `ddl` object. +#' On the `server` side, function calls `shiny` module and adjusts the arguments +#' to the formals of the `server` function. +#' @param id (`character`) `shiny` module id. +#' @param x (`ddl`) object. +#' @name ddl_module +#' @return `shiny` module +#' @keywords internal +NULL + +#' @rdname ddl_module +#' @keywords internal +ddl_server <- function(id, x) { + # subset attributes to only those that are arguments of the server function + args <- names(formals(x$server)) + attrs <- attributes(x) + attrs <- attrs[setdiff(names(attrs), c("id", "class", "names"))] + do.call(x$server, c(list(id = id), attrs)) +} + +#' @rdname ddl_module +#' @keywords internal +ddl_ui <- function(id, x) { + x$ui(id = id) +} diff --git a/R/ddl-run.R b/R/ddl-run.R new file mode 100644 index 0000000000..bd792c97d8 --- /dev/null +++ b/R/ddl-run.R @@ -0,0 +1,77 @@ +#' Run code and mask inputs +#' +#' Function runs the `code`, masks the `code` and creates `teal_data` object. +#' @param input (`list`) containing inputs to be used in the `code` +#' @param code (`language`) code to be executed +#' @param input_mask (`list`) containing inputs to be masked in the `code` +#' @param datanames (`character`) names of the objects to be created from the code evaluation +#' @param join_keys (`join_keys`) object +#' +#' @return `teal_data` object +#' +#' @export +ddl_run <- function(input = list(), + code, + input_mask = list(), + join_keys = teal.data::join_keys(), + datanames = names(join_keys$get())) { + checkmate::assert_list(input) + if (inherits(input, "reactivevalues")) { + input <- shiny::reactiveValuesToList(input) + } + data <- teal_data(join_keys = join_keys) + + # evaluate code and substitute input + data <- teal.code::eval_code(data, .substitute_inputs(code, args = input)) + + if (identical(ls(data@env), character(0))) { + warning( + "Evaluation of `ddl` code haven't created any objects.\n", + "Please make sure that the code is syntactically correct and creates necessary data." + ) + } + + if (!missing(input_mask)) { + # mask dynamic inputs with mask + input <- utils::modifyList(input, input_mask) + + # replace code of teal_data with masked code + # question: warnings and errors are not masked, is it ok? + data@code <- format_expression(.substitute_inputs(code, args = input)) + } + + if (length(datanames)) { + datanames(data) <- datanames + } + if (length(datanames(data)) == 0) { + datanames(data) <- ls(data@env) + } + + data +} + +#' substitute inputs in the code +#' +#' Function replaces symbols in the provided code prefixed with `input$` or `input[["` +#' by values of the `args` argument. +#' +#' @param code (`language`) code to substitute +#' @param args (`list`) named list or arguments +.substitute_inputs <- function(code, args) { + code <- if (identical(as.list(code)[[1L]], as.symbol("{"))) { + as.list(code)[-1L] + } else { + code + } + + code_strings <- vapply(code, deparse1, character(1L)) + code_strings <- gsub("(input\\$)(\\w+)", "\\.(\\2\\)", code_strings) + code_strings <- gsub("(input\\[\\[\")(\\w+)(\"\\]\\])", "\\.(\\2\\)", code_strings) + + # Use bquote to obtain code with input values and masking values. + as.expression( + lapply(code_strings, function(x) { + do.call(bquote, list(str2lang(x), list2env(args))) + }) + ) +} diff --git a/R/ddl.R b/R/ddl.R deleted file mode 100644 index f96be97495..0000000000 --- a/R/ddl.R +++ /dev/null @@ -1,226 +0,0 @@ -#' DDL object -#' -#' Object to execute custom DDL code in the shiny session -#' -#' @param expr (`expression`)\cr -#' Syntatically valid R code to be executed in the shiny session. -#' shouldn't be specified when `code` is specified. -#' -#' @param code (`character`, `language`)\cr -#' Object containing code to be evaluated to load data. Shouldn't be specified when `expr` -#' is specified. -#' -#' -#' @param ui (`shiny.tag`)\cr -#' `shiny` ui module containing inputs which `id` correspond to the -#' args in the `code`. -#' -#' @param server (`function`)\cr -#' `shiny` server module returning data. This server should execute -#' `code` and return a reactive data containing necessary data. To handle -#' evaluation and code masking process it is recommended to use `ddl_run`. -#' Package provides universal `username_password_server` which -#' runs `ddl_run` function, which returns `teal_data` object. -#' Details in the the example -#' - `code` (`character`, `language`) code to be executed and returned in `teal_data` object. -#' - `input_mask` (`list` named) arguments to be substituted in the `code`. -#' - `datanames` (`character`) names of the objects to be created from the code evaluation. -#' - `join_keys` (`JoinKeys`) object -#' `...` can be handled automatically by [ddl_run()] but -#' -#' @param input_mask (`list` named)\cr -#' arguments to be substituted in the `code`. These -#' argument are going to replace arguments set through -#' `ui` and `server`. Example use case is when app user -#' is asked to input a password and we'd like to skip this -#' input in the reproducible code. Typically users password -#' is substituted with `askpass::askpass()` call, so the -#' returned code is still executable but secure. -#' -#' @param datanames (`character`)\cr -#' Names of the objects to be created from the code evaluation. -#' If not specified (`character(0)`), all objects will be used to `teal_data` function -#' (via `env_list` in `postprocess_fun`). -#' -#' @inheritParams teal.data::teal_data -#' -#' -#' @export -ddl <- function(expr, - code = character(0), - ui = submit_button_ui, - input_mask = list(), - server = submit_button_server, - join_keys = teal.data::join_keys(), - datanames = names(join_keys$get())) { - if (!missing(expr)) { - code <- substitute(expr) - } - if (is.character(code)) { - code <- parse(text = code) - } - checkmate::assert_list(input_mask) - checkmate::check_function(ui, args = "id") - checkmate::check_function(server, args = c("id", "...")) - checkmate::check_class(join_keys, "JoinKeys") - checkmate::check_character(datanames, min.len = 1) - - ddl_object <- structure( - list(ui = ui, server = server), - code = code, - input_mask = input_mask, - datanames = datanames, - join_keys = join_keys, - class = "ddl" - ) - - ddl_object -} - -#' @name ddl_module -#' @keywords internal -NULL - -#' @rdname ddl_module -#' @keywords internal -ddl_server <- function(id, x) { - attrs <- attributes(x) - do.call( - x$server, - c( - list(id = id), - attrs[setdiff(names(attrs), c("class", "names"))] - ) - ) -} - -#' @rdname ddl_module -#' @keywords internal -ddl_ui <- function(id, x) { - x$ui(id = id) -} - -#' Run code and mask inputs -#' -#' Delayed Data Loading module with login and password input. -#' -#' @name submit_button_module -#' -#' -#' @param id (`character`) `shiny` module id. -#' @param ... (`list`) arguments passed to `ddl_run` function. -#' @return `shiny` module -NULL - -#' @rdname submit_button_module -#' @export -submit_button_ui <- function(id) { - ns <- NS(id) - actionButton(inputId = ns("submit"), label = "Submit") -} - -#' @rdname submit_button_module -#' @export -submit_button_server <- function(id, ...) { - moduleServer(id, function(input, output, session) { - tdata <- eventReactive(input$submit, { - ddl_run(input = input, ...) - }) - - # would need to make sure we handle reactivity correctly here as teal::init expects not reactive teal_data... - return(tdata) - }) -} - -#' substitute inputs in the code -#' -#' Function replaces symbols in the provided code prefixed with `input$` or `input[["` -#' by values of the `args` argument. -#' -#' @param code (`language`) code to substitute -#' @param args (`list`) named list or arguments -.substitute_inputs <- function(code, args) { - code <- if (identical(as.list(code)[[1L]], as.symbol("{"))) { - as.list(code)[-1L] - } else { - code - } - - code_strings <- vapply(code, deparse1, character(1L)) - code_strings <- gsub("(input\\$)(\\w+)", "\\.(\\2\\)", code_strings) - code_strings <- gsub("(input\\[\\[\")(\\w+)(\"\\]\\])", "\\.(\\2\\)", code_strings) - - # Use bquote to obtain code with input values and masking values. - as.expression( - lapply(code_strings, function(x) { - do.call(bquote, list(str2lang(x), list2env(args))) - }) - ) -} - -# todo: to remove ------------- -#' @export -open_conn <- function(username, password) { - if (password != "pass") stop("Invalid credentials. 'pass' is the password") else TRUE -} -#' @export -close_conn <- function(conn) { - message("closed") - return(NULL) -} - - -# methods from teal.data - -#' Get datanames from `ddl` -#' @rdname get_dataname -#' @param x (`ddl`) object -#' @export -get_dataname.ddl <- function(x) { - attr(x, "datanames") -} - -#' @rdname get_join_keys -#' @export -get_join_keys.ddl <- function(data) { - attr(data, "join_keys") -} - -#' Run code and mask inputs -#' -#' Function runs the `code`, masks the `code` and creates `teal_data` object. -#' @param input (`list`) containing inputs to be used in the `code` -#' @param code (`language`) code to be executed -#' @param input_mask (`list`) containing inputs to be masked in the `code` -#' @param datanames (`character`) names of the objects to be created from the code evaluation -#' @param join_keys (`join_keys`) object -#' -#' @return `teal_data` object -#' -#' @export -ddl_run <- function(input = list(), code, input_mask, datanames, join_keys) { - checkmate::assert_list(input) - if (inherits(input, "reactivevalues")) { - input <- shiny::reactiveValuesToList(input) - } - data <- teal_data(join_keys = join_keys) - - # evaluate code and substitute input - data <- teal.code::eval_code(data, .substitute_inputs(code, args = input)) - - if (identical(ls(data@env), character(0))) { - warning("DDL code returned NULL. Returning empty object") - } - - if (length(input_mask) > 0) { - # mask dynamic inputs with mask - input <- utils::modifyList(input, input_mask) - - # replace code of teal_data with masked code - # question: warnings and errors are not masked, is it ok? - data@code <- format_expression(.substitute_inputs(code, args = input)) - } - datanames(data) <- datanames - - data -} diff --git a/man/ddl.Rd b/man/ddl.Rd index 5cd1c214b5..8aed6f1343 100644 --- a/man/ddl.Rd +++ b/man/ddl.Rd @@ -1,65 +1,100 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/ddl.R +% Please edit documentation in R/ddl-class.R \name{ddl} \alias{ddl} \title{DDL object} \usage{ ddl( expr, - code = character(0), - ui = submit_button_ui, + code, input_mask = list(), + ui = submit_button_ui, server = submit_button_server, join_keys = teal.data::join_keys(), datanames = names(join_keys$get()) ) } \arguments{ -\item{expr}{(\code{expression})\cr -Syntatically valid R code to be executed in the shiny session. -shouldn't be specified when \code{code} is specified.} +\item{expr}{(optional \code{expression})\cr +Syntactically valid R expression to be executed in the shiny session. +Shouldn't be specified when \code{code} is specified.} -\item{code}{(\code{character}, \code{language})\cr -Object containing code to be evaluated to load data. Shouldn't be specified when \code{expr} -is specified.} +\item{code}{(optional \code{character} or \code{language})\cr +Object containing (defused) syntactically valid R expression to be executed in the shiny session. +Shouldn't be specified when \code{expr} is specified.} -\item{ui}{(\code{shiny.tag})\cr -\code{shiny} ui module containing inputs which \code{id} correspond to the -args in the \code{code}.} +\item{input_mask}{(optional \verb{named list})\cr +arguments to be substituted in the \code{code}. These (named) list elements are going to replace +symbols in the code prefixed with \verb{input$} or \verb{input[["}. Typically \code{input_mask} is used +to mask username or password with \code{list(password = quote(askpass::askpass()))}. +See section \verb{code masking} for more details.} -\item{input_mask}{(\code{list} named)\cr -arguments to be substituted in the \code{code}. These -argument are going to replace arguments set through -\code{ui} and \code{server}. Example use case is when app user -is asked to input a password and we'd like to skip this -input in the reproducible code. Typically users password -is substituted with \code{askpass::askpass()} call, so the -returned code is still executable but secure.} +\item{ui}{(\code{shiny.tag})\cr +\code{shiny} user-interface module containing inputs whose \code{id} correspond to the arguments in the \code{code}.} \item{server}{(\code{function})\cr -\code{shiny} server module returning data. This server should execute -\code{code} and return a reactive data containing necessary data. To handle -evaluation and code masking process it is recommended to use \code{ddl_run}. -Package provides universal \code{username_password_server} which -runs \code{ddl_run} function, which returns \code{teal_data} object. -Details in the the example +\code{shiny} server module \code{\link[teal.data:teal_data-class]{teal.data::teal_data}} possibly wrapped in a \code{\link[=reactive]{reactive()}}. +\code{server} function should have \code{id} and \code{...} as formals. Where: \itemize{ -\item \code{code} (\code{character}, \code{language}) code to be executed and returned in \code{teal_data} object. -\item \code{input_mask} (\code{list} named) arguments to be substituted in the \code{code}. -\item \code{datanames} (\code{character}) names of the objects to be created from the code evaluation. -\item \code{join_keys} (\code{JoinKeys}) object -\code{...} can be handled automatically by \code{\link[=ddl_run]{ddl_run()}} but +\item \code{id} is a \code{shiny} module id, and +\item \code{...} passes arguments from the \code{ddl} object (\code{code}, \code{input_mask}, \code{datanames}, \code{join_keys}). +See section \verb{Code masking}. }} \item{join_keys}{(\code{JoinKeys}) or a single (\code{JoinKeySet})\cr (optional) object with dataset column relationships used for joining. If empty then no joins between pairs of objects} -\item{datanames}{(\code{character})\cr -Names of the objects to be created from the code evaluation. -If not specified (\code{character(0)}), all objects will be used to \code{teal_data} function -(via \code{env_list} in \code{postprocess_fun}).} +\item{datanames}{(optional \code{character})\cr +Names of the datasets created by evaluation of the \code{code}. By default, \code{datanames} +are obtained from the \code{join_keys} or from results of the \code{code} evaluation. +If \code{code} evaluation creates objects which are not considered as datasets, they +should be omitted from \code{datanames} to avoid errors.} } \description{ -Object to execute custom DDL code in the shiny session +Object to execute custom DDL code in the shiny session. +} +\section{Creating reproducible data}{ + +\code{ddl} object can be used to create reproducible data in the shiny session. \code{ddl$server} function +can execute any R code and return \code{\link[teal.data:teal_data-class]{teal.data::teal_data}}. For reproducibility purposes, +we recommend to initialize empty \code{teal_data} object and evaluate necessary code with \code{eval_code} or \code{within}. + +\if{html}{\out{
}}\preformatted{function(id, ...) \{ + moduleServer(id, function(input, output, session) \{ + eventReactive(input$submit, \{ + data <- teal_data() |> within(\{ + # code to be run when app user presses submit + \}) + \}) + \}) +\} +}\if{html}{\out{
}} + +Obtained data is passed further in the \code{teal} app with \code{code} which can be used to recreate the objects. } + +\section{Code masking}{ + +\code{ddl} object can be used in a way that evaluated code is different than the code +returned in \code{teal_data} object. Typically occurs when app user is asked to input a +password and we'd like to skip this input in the reproducible code. Possibly, users password +could be substituted with \code{askpass::askpass()} call, so the returned code is still executable but secure. +\code{ddl} developer must understand that this is a security risk and should be handled with care. +To make sure that the code is reproducible, \code{ddl} object should be used with \code{input_mask} argument. +\code{teal} provides convenience function \code{\link[=ddl_run]{ddl_run()}} which handles evaluation of the code, masking +and creating \code{teal_data} object. Such \code{server} function could look like this: + +\if{html}{\out{
}}\preformatted{server = function(id, ...) \{ + moduleServer(id, function(input, output, session) \{ + reactive(\{ + ddl_run(input = input, ...) + \}) + \}) +\} +}\if{html}{\out{
}} + +If \code{ddl} developer values more control, then might be interested in using \code{...} explicitly, +and create \code{teal_data} object manually. +} + diff --git a/man/ddl_module.Rd b/man/ddl_module.Rd new file mode 100644 index 0000000000..38b5146b1e --- /dev/null +++ b/man/ddl_module.Rd @@ -0,0 +1,26 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/ddl-modules.R +\name{ddl_module} +\alias{ddl_module} +\alias{ddl_server} +\alias{ddl_ui} +\title{Wrapper for \code{ui} and \code{server} in \code{ddl} object} +\usage{ +ddl_server(id, x) + +ddl_ui(id, x) +} +\arguments{ +\item{id}{(\code{character}) \code{shiny} module id.} + +\item{x}{(\code{ddl}) object.} +} +\value{ +\code{shiny} module +} +\description{ +Convenience wrapper for \code{ui} and \code{server} functions in \code{ddl} object. +On the \code{server} side, function calls \code{shiny} module and adjusts the arguments +to the formals of the \code{server} function. +} +\keyword{internal} diff --git a/man/ddl_run.Rd b/man/ddl_run.Rd index 871cd64c7a..1af450aa7e 100644 --- a/man/ddl_run.Rd +++ b/man/ddl_run.Rd @@ -1,10 +1,16 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/ddl.R +% Please edit documentation in R/ddl-run.R \name{ddl_run} \alias{ddl_run} \title{Run code and mask inputs} \usage{ -ddl_run(input = list(), code, input_mask, datanames, join_keys) +ddl_run( + input = list(), + code, + input_mask = list(), + join_keys = teal.data::join_keys(), + datanames = names(join_keys$get()) +) } \arguments{ \item{input}{(\code{list}) containing inputs to be used in the \code{code}} @@ -13,9 +19,9 @@ ddl_run(input = list(), code, input_mask, datanames, join_keys) \item{input_mask}{(\code{list}) containing inputs to be masked in the \code{code}} -\item{datanames}{(\code{character}) names of the objects to be created from the code evaluation} - \item{join_keys}{(\code{join_keys}) object} + +\item{datanames}{(\code{character}) names of the objects to be created from the code evaluation} } \value{ \code{teal_data} object diff --git a/man/dot-substitute_inputs.Rd b/man/dot-substitute_inputs.Rd index 3848f4a392..2c97db3062 100644 --- a/man/dot-substitute_inputs.Rd +++ b/man/dot-substitute_inputs.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/ddl.R +% Please edit documentation in R/ddl-run.R \name{.substitute_inputs} \alias{.substitute_inputs} \title{substitute inputs in the code} diff --git a/man/get_dataname.Rd b/man/get_dataname.Rd index 30370cabb9..2f19bc3fb0 100644 --- a/man/get_dataname.Rd +++ b/man/get_dataname.Rd @@ -1,8 +1,8 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/ddl.R +% Please edit documentation in R/ddl-class.R \name{get_dataname.ddl} \alias{get_dataname.ddl} -\title{Get datanames from \code{ddl}} +\title{Get data names from \code{ddl}} \usage{ \method{get_dataname}{ddl}(x) } @@ -10,5 +10,5 @@ \item{x}{(\code{ddl}) object} } \description{ -Get datanames from \code{ddl} +Get data names from \code{ddl} } diff --git a/man/get_join_keys.Rd b/man/get_join_keys.Rd index 709499e4a3..1ba0e8b858 100644 --- a/man/get_join_keys.Rd +++ b/man/get_join_keys.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/ddl.R, R/tdata.R +% Please edit documentation in R/ddl-class.R, R/tdata.R \name{get_join_keys.ddl} \alias{get_join_keys.ddl} \alias{get_join_keys.tdata} diff --git a/man/submit_button_module.Rd b/man/submit_button_module.Rd index a858017ba5..8add2ddcd8 100644 --- a/man/submit_button_module.Rd +++ b/man/submit_button_module.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/ddl.R +% Please edit documentation in R/ddl-modules.R \name{submit_button_module} \alias{submit_button_module} \alias{submit_button_ui}