Skip to content

Commit

Permalink
Merge 4ec979b into d0e0dc3
Browse files Browse the repository at this point in the history
  • Loading branch information
gogonzo committed Mar 7, 2023
2 parents d0e0dc3 + 4ec979b commit d218074
Show file tree
Hide file tree
Showing 83 changed files with 5,787 additions and 5,316 deletions.
4 changes: 3 additions & 1 deletion NEWS.md
Expand Up @@ -18,12 +18,14 @@

* Fixed an error where the `RangeFilterState` produced an error when using `bootstrap 4`.
* Fixed a bug that caused the range slider to omit values selected programmatically through the filter API.
* Fixed a bug where setting incorrect values for Date and Date time ranges caused the app to crash.

### Miscellaneous

* Calculation of step in slider for `RangeFilterState` now uses `checkmate::test_integerish` instead of `is.integer`.
* Updated `init_filtered_data` to take into account the removal of `CDISCTealData` from `teal.data` package.
* Added examples apps for `ChoicesFilterState` and `DFFilterStates`.
* Added `shinyvalidate` validation for Date and Date time ranges.
* Added examples apps for `FilterState` child classes and `DFFilterStates`.

# teal.slice 0.2.0

Expand Down
6 changes: 3 additions & 3 deletions R/FilterPanelAPI.R
Expand Up @@ -32,7 +32,7 @@
#' isolate(fpa$get_filter_state())
#'
#' # remove all_filter_states
#' fpa$remove_all_filter_states()
#' fpa$clear_filter_states()
#'
#' # get the actual filter state --> empty named list
#' isolate(fpa$get_filter_state())
Expand Down Expand Up @@ -98,10 +98,10 @@ FilterPanelAPI <- R6::R6Class( # nolint
#'
#' @return `NULL`
#'
remove_all_filter_states = function(datanames) {
clear_filter_states = function(datanames) {
if (private$filtered_data$get_filter_panel_active()) {
datanames_to_remove <- if (missing(datanames)) private$filtered_data$datanames() else datanames
private$filtered_data$remove_all_filter_states(datanames = datanames_to_remove)
private$filtered_data$clear_filter_states(datanames = datanames_to_remove)
} else {
warning(private$deactivated_msg)
}
Expand Down
70 changes: 70 additions & 0 deletions R/FilterState-abstract.R
@@ -0,0 +1,70 @@
#' @name FilterState
#' @docType class
#'
#'
#' @title FilterState Abstract Class
#'
#' @description Abstract class to encapsulate filter states
#'
#' @details
#' This abstract class to encapsulate [InteractiveFilterState]
#' @keywords internal
FilterState <- R6::R6Class( # nolint
"FilterState",

# public methods ----
public = list(
#' @description
#' Initialize a `FilterState` object
#' @param x (`vector`)\cr
#' values of the variable used in filter
#' @param varname (`character`)\cr
#' name of the variable
#' @param varlabel (`character(1)`)\cr
#' label of the variable (optional).
#' @param dataname (`character(1)`)\cr
#' name of dataset where `x` is taken from.
#' @param extract_type (`character(0)`, `character(1)`)\cr
#' whether condition calls should be prefixed by dataname. Possible values:
#' \itemize{
#' \item{`character(0)` (default)}{ `varname` in the condition call will not be prefixed}
#' \item{`"list"`}{ `varname` in the condition call will be returned as `<dataname>$<varname>`}
#' \item{`"matrix"`}{ `varname` in the condition call will be returned as `<dataname>[, <varname>]`}
#' }
#'
#' @return self invisibly
#'
initialize = function(x,
varname,
varlabel = character(0),
dataname = NULL,
extract_type = character(0)) {
checkmate::assert_string(varname)
checkmate::assert_character(varlabel, max.len = 1, any.missing = FALSE)
checkmate::assert_string(dataname, null.ok = TRUE)

private$dataname <- dataname
private$varname <- varname
private$varlabel <- if (identical(varlabel, as.character(varname))) {
# to not display duplicated label
character(0)
} else {
varlabel
}
invisible(self)
},

#' @description
#' Returns reproducible condition call
#'
get_call = function() {
NULL
}
),
# private members ----
private = list(
dataname = character(0),
varname = character(0),
varlabel = character(0)
)
)
60 changes: 44 additions & 16 deletions R/FilterState-utils.R
@@ -1,9 +1,15 @@
#' Initializes `FilterState`
#' Initializes `InteractiveFilterState`
#'
#' Initializes `FilterState` depending on a variable class.\cr
#' Initializes `InteractiveFilterState` depending on a variable class.\cr
#' @param x (`vector`)\cr
#' values of the variable used in filter
#'
#' @param x_reactive (`reactive`)\cr
#' returning vector of the same type as `x`. Is used to update
#' counts following the change in values of the filtered dataset.
#' If it is set to `reactive(NULL)` then counts based on filtered
#' dataset are not shown.
#'
#' @param varname (`character(1)`)\cr
#' name of the variable.
#'
Expand All @@ -25,7 +31,8 @@
#'
#' @examples
#' filter_state <- teal.slice:::RangeFilterState$new(
#' c(1:10, NA, Inf),
#' x = c(1:10, NA, Inf),
#' x_reactive = reactive(c(1:10, NA, Inf)),
#' varname = "x",
#' varlabel = "Pretty name",
#' dataname = "dataname",
Expand All @@ -52,6 +59,7 @@
#' }
#' @return `FilterState` object
init_filter_state <- function(x,
x_reactive = reactive(NULL),
varname,
varlabel = attr(x, "label"),
dataname = NULL,
Expand All @@ -73,6 +81,7 @@ init_filter_state <- function(x,
return(
EmptyFilterState$new(
x = x,
x_reactive = x_reactive,
varname = varname,
varlabel = varlabel,
dataname = dataname,
Expand All @@ -86,13 +95,15 @@ init_filter_state <- function(x,
#' @keywords internal
#' @export
init_filter_state.default <- function(x,
x_reactive = reactive(NULL),
varname,
varlabel = attr(x, "label"),
dataname = NULL,
extract_type = character(0)) {
if (is.null(varlabel)) varlabel <- character(0)
FilterState$new(
InteractiveFilterState$new(
x = x,
x_reactive = x_reactive,
varname = varname,
varlabel = varlabel,
dataname = dataname,
Expand All @@ -103,13 +114,15 @@ init_filter_state.default <- function(x,
#' @keywords internal
#' @export
init_filter_state.logical <- function(x,
x_reactive = reactive(NULL),
varname,
varlabel = attr(x, "label"),
dataname = NULL,
extract_type = character(0)) {
if (is.null(varlabel)) varlabel <- character(0)
LogicalFilterState$new(
x = x,
x_reactive = x_reactive,
varname = varname,
varlabel = varlabel,
dataname = dataname,
Expand All @@ -120,6 +133,7 @@ init_filter_state.logical <- function(x,
#' @keywords internal
#' @export
init_filter_state.numeric <- function(x,
x_reactive = reactive(NULL),
varname,
varlabel = attr(x, "label"),
dataname = NULL,
Expand All @@ -128,6 +142,7 @@ init_filter_state.numeric <- function(x,
if (length(unique(x[!is.na(x)])) < getOption("teal.threshold_slider_vs_checkboxgroup")) {
ChoicesFilterState$new(
x = x,
x_reactive = x_reactive,
varname = varname,
varlabel = varlabel,
dataname = dataname,
Expand All @@ -136,6 +151,7 @@ init_filter_state.numeric <- function(x,
} else {
RangeFilterState$new(
x = x,
x_reactive = x_reactive,
varname = varname,
varlabel = varlabel,
dataname = dataname,
Expand All @@ -147,13 +163,15 @@ init_filter_state.numeric <- function(x,
#' @keywords internal
#' @export
init_filter_state.factor <- function(x,
x_reactive = reactive(NULL),
varname,
varlabel = attr(x, "label"),
dataname = NULL,
extract_type = character(0)) {
if (is.null(varlabel)) varlabel <- character(0)
ChoicesFilterState$new(
x = x,
x_reactive = x_reactive,
varname = varname,
varlabel = varlabel,
dataname = dataname,
Expand All @@ -164,13 +182,15 @@ init_filter_state.factor <- function(x,
#' @keywords internal
#' @export
init_filter_state.character <- function(x,
x_reactive = reactive(NULL),
varname,
varlabel = attr(x, "label"),
dataname = NULL,
extract_type = character(0)) {
if (is.null(varlabel)) varlabel <- character(0)
ChoicesFilterState$new(
x = x,
x_reactive = x_reactive,
varname = varname,
varlabel = varlabel,
dataname = dataname,
Expand All @@ -181,6 +201,7 @@ init_filter_state.character <- function(x,
#' @keywords internal
#' @export
init_filter_state.Date <- function(x,
x_reactive = reactive(NULL),
varname,
varlabel = attr(x, "label"),
dataname = NULL,
Expand All @@ -189,6 +210,7 @@ init_filter_state.Date <- function(x,
if (length(unique(x[!is.na(x)])) < getOption("teal.threshold_slider_vs_checkboxgroup")) {
ChoicesFilterState$new(
x = x,
x_reactive = x_reactive,
varname = varname,
varlabel = varlabel,
dataname = dataname,
Expand All @@ -197,6 +219,7 @@ init_filter_state.Date <- function(x,
} else {
DateFilterState$new(
x = x,
x_reactive = x_reactive,
varname = varname,
varlabel = varlabel,
dataname = dataname,
Expand All @@ -208,6 +231,7 @@ init_filter_state.Date <- function(x,
#' @keywords internal
#' @export
init_filter_state.POSIXct <- function(x,
x_reactive = reactive(NULL),
varname,
varlabel = attr(x, "label"),
dataname = NULL,
Expand All @@ -216,6 +240,7 @@ init_filter_state.POSIXct <- function(x,
if (length(unique(x[!is.na(x)])) < getOption("teal.threshold_slider_vs_checkboxgroup")) {
ChoicesFilterState$new(
x = x,
x_reactive = x_reactive,
varname = varname,
varlabel = varlabel,
dataname = dataname,
Expand All @@ -224,6 +249,7 @@ init_filter_state.POSIXct <- function(x,
} else {
DatetimeFilterState$new(
x = x,
x_reactive = x_reactive,
varname = varname,
varlabel = varlabel,
dataname = dataname,
Expand All @@ -235,6 +261,7 @@ init_filter_state.POSIXct <- function(x,
#' @keywords internal
#' @export
init_filter_state.POSIXlt <- function(x,
x_reactive = reactive(NULL),
varname,
varlabel = attr(x, "label"),
dataname = NULL,
Expand All @@ -243,6 +270,7 @@ init_filter_state.POSIXlt <- function(x,
if (length(unique(x[!is.na(x)])) < getOption("teal.threshold_slider_vs_checkboxgroup")) {
ChoicesFilterState$new(
x = x,
x_reactive = x_reactive,
varname = varname,
varlabel = varlabel,
dataname = dataname,
Expand All @@ -251,6 +279,7 @@ init_filter_state.POSIXlt <- function(x,
} else {
DatetimeFilterState$new(
x = x,
x_reactive = x_reactive,
varname = varname,
varlabel = varlabel,
dataname = dataname,
Expand All @@ -270,9 +299,9 @@ init_filter_state.POSIXlt <- function(x,
#'
#' @examples
#' \dontrun{
#' check_in_range(c(3, 1), c(1, 3))
#' check_in_range(c(0, 3), c(1, 3))
#' check_in_range(
#' teal.slice:::check_in_range(c(3, 1), c(1, 3))
#' teal.slice:::check_in_range(c(0, 3), c(1, 3))
#' teal.slice:::check_in_range(
#' c(as.Date("2020-01-01"), as.Date("2020-01-20")),
#' c(as.Date("2020-01-01"), as.Date("2020-01-02"))
#' )
Expand Down Expand Up @@ -317,13 +346,12 @@ check_in_range <- function(subinterval, range, pre_msg = "") {
#' @keywords internal
#'
#' @examples
#' \donttest{
#' teal.slice:::check_in_subset(c("a", "b"), c("a", "b", "c"))
#' \dontrun{
#' check_in_subset <- check_in_subset
#' check_in_subset(c("a", "b"), c("a", "b", "c"))
#' \dontrun{
#' check_in_subset(c("a", "b"), c("b", "c"), pre_msg = "Error: ")
#' teal.slice:::check_in_subset(c("a", "b"), c("b", "c"), pre_msg = "Error: ")
#' # truncated because too long
#' check_in_subset("a", LETTERS, pre_msg = "Error: ")
#' teal.slice:::check_in_subset("a", LETTERS, pre_msg = "Error: ")
#' }
#' }
check_in_subset <- function(subset, choices, pre_msg = "") {
Expand Down Expand Up @@ -368,14 +396,14 @@ check_in_subset <- function(subset, choices, pre_msg = "") {
#' @keywords internal
#'
#' @examples
#' \dontrun{
#' \donttest{
#' ticks <- 1:10
#' values1 <- c(3, 5)
#' contain_interval(values1, ticks)
#' teal.slice:::contain_interval(values1, ticks)
#' values2 <- c(3.1, 5.7)
#' contain_interval(values2, ticks)
#' teal.slice:::contain_interval(values2, ticks)
#' values3 <- c(0, 20)
#' contain_interval(values3, ticks)
#' teal.slice:::contain_interval(values3, ticks)
#'}
contain_interval <- function(x, range) {
checkmate::assert_numeric(x, len = 2L, any.missing = FALSE, sorted = TRUE)
Expand Down

0 comments on commit d218074

Please sign in to comment.