diff --git a/.Rbuildignore b/.Rbuildignore index e088807..bab6a08 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -1,3 +1,5 @@ +^renv$ +^renv\.lock$ ^LICENSE\.md$ ^\.lintr ^docs/ @@ -8,4 +10,4 @@ ^docs$ ^pkgdown$ ^\.github$ -^_HEXAGON_DESIGN_CONTEST\.md$ \ No newline at end of file +^_HEXAGON_DESIGN_CONTEST\.md$ diff --git a/R/BlockConditions.R b/R/BlockConditions.R index 0acc047..0a0d0f9 100644 --- a/R/BlockConditions.R +++ b/R/BlockConditions.R @@ -14,7 +14,7 @@ setClass("BlockConditions", slots = list(conditions = "list")) #' #' @param object A `BlockConditions` object. #' @param variable A character string specifying the variable/column name. -#' @param operator A character string specifying the operator (e.g., "==", "!=", "<", ">", "<=", ">="). +#' @param operator A character string specifying the operator (e.g., "==", "!=", "<", ">", "<=", ">=", "%in%", "!%in%"). #' @param value The value to compare against. #' #' @return An updated `BlockConditions` object with the new condition added. @@ -46,10 +46,17 @@ setMethod("get_str_expression", "BlockConditions", function(object, dataname, da var <- cond$variable val <- if (is.numeric(data()[[dataname]][[cond$variable]])) { cond$value + } else if (isTRUE(cond$operator == "%in%" || cond$operator == "!%in%")) { + quoted_vals <- paste0(sprintf("'%s'", cond$value), collapse = ", ") + sprintf("c(%s)", quoted_vals) } else { - paste0("'", cond$value, "'") + sprintf("'%s'", cond$value) + } + if (cond$operator == "!%in%") { + sprintf("!(%s %%in%% %s)", var, val) + } else { + sprintf("%s %s %s", var, cond$operator, val) } - paste0(var, " ", cond$operator, " ", val) }) - paste0("(", paste(conds, collapse = " & "), ")") + sprintf("(%s)", paste(conds, collapse = " & ")) }) diff --git a/R/or_filtering_transformator.R b/R/or_filtering_transformator.R index d787428..fb68f5b 100644 --- a/R/or_filtering_transformator.R +++ b/R/or_filtering_transformator.R @@ -18,7 +18,7 @@ #' #' - **Supported Data Types & Expressions:** #' - Supports filtering on \code{character}, \code{factor}, and \code{numeric} columns. -#' - Conditions can use operators: \code{==}, \code{!=}, \code{<}, \code{>}, \code{<=}, \code{>=}. +#' - Conditions can use operators: \code{==}, \code{!=}, \code{<}, \code{>}, \code{<=}, \code{>=}, \code{%in%}, \code{!%in%}. #' - Conditions are specified as simple expressions, e.g., #' \code{columnA == 'value'} #' \code{columnB != 5} @@ -198,9 +198,8 @@ or_filtering_transformator <- function(dataname) { "Select Condition", choices = c("==", "!=", "<", ">") ), - shiny::selectInput( - session$ns(paste0("value_input_", view_model$alt_id())), "Select Value", - choices = NULL + shiny::uiOutput( + session$ns(paste0("value_input_", view_model$alt_id())) ), shiny::actionButton( session$ns(paste0("add_condition_", view_model$alt_id())), @@ -220,7 +219,17 @@ or_filtering_transformator <- function(dataname) { operator <- input[[paste0("operator_selector_", view_model$alt_id())]] value <- input[[paste0("value_input_", view_model$alt_id())]] - cond_str <- paste0(variable, " ", operator, " ", value) + cond_str <- switch(operator, + "%in%" = { + quoted_vals <- paste0(sprintf("'%s'", value), collapse = ", ") + sprintf("%s %%in%% c(%s)", variable, quoted_vals) + }, + "!%in%" = { + quoted_vals <- paste0(sprintf("'%s'", value), collapse = ", ") + sprintf("!%s %%in%% c(%s)", variable, quoted_vals) + }, + sprintf("%s %s %s", variable, operator, value) + ) # Check for duplicates in current block existing_conds <- if (is.null(view_model$block_conditions[[as.character(view_model$alt_id())]])) { @@ -311,17 +320,46 @@ or_filtering_transformator <- function(dataname) { col_data <- data()[[dataname]][[selected_col]] if (is.numeric(col_data)) { - shiny::updateSelectInput(session, paste0("value_input_", current_id), choices = c(unique(col_data))) + output[[paste0("value_input_", current_id)]] <- renderUI({ + shiny::selectInput( + session$ns(paste0("value_input_", current_id)), + "Select Value", + choices = unique(col_data) + ) + }) shiny::updateSelectInput( - session, paste0("operator_selector_", current_id), - choices = c("==", "!=", "<=", ">=") + session, + paste0("operator_selector_", current_id), + choices = c("==", "!=", "<=", ">="), + selected = "==" ) } else if (is.character(col_data) || is.factor(col_data)) { + lvls <- levels(factor(col_data)) + + output[[paste0("value_input_", current_id)]] <- renderUI({ + op <- input[[paste0("operator_selector_", current_id)]] + if (!is.null(op) && op %in% c("%in%", "!%in%")) { + shinyWidgets::pickerInput( + session$ns(paste0("value_input_", current_id)), + "Select Values", + choices = lvls, + selected = lvls, + multiple = TRUE + ) + } else { + shiny::selectInput( + session$ns(paste0("value_input_", current_id)), + "Select Value", + choices = lvls + ) + } + }) + shiny::updateSelectInput( - session, paste0("value_input_", current_id), - choices = c(levels(factor(col_data))) + session, + paste0("operator_selector_", current_id), + choices = c("==", "!=", "%in%", "!%in%") ) - shiny::updateSelectInput(session, paste0("operator_selector_", current_id), choices = c("==", "!=")) } else { shiny::updateSelectInput(session, paste0("value_input_", current_id), choices = NULL) shiny::updateSelectInput(session, paste0("operator_selector_", current_id), choices = NULL) @@ -356,7 +394,7 @@ or_filtering_transformator <- function(dataname) { within( data(), { - if (filters != "" & filters != "()") { + if (filters != "" && filters != "()") { df <- df |> dplyr::filter(!!rlang::parse_expr(filters)) } }, diff --git a/man/add_condition.Rd b/man/add_condition.Rd index 7063a41..69c5bc3 100644 --- a/man/add_condition.Rd +++ b/man/add_condition.Rd @@ -11,7 +11,7 @@ add_condition(object, variable, operator, value) \item{variable}{A character string specifying the variable/column name.} -\item{operator}{A character string specifying the operator (e.g., "==", "!=", "<", ">", "<=", ">=").} +\item{operator}{A character string specifying the operator (e.g., "==", "!=", "<", ">", "<=", ">=", "\%in\%", "!\%in\%").} \item{value}{The value to compare against.} } diff --git a/man/or_filtering_transformator.Rd b/man/or_filtering_transformator.Rd index 29190b7..a365908 100644 --- a/man/or_filtering_transformator.Rd +++ b/man/or_filtering_transformator.Rd @@ -34,7 +34,7 @@ Each module call is independent and manages filters for its specific dataset. \item \strong{Supported Data Types & Expressions:} \itemize{ \item Supports filtering on \code{character}, \code{factor}, and \code{numeric} columns. -\item Conditions can use operators: \code{==}, \code{!=}, \code{<}, \code{>}, \code{<=}, \code{>=}. +\item Conditions can use operators: \code{==}, \code{!=}, \code{<}, \code{>}, \code{<=}, \code{>=}, \code{\%in\%}, \code{!\%in\%}. \item Conditions are specified as simple expressions, e.g., \code{columnA == 'value'} \code{columnB != 5}