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

Feature branch PR #603

Merged
merged 22 commits into from
Aug 12, 2024
Merged

Feature branch PR #603

merged 22 commits into from
Aug 12, 2024

Conversation

gogonzo
Copy link
Contributor

@gogonzo gogonzo commented Jul 31, 2024

  • reduce the size of filter-panel by moving ui/srv_add to ui/srv_active
  • change log level
  • introduce self$finalize method to destroy all the observers and inputs (needed after data reloading)

@gogonzo gogonzo added the core label Jul 31, 2024
@gogonzo gogonzo changed the title 669 insert UI@main Feature branch PR Jul 31, 2024
Copy link
Contributor

github-actions bot commented Jul 31, 2024

badge

Code Coverage Summary

Filename                        Stmts    Miss  Cover    Missing
----------------------------  -------  ------  -------  -----------------------------------------------------------------------------------------------------------------------
R/calls_combine_by.R                7       0  100.00%
R/choices_labeled.R                49      14  71.43%   25, 36, 41, 51-56, 68, 72-76
R/count_labels.R                  102       0  100.00%
R/filter_panel_api.R               27       1  96.30%   132
R/FilteredData-utils.R             68      25  63.24%   21-24, 27-30, 52-57, 153, 175-184
R/FilteredData.R                  540     186  65.56%   110, 184, 326, 398, 503-511, 534, 553-596, 616-619, 660, 697, 718-750, 773-775, 778-792, 796-806, 809-852, 909, 921-943
R/FilteredDataset-utils.R          23       1  95.65%   125
R/FilteredDataset.R               232      72  68.97%   48, 147, 179, 206-276, 379
R/FilteredDatasetDataframe.R      120       8  93.33%   87, 148, 158, 233-237
R/FilteredDatasetDefault.R         18       4  77.78%   104-117
R/FilteredDatasetMAE.R            133      37  72.18%   56, 117-122, 159-164, 168-169, 187-209
R/FilterPanelAPI.R                 10       0  100.00%
R/FilterState-utils.R             101       2  98.02%   264, 294
R/FilterState.R                   363      61  83.20%   89, 213, 231-235, 242-243, 257-258, 264-265, 321, 323, 325, 377, 420, 641, 684-707, 717-736, 771-777, 786-792
R/FilterStateChoices.R            352     109  69.03%   301, 368-375, 379-396, 423-426, 439-450, 462-470, 474-503, 523-526, 529-532, 542-567, 578, 583, 594
R/FilterStateDate.R               213     127  40.38%   230, 282-437
R/FilterStateDatettime.R          307     197  35.83%   266, 318-547
R/FilterStateEmpty.R               53      31  41.51%   89, 99-104, 117, 129-169
R/FilterStateExpr.R                83      68  18.07%   167-280
R/FilterStateLogical.R            194     142  26.80%   136, 158, 218, 222-404
R/FilterStateRange.R              410     104  74.63%   262, 384, 517-521, 524-534, 537, 548-554, 565-577, 581-591, 595-597, 610-636, 651, 654, 668-685, 720-725, 735-737
R/FilterStates-utils.R             70       7  90.00%   108, 127, 188-194
R/FilterStates.R                  361      31  91.41%   76-80, 187, 309-318, 403-406, 449, 487, 550-554, 599, 719-722
R/FilterStatesDF.R                  5       0  100.00%
R/FilterStatesMAE.R                10       1  90.00%   40
R/FilterStatesMatrix.R              3       0  100.00%
R/FilterStatesSE.R                216      62  71.30%   36, 71-73, 83-85, 108-115, 123-130, 206, 231, 250-268, 276-294, 302
R/include_css_js.R                  5       5  0.00%    12-16
R/teal_slice.R                    107       4  96.26%   131, 195-196, 206
R/teal_slices.R                    84       5  94.05%   150-155
R/test_utils.R                     21       0  100.00%
R/utils.R                          20       0  100.00%
R/variable_types.R                 15       1  93.33%   48
R/zzz.R                            17      17  0.00%    3-47
TOTAL                            4339    1322  69.53%

Diff against main

Filename                        Stmts    Miss  Cover
----------------------------  -------  ------  --------
R/filter_panel_api.R               -2       0  -0.26%
R/FilteredData.R                  -22     -41  +5.95%
R/FilteredDataset.R               +62     +11  +4.85%
R/FilteredDatasetDataframe.R       -1       0  -0.06%
R/FilteredDatasetMAE.R             -1       0  -0.21%
R/FilterState.R                    +2       0  +0.09%
R/FilterStateChoices.R             -2      -1  +0.11%
R/FilterStateDate.R                -2      -2  +0.38%
R/FilterStateDatettime.R           -2      -2  +0.23%
R/FilterStateExpr.R                +8      +6  +0.74%
R/FilterStateLogical.R             -2      -2  +0.27%
R/FilterStateRange.R               -4      -1  -0.00%
R/FilterStates-utils.R              0      -2  +2.86%
R/FilterStates.R                   -3      +1  -0.35%
R/FilterStatesSE.R                 +5     -95  +45.70%
R/utils.R                          +2       0  +100.00%
R/variable_types.R                  0      -7  +46.67%
TOTAL                             +38    -135  +3.41%

Results for commit: cfb750a

Minimum allowed coverage is 80%

♻️ This comment has been updated with latest results

#602)

# Pull Request

Companion of insightsengineering/teal#1275

Note: There's a similar solution that is cleaner. I'll push it on Monday

#### Changes description

- Keeps track of `remove observers` on filter panel
- Destroys `remove observer` when clearing filter panel



Co-authored-by: go_gonzo <[email protected]>
Copy link
Contributor

github-actions bot commented Aug 1, 2024

Unit Tests Summary

  1 files   29 suites   23s ⏱️
360 tests 360 ✅ 0 💤 0 ❌
826 runs  826 ✅ 0 💤 0 ❌

Results for commit cfb750a.

♻️ This comment has been updated with latest results.

averissimo and others added 7 commits August 2, 2024 13:17
WIP. Still testing with more filter option

Companion of insightsengineering/teal#1275

#### Changes description

- Removes all observeEvents generated from `FilterData` when `finalize`
method is called.

#### How to test

- Override `observeEvent` in `{teal.slice}` in order to keep track of
all that are created
  - Stores observers in `.tmp_list` on `.GlobalEnv`
- Place `browser()` call somewhere with access to `FilterData` object
- Run snippet at bottom that shows count of observers that have not been
destroyed
- These are shown in order of creation `<order>_<parent r6
class>_<memory address>`
- Run `finalize()`
- Run snippet again

<details>

<summary>Example teal app</summary>

```r
.tmp_list <- rlang::new_environment()

options(
  teal.log_level = "INFO",
  teal.show_js_log = TRUE,
  # teal.bs_theme = bslib::bs_theme(version = 5),
  shiny.bookmarkStore = "server"
)

pkgload::load_all("../teal.slice")
pkgload::load_all("../teal")

data <- teal::teal_data_module(
  ui = function(id) {
    ns <- shiny::NS(id)
    shiny::tagList(
      shiny::checkboxGroupInput(
        ns("datasets"),
        "Datasets",
        choices = c("ADSL", "ADTTE", "iris", "CO2", "miniACC"),
        selected = c("ADSL", "ADTTE", "iris", "CO2")
      ),
      shiny::actionButton(ns("submit"), label = "Submit")
    )
  },
  server = function(id, ...) {
    shiny::moduleServer(id, function(input, output, session) {
      code <- list(
        ADSL = expression(
          ADSL <- teal.data::rADSL
        ),
        ADTTE = expression({
          ADTTE <- teal.data::rADTTE
          ADTTE$CNSRL <- as.logical(ADTTE$CNSR)
        }),
        iris = expression(
          iris <- iris
        ),
        CO2 = expression({
          CO2 <- CO2
          factors <- names(Filter(isTRUE, vapply(CO2, is.factor, logical(1L))))
          CO2[factors] <- lapply(CO2[factors], as.character)
        }),
        miniACC = expression({
          data(
            "miniACC",
            package = "MultiAssayExperiment",
            envir = environment(),
            overwrite = TRUE
          )
          miniACC <- miniACC
        })
      )

      datasets <- reactive(input$datasets)

      shiny::eventReactive(input$submit, {
        code_to_eval <- do.call(c, code[datasets()])
        data <- teal.code::eval_code(teal.data::teal_data(), code_to_eval)

        join_keys(data) <- default_cdisc_join_keys[datasets()]
        teal.data::datanames(data) <- datasets()
        data
      })
    })
  },
  once = FALSE
)

teal::init(
  data = data,
  modules = teal::modules(
    teal::example_module(label = "A"),
    teal::example_module(label = "B")
  ),
  filter = teal::teal_slices(
    # FilterRange
    teal.slice::teal_slice("ADSL", "AGE", selected = c(18L, 65L)),
    # FilterExpr
    teal_slice(
      dataname = "ADSL",
      id = "Female adults",
      expr = "SEX == 'F' & AGE >= 18",
      title = "Female adults"
    ),
    # FilterDatetime
    teal_slice(
      dataname = "ADTTE",
      varname = "ADTM",
      id = "Analysis DTM",
      selected = c("2019-03-25 07:06:18", "2020-01-22 15:03:58"),
      title = "Female adults"
    ),
    # FilterDate with LSTALVDT
    teal_slice(
      dataname = "ADSL",
      varname = "LSTALVDT",
      id = "Last Alive Date",
      selected = c("2022-02-14", "2022-11-24"),
      title = "Last Alive Date"
    ),
    # FilterEmpty
    # FilterLogical with CNSRL
    teal_slice(
      dataname = "ADTTE",
      varname = "CNSRL",
      id = "Censored",
      selected = TRUE,
      title = "Censored"
    ),
    module_specific = TRUE,
    teal.slice::teal_slice("ADSL", "SEX")
  ),
  title = "yada"
) |>
  shiny::runApp()
```

</details>

<details>

<summary>"observeEvent" override</summary>

```r
observeEvent = function(eventExpr,
                        handlerExpr,
                        ...
  ) {
  logger::log_info("yada")

  rlang::enquo(eventExpr)
  rlang::enquo(handlerExpr)

  obs <- do.call(
    shiny::observeEvent,
    list(
      eventExpr = rlang::enquo(eventExpr),
      handlerExpr = rlang::enquo(handlerExpr),
      ...
    ),
    envir = parent.frame()
  )

  # Create a temporary list to store observers and parent objects
  if (is.null(.GlobalEnv$.tmp_list)) .GlobalEnv$.tmp_list <- rlang::new_environment()

  self <- parent.env(parent.env(parent.frame()))$self
  obj_addr <- rlang::obj_address(self) |>
    as.character() |>
    stringr::str_replace("0x", "")

  obj_addr <- paste0(class(self)[1], "_", obj_addr)

  .tmp_list[["objects"]] <- c(
    list(),
    .tmp_list[["objects"]],
    setNames(list(self), obj_addr)
  )

  .tmp_list[[sprintf("%03d_%s", length(.tmp_list[["objects"]]), obj_addr)]] <- c(
    list(),
    .tmp_list[[obj_addr]],
    list(obs)
  )

  obs
}
```

</details>

<details>

<summary>Snippet to analyse ".tmp_list"</summary>

```r
ls(.tmp_list) |>
  purrr::keep(~!grepl("^objects$", .x)) |>
  vapply(
    \(x) {
      sum(
        vapply(
          .tmp_list[[x]],
          \(.x) isFALSE(.x$.destroyed),
          integer(1L)
        )
      )
    },
    integer(1L)
  ) |>
  as.list() |>
  jsonlite::toJSON(pretty = TRUE, auto_unbox = TRUE)
```

</details>


![text444](https://github.com/user-attachments/assets/95e29e4a-d2dd-4872-859c-9dbc70ec39a6)

---------

Co-authored-by: go_gonzo <[email protected]>
R/FilterState.R Outdated Show resolved Hide resolved
…ule (#604)

links to insightsengineering/teal#1282

Fixes the +/- icon behavior on the filter panel.
Please checkout to the `fix-add-remove-ui@669_insertUI@main` in both
`teal` and `teal.slice`
In `teal.slice` it just reverts one commit to the working version of the
show/hide logic.

When the data changes using `teal_data_module` the filter panel
observers are being called once again thus running the scope of the
observers as many times the data changes.
The fix is to reinitialize the filter panel with new NS so the observers
are not connected to the active UI anymore.

### Example app to test
```r
pkgload::load_all("teal.slice")
pkgload::load_all("teal")
library(MultiAssayExperiment)

data <- teal::teal_data_module(
  ui = function(id) {
    ns <- shiny::NS(id)
    shiny::tagList(
      shiny::textInput(ns("username"), label = "Username"),
      shiny::passwordInput(ns("password"), label = "Password"),
      shiny::actionButton(ns("submit"), label = "Submit")
    )
  },
  server = function(id, ...) {
    shiny::moduleServer(id, function(input, output, session) {
      shiny::eventReactive(input$submit, {
        data <- teal.data::teal_data() |>
          within(
            {
              logger::log_debug("Loading data...")
              iris <- iris
              data("miniACC", package = "MultiAssayExperiment", envir = environment())
            },
            username = input$username,
            password = input$password
          )
        data
      })
    })
  },
  once = FALSE
)

app <- init(
  data = data,
  modules = example_module()
)

shiny::runApp(app$ui, app$server)
```

---------

Signed-off-by: Vedha Viyash <[email protected]>
Co-authored-by: Dawid Kałędkowski <[email protected]>
Copy link
Contributor

github-actions bot commented Aug 6, 2024

Unit Test Performance Difference

Additional test case details
Test Suite $Status$ Time on main $±Time$ Test Case
FilteredData 💀 $0.21$ $-0.21$ get_filter_count_properly_tallies_active_filter_states
FilteredData 💀 $0.17$ $-0.17$ get_filter_count_properly_tallies_active_filter_states_for_MAE_objects

Results for commit d831361

♻️ This comment has been updated with latest results.

@gogonzo gogonzo enabled auto-merge (squash) August 12, 2024 15:49
Copy link
Contributor

@averissimo averissimo left a comment

Choose a reason for hiding this comment

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

Let's go!

@gogonzo gogonzo merged commit 0ccfa94 into main Aug 12, 2024
29 checks passed
@gogonzo gogonzo deleted the 669_insertUI@main branch August 12, 2024 16:35
@github-actions github-actions bot locked and limited conversation to collaborators Aug 12, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants