Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

298 reset button #859

Merged
merged 101 commits into from
Jul 21, 2023
Merged

298 reset button #859

merged 101 commits into from
Jul 21, 2023

Conversation

chlebowa
Copy link
Contributor

@chlebowa chlebowa commented Jul 2, 2023

Relates to this issue.

Adds module for management of snapshots of application state.
A snapshot contains in formation on all filter states currently existing within the app, as well as their application to particular modules.
A snapshot can be added at any time by the user.
A snapshot can be restored at any time by the user.
A snapshot can be saved to file.
The initial state of the application is the first snapshot (not displayed in the list).

In addition, teal_slices handles global-module-specific specification differently. The deciding argument is module_specific. mapping$global_filters will decide which - if any - filters are active on start-up in global mode.

gogonzo and others added 21 commits March 9, 2023 15:25
Introduces changes necessary to handle the new Filter Panel API coming
from [this
PR](insightsengineering/teal.slice#222).

---------

Co-authored-by: Dawid Kałędkowski <dawid.kaledkowski@gmail.com>
Co-authored-by: Andrew Bates <andrew.bates@atorusresearch.com>
Co-authored-by: asbates <asbates@users.noreply.github.com>
Co-authored-by: chlebowa <chlebowa@users.noreply.github.com>
Co-authored-by: 27856297+dependabot-preview[bot]@users.noreply.github.com <27856297+dependabot-preview[bot]@users.noreply.github.com>
The follow-up after
insightsengineering/coredev-tasks#235

The current spelling-check output is below. `omics` is a part of
`multi-omics`. `pre-selected` is treated as spelling mistake either if
it's written `pre-selected` or `preselected`. `themer` and `theming` are
a part of subject-language about themes. `tabsetted` does not seem to be
an English word, even though TabSet class became of common word around
developers.

```{R}
spelling::spell_check_package()
  WORD               FOUND IN
Forkers            README.md:75,85,87
funder             teal-package.Rd:32
Hoffmann           teal-package.Rd:32
omics              README.md:29
                   including-mae-data-in-teal.Rmd:13
preselected        teal.Rmd:101
programmatically   NEWS.md:118
repo               README.md:9,15,83,87
reproducibility    init.Rd:24,25
                   srv_teal_with_splash.Rd:23,24
                   ui_teal_with_splash.Rd:25,26
                   NEWS.md:71,91,282
                   README.md:44
                   adding-support-for-reporting.Rmd:238
                   including-adam-data-in-teal.Rmd:16,104
                   including-general-data-in-teal.Rmd:80
                   including-mae-data-in-teal.Rmd:41
                   preprocessing-data.Rmd:87
                   teal.Rmd:75
tabsetted          ui_teal.Rd:43
themer             teal-bs-themes.Rmd:188,222
theming            teal-bs-themes.Rmd:39,108
TLG                README.md:53
UI                 init.Rd:5
                   srv_teal.Rd:103
                   ui_nested_tabs.Rd:8,35,42
                   ui_tabs_with_filters.Rd:25
                   ui_teal.Rd:5,19,20,35,38,41,43,46
                   ui_teal_with_splash.Rd:5
                   NEWS.md:118,194,210,313,317,366
                   creating-custom-modules.Rmd:47,49,52
                   teal-options.Rmd:89
                   teal.Rmd:59
UIs                ui_tabs_with_filters.Rd:5
uncheck            teal-bs-themes.Rmd:175
UX                 teal-options.Rmd:89

```
this fixes insightsengineering/teal.slice#330

Here in this PR , parameter module_add is being added to
teal::teal_filters() which passes parameter value to
teal.slice::filter_settings() function.

Testing code:
```
options(teal.log_level = "TRACE", teal.show_js_log = TRUE)
# options("teal.bs_theme" = bslib::bs_theme(version = 5))
# options(shiny.trace = TRUE)
# todo: change groupCheckbox to include locked (not able to interact with)
#       change groupCheckbox to have some colors (instead of grey)
# todo: available filter should present information about selected values (for example tooltip)


library(shiny)
library(scda)
library(scda.2022)
library(teal.data)
library(teal.transform)
library(teal.modules.general)
pkgload::load_all()

funny_module <- function (label = "Filter states", datanames = "all") {
  checkmate::assert_string(label)
  module(
    label = label,
    filters = datanames,
    ui = function(id, ...) {
      ns <- NS(id)
      div(
        h2("The following filter calls are generated:"),
        verbatimTextOutput(ns("filter_states")),
        verbatimTextOutput(ns("filter_calls")),
        actionButton(ns("reset"), "reset_to_default")
      )
    },
    server = function(input, output, session, data, filter_panel_api) {
      checkmate::assert_class(data, "tdata")
      observeEvent(input$reset, set_filter_state(filter_panel_api, default_filters))
      output$filter_states <-  renderPrint({
        logger::log_trace("rendering text1")
        filter_panel_api %>% get_filter_state()
      })
      output$filter_calls <- renderText({
        logger::log_trace("rendering text2")
        attr(data, "code")()
      })
    }
  )
}

ADSL <- synthetic_cdisc_data("latest")$adsl
ADSL$empty <- NA
ADSL$logical1 <- FALSE
ADSL$logical <- sample(c(TRUE, FALSE), size = nrow(ADSL), replace = TRUE)
ADSL$numeric <- rnorm(nrow(ADSL))
ADSL$categorical2 <- sample(letters[1:10], size = nrow(ADSL), replace = TRUE)
ADSL$categorical <- sample(letters[1:3], size = nrow(ADSL), replace = TRUE, prob = c(.1, .3, .6))
ADSL$date <- Sys.Date() + seq_len(nrow(ADSL))
ADSL$date2 <- rep(Sys.Date() + 1:3, length.out = nrow(ADSL))
ADSL$datetime <- Sys.time() + seq_len(nrow(ADSL)) * 3600 * 12
ADSL$datetime2 <- rep(Sys.time() + 1:3 * 43200, length.out = nrow(ADSL))

ADSL$numeric[sample(1:nrow(ADSL), size = 10)] <- NA
ADSL$numeric[sample(1:nrow(ADSL), size = 10)] <- Inf
ADSL$logical[sample(1:nrow(ADSL), size = 10)] <- NA
ADSL$date[sample(1:nrow(ADSL), size = 10)] <- NA
ADSL$datetime[sample(1:nrow(ADSL), size = 10)] <- NA
ADSL$categorical2[sample(1:nrow(ADSL), size = 10)] <- NA
ADSL$categorical[sample(1:nrow(ADSL), size = 10)] <- NA

ADTTE <- synthetic_cdisc_data("latest")$adtte
ADRS <- synthetic_cdisc_data("latest")$adrs

ADTTE$numeric <- rnorm(nrow(ADTTE))
ADTTE$numeric[sample(1:nrow(ADTTE), size = 10,)] <- NA

default_filters <- teal::teal_filters(
  filter_var(dataname = "ADSL", varname = "categorical", selected = c("a", "b"), id = "categorical", locked = TRUE),
  filter_var(dataname = "ADSL", varname = "categorical2", selected = c("a", "b"), locked = TRUE),
  filter_var(dataname = "ADSL", varname = "numeric", selected = c(0, 140), keep_na = TRUE, keep_inf = TRUE),
  filter_var(dataname = "ADSL", varname = "logical", selected = c(T), keep_na = TRUE, keep_inf = TRUE),
  filter_var(dataname = "ADSL", varname = "datetime"),
  filter_var(dataname = "ADSL", varname = "date2"),
  filter_expr(id = "AF", title = "ADULT FEMALE", dataname = "ADSL", expr = "SEX %in% 'F' & AGE >= 18L"),
  filter_expr(id = "SE", title = "Safety-Evaluable", dataname = "ADSL", expr = "SAFFL == 'Y'"),
  filter_var(dataname = "ADSL", varname = "COUNTRY", selected = c("USA", "CAN", "JPN"), fixed = TRUE),
  count_type = "all",
  include_varnames = list(ADSL = c("SEX", "categorical", "categorical2", "numeric", "logical", "date", "datetime", "date2", "datetime2", "COUNTRY")),
  exclude_varnames = list(
    ADTTE = intersect(colnames(ADSL), colnames(ADTTE)),
    ADRS = colnames(ADSL)
  ),
  mapping = list(
    `table` = "categorical"
  ),
  module_specific = TRUE,
  module_add = FALSE  # set it to true for seeing filter add module

)

app <- init(
  data = cdisc_data(
    cdisc_dataset("ADSL", ADSL),
    cdisc_dataset("ADTTE", ADTTE),
    cdisc_dataset("ADRS", ADRS)
  ),
  modules = modules(
    tm_data_table(
      "table",
      variables_selected = list(ADSL = c("STUDYID", "USUBJID", "SUBJID", "SITEID", "AGE", "SEX")),
      dt_args = list(caption = "ADSL Table Caption")
    ),
    modules(
      label = "tab1",
      funny_module("funny", datanames = NULL),
      funny_module("funny2", datanames = "ADTTE") # will limit datanames to ADTTE and ADSL (parent)
    )
  ),
  filter = default_filters
)


runApp(app)
```

Co-authored-by: kartikeya <kartikeya.kirar@unicle.life>
@chlebowa chlebowa added the core label Jul 2, 2023
@chlebowa chlebowa changed the base branch from main to filter_panel_refactor@main July 2, 2023 13:29
@chlebowa
Copy link
Contributor Author

chlebowa commented Jul 2, 2023

TESTING

Set teal and teal.slice to 298_reset_button@filter_panel_refactor@main
Use the following app.

options(teal.log_level = "WARN", teal.show_js_log = TRUE)
# options("teal.bs_theme" = bslib::bs_theme(version = 5))
# options(shiny.trace = TRUE)
# todo: change groupCheckbox to include locked (not able to interact with)
#       change groupCheckbox to have some colors (instead of grey)
# todo: available filter should present information about selected values (for example tooltip)

library(shiny)
library(scda)
library(scda.2022)
library(teal.data)
library(teal.transform)
library(teal.modules.general)
pkgload::load_all("../teal.slice")
pkgload::load_all("../teal")

funny_module <- function (label = "Filter states", datanames = "all") {
  checkmate::assert_string(label)
  module(
    label = label,
    filters = datanames,
    ui = function(id, ...) {
      ns <- NS(id)
      div(
        h2("The following filter calls are generated:"),
        verbatimTextOutput(ns("filter_states")),
        verbatimTextOutput(ns("filter_calls")),
        actionButton(ns("reset"), "reset_to_default")
      )
    },
    server = function(input, output, session, data, filter_panel_api) {
      checkmate::assert_class(data, "tdata")
      observeEvent(input$reset, set_filter_state(filter_panel_api, default_filters))
      output$filter_states <-  renderPrint({
        logger::log_trace("rendering text1")
        filter_panel_api %>% get_filter_state()
      })
      output$filter_calls <- renderText({
        logger::log_trace("rendering text2")
        attr(data, "code")()
      })
    }
  )
}

default_filters <- teal::teal_slices(
  teal_slice("iris", "Sepal.Length"),
  teal_slice("iris", "Sepal.Width"),
  teal_slice("iris", "Species"),
  teal_slice("mtcars", "mpg"),
  exclude_varnames = list(
    iris = c("Petal.Length"),
    mtcars = c("qsec", "drat")
  ),
  mapping = list(
    funny = c("iris Sepal.Length"),
    funny2 = c("iris Sepal.Width"),
    global_filters = "mtcars mpg"
  )
  # module_specific = FALSE
)
app <- init(
  data = teal_data(
    dataset("iris", iris),
    dataset("mtcars", mtcars)
  ),
  modules = modules(
    tm_data_table(
      "table",
      variables_selected = list(),
      dt_args = list()
    ),
    modules(
      label = "tab1",
      funny_module("funny", datanames = NULL),
      funny_module("funny2", datanames = "iris")
    )
  ),
  filter = default_filters
)

runApp(app, launch.browser = TRUE)

Signed-off-by: Aleksander Chlebowski <114988527+chlebowa@users.noreply.github.com>
Copy link
Contributor

@gogonzo gogonzo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I consider technicals on the teal side robust.

image

@m7pr
Copy link
Contributor

m7pr commented Jul 19, 2023

I love the elegancy of the graph/workflow

@chlebowa
Copy link
Contributor Author

Great chart indeed @gogonzo and you beat me to it 🙂

I don't quite like the click either but since we can't think of anything better at the moment, let's put a pin in it, maybe we will come up with something later. Unless @lcd2yyz withdraws the requirement.

Copy link
Contributor

@gogonzo gogonzo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WOWs

@chlebowa chlebowa merged commit f88693f into main Jul 21, 2023
23 checks passed
@chlebowa chlebowa deleted the 298_reset_button@filter_panel_refactor@main branch July 21, 2023 08:25
@m7pr
Copy link
Contributor

m7pr commented Jul 21, 2023 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants