Enhancement: SimplifyTLG Order Details Table, Internalize PCSPC Filtering - #1380
Conversation
… search, downloads, and scoped select-all
Gero1999
left a comment
There was a problem hiding this comment.
I really really love this! Everything worked as expected within the App experience
I will just write some non-blocking things I would suggest to do:
-
Codewise: This PR injects a large block of hardcoded CSS, perhaps we can consider moving it to the
scssdocuments. There's already a modules/_colors.scss; insteadd of hardcoding, the colors (#007bc2, #E7ECFA, etc...) could come from there. -
Experience wise: If any ADPP-TLG based is requested by the user, but no ADDP is availabe (i.e, NCA was not run) push a notification for the user to know why some TLGs may be missing/not rendered well. Right now the error/problem is silent. But this can easily be a new issue/PR, I will leave it to your criteria 😉
bugtlgs.mp4Found a little bug when you filter on "tt", there is 0 pk conc, and 1 pk param, but selecting the one with 0 does not change the display |
…ent-simplify-tlg-order-details-table-and-internalize-pcspec-filtering
| if (length(checked_ids) > 0) { | ||
| tlg_order_data <- tlg_order() | ||
| tlg_order_data$Selection[!tlg_order_data$Selection][selected_rows] <- TRUE | ||
| tlg_order_data$Selection[tlg_order_data$id %in% as.integer(checked_ids)] <- TRUE |
There was a problem hiding this comment.
[Error] New selection logic is untested.
The reactable→checkbox rewrite changes how selections map to tlg_order() (now id %in% checked_ids instead of positional index). This is the highest-risk change in the PR and has no test — both "passes all unit tests" and "new logic covered by tests" are unchecked.
Proposed resolution — add a testServer test (e.g. tests/testthat/test-tab_tlg.R):
describe("tab_tlg_server: add-picker selection", {
it("sets Selection = TRUE for the checked ids", {
testServer(tab_tlg_server, args = list(data = reactive(test_data)), {
# two non-default rows available in the modal
ids <- tlg_order()$id[!tlg_order()$Selection][1:2]
modal_group_ids("modal_check_1")
session$setInputs(modal_check_1 = as.character(ids))
session$setInputs(confirm_add_tlg = 1)
expect_true(all(tlg_order()$Selection[tlg_order()$id %in% ids]))
})
})
it("removes the selected rows", {
testServer(tab_tlg_server, args = list(data = reactive(test_data)), {
# remove handler uses positional index into currently-selected rows
before <- sum(tlg_order()$Selection)
# stub selected_tlg_state()$selected = 1 via the reactable mock, then:
session$setInputs(remove_tlg = 1)
expect_lt(sum(tlg_order()$Selection), before)
})
})
})Also add a unit test for the warning path in tlg_module.R (see separate comment there).
| # line up on the same left edge. | ||
| div( | ||
| class = "tlg-add-modal", | ||
| tags$style(HTML(" |
There was a problem hiding this comment.
[Warning] Inline CSS bypasses the SCSS workflow and duplicates existing color tokens.
~100 lines of CSS are embedded via tags$style, with hardcoded hex values (#007bc2, #E7ECFA) that already exist as SCSS variables $anca-blue / $anca-blue-light in styles/modules/_colors.scss. This is the only module using inline tags$style, and per AGENTS.md styling must live in .scss and be compiled to main.css. The checklist item "run compile_css.R" is unchecked.
Proposed resolution — move the block into a new partial and reuse tokens:
// inst/shiny/www/styles/partials/_tlg_add_modal.scss
@use "../modules/colors" as *;
.tlg-add-modal {
--tlg-inset: 0.55em;
.tlg-tab.active { color: $anca-blue; border-bottom-color: $anca-blue; }
.tlg-add-checklist .checkbox:has(input:checked) { background: $anca-blue-light; }
.tlg-add-checklist .checkbox input[type=checkbox] { accent-color: $anca-blue; }
// …migrate the remaining rules here…
}// styles/main.scss
@use "partials/tlg_add_modal";Then drop the tags$style(...) from .build_add_checklist(), run Rscript data-raw/compile_css.R, and commit both the partial and the regenerated main.css.
| } | ||
|
|
||
| tab_tlg_server <- function(id, data, adpp = reactive(NULL)) { | ||
| tab_tlg_server <- function(id, data, adpp = reactive(NULL)) { # nolint: cyclocomp_linter |
There was a problem hiding this comment.
[Warning] Complexity suppressed instead of reduced.
# nolint: cyclocomp_linter was added because tab_tlg_server now mixes UI construction, a ~100-line inline <style>, an inline window.tlgAdd JS object, download handlers, and confirm/remove logic in one function. Per AGENTS.md ("flag overly complex implementations that could be simplified"), this should be decomposed rather than silenced.
Proposed resolution — extract helpers into inst/shiny/functions/ (this also makes the logic testable for E1):
# inst/shiny/functions/tlg_add_picker.R
#' Build the "Add TLGs" catalog checklist UI.
build_add_checklist <- function(avail, ns) {
# …move the current .build_add_checklist body here…
}
#' Assets (CSS + JS) for the add-picker modal.
tlg_add_picker_assets <- function() {
tagList(
includeCSS(app_sys("shiny/www/main.css")), # once styles are moved to SCSS
tags$script(src = "tlg_add_picker.js") # move window.tlgAdd here
)
}
#' Rows checked in the modal, mapped back to tlg_order ids.
checked_tlg_ids <- function(input, group_ids) {
as.integer(unlist(lapply(group_ids, function(gid) input[[gid]])))
}Then tab_tlg_server calls these helpers, window.tlgAdd moves to www/tlg_add_picker.js, and the nolint can be removed.
| warning = function(w) { | ||
| showNotification(conditionMessage(w), type = "warning", duration = 10) | ||
| invokeRestart("muffleWarning") | ||
| } |
There was a problem hiding this comment.
[Warning] Warning-surfacing path is untested; raw warning text shown to users.
The withCallingHandlers → showNotification → muffleWarning path (the user-facing half of the PCSPEC-missing behavior) has no test, and it forwards the raw conditionMessage(w) — which may read technically for end users.
Proposed resolution — add a unit test and a friendlier prefix:
# tests/testthat/test-tlg_module.R
it("surfaces render warnings as notifications and continues (issue #1335)", {
warn_fn <- function(data, ...) {
warning("PCSPEC/PPSPEC not found; specimen filtering skipped")
list("plot_a")
}
testServer(
tlg_module_server,
args = list(data = test_data, type = "graph",
render_list = warn_fn, options = list()),
{
session$setInputs(entries_per_page = "All")
session$elapse(800); session$flushReact()
expect_equal(tlg_list(), list("plot_a")) # muffled: rendering continues
# notification captured via mockery::stub on showNotification, asserting it fired
}
)
})Optional message tweak:
warning = function(w) {
showNotification(
paste0("Notice: ", conditionMessage(w)),
type = "warning", duration = 10
)
invokeRestart("muffleWarning")
}|
[Error] Edit write-back may target the wrong column after trimming the display table. (Posting as a general comment — The Order Details table was trimmed to new_tlg_order[new_tlg_order$Selection, ][info$row, info$column] <- info$valueThe full frame still contains Proposed resolution — resolve by name and guard against non-editable columns: observeEvent(selected_tlg_state()$edit(), {
info <- selected_tlg_state()$edit()
# info$column may be a display-frame index; map to the full-frame column name
editable_cols <- c("Footnote", "Stratification", "Comment")
col_name <- if (is.numeric(info$column)) {
names(displayed_order())[info$column]
} else {
info$column
}
req(col_name %in% editable_cols) # never write to a non-editable column
new_tlg_order <- tlg_order()
new_tlg_order[new_tlg_order$Selection, ][info$row, col_name] <- info$value
tlg_order(new_tlg_order)
})Please confirm what |
…log' into 1335-enhancement-simplify-tlg-order-details-table-and-internalize-pcspec-filtering
… notice, fix search tabs
|
@Shaakon35 bug is fixed feel free to approve! We just added a WISH feat for select-all / delete-all |
…s (respecting search)
…log' into 1335-enhancement-simplify-tlg-order-details-table-and-internalize-pcspec-filtering # Conflicts: # DESCRIPTION # inst/shiny/modules/tab_tlg/tlg_module.R # tests/testthat/test-tab_tlg.R
Issue
Closes #1335
Description
Simplifies the TLG Order Details table and internalizes urine (PCSPEC) filtering:
Conditioncolumn is hidden from the UI and removed from the editable set. It remains intlg.yamlas metadata and still drives urine auto-selection under the hood. The table is trimmed to the recommended columns: Type, Dataset, Output, Footnote, Stratification, Comment (PKid / Label / Description dropped from display).t_pkpt08_uri,l_pkcl02_uri,p_pkpg01_cum,p_pkpg01_per, from the Enhancement: Expand TLG catalog with new graph and table functions #1343 base) filter to urine specimens by themselves. WhenPCSPEC/PPSPECis absent they emit a warning, which is now surfaced to the user as an in-appshowNotification()rather than failing silently.Definition of Done
How to test
Conditioncolumn, andConditionis not editable.PCSPEC = "URINE").PCSPEC/PPSPECand confirm a warning notification appears.Contributor checklist
.scsschange was done, rundata-raw/compile_css.Rdata-raw/test_suggests_hidden.RNotes to reviewer