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
show/hide filter state inputs #181
show/hide filter state inputs #181
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good. This is a good way to solve out problems. Let's discuss the way how new FS are going to be added/inserted.
I think that to complete this issue we will have to use renderUI instead of insertUI/removeUI #135
I'm happy to discuss this on the call
R/FilterStateChoices.R
Outdated
ui = function(id) { | ||
ns <- NS(id) | ||
|
||
tags$li( | ||
id = id, | ||
tags$div( | ||
class = "filter-card filter-card-range", | ||
tags$div( | ||
class = "filter-card-header", | ||
uiOutput(ns("header_name_value"), inline = TRUE), | ||
uiOutput(ns("header_keep_na"), inline = TRUE), | ||
tags$div( | ||
class = "filter-card-icons", | ||
tags$span( | ||
class = "filter-card-toggle fa fa-chevron-right" | ||
), | ||
actionLink( | ||
inputId = ns("remove"), | ||
label = icon("circle-xmark", lib = "font-awesome"), | ||
class = "filter-card-remove" | ||
) | ||
) | ||
), | ||
tags$div( | ||
class = "filter-card-body", | ||
private$ui_inputs(ns("inputs")) | ||
) | ||
) | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can keep ui in the FilterState as before but header could be delegated to the child-classes - in the FIlterState it could look like this:
ui = div(
class = "filter-card-header",
private$ui_header(ns("header")),
actionLink(ns("remove"),...)
)
div(
private$ui_inputs(ns("inputs"))
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I second the opinion about keeping the ui in the FilterState since the code seems reusable and all the FilterStateXXX inherits from FilterState.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also see reusable code in server method. Maybe we can move that to FilterState class too?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Definitely some repeated code. I think I misunderstood a conversation the other day.
R/FilterStateRange.R
Outdated
uiOutput(ns("header_name_value"), inline = TRUE), | ||
uiOutput(ns("header_keep_na"), inline = TRUE), | ||
uiOutput(ns("header_keep_inf"), inline = TRUE), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe instead of:
<varname>: min-max NA: TRUE Inf: TRUE
<varname>: min-max NA: FALSE Inf: FALSE
following could be better:
<varname>: min-max, NA, Inf
<varname>: min-max
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure what you mean here. Could you expand on this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I was wrong above. I put <varname>:
instead of selected:
.
NA: TRUE
and Inf: TRUE
takes some space so I think about alternative display. Instead of having NA: TRUE
as a separate "span" we can include it in the selected
"span", so we could have:
selected: F, M, NA
when NA is TRUEselected: 18-64, Inf
when Inf is TRUEselected: 18-64
when Inf is FALSE
In above examples word selected
could be replaced with choices
color: var(--bs-danger, #a94442); | ||
} | ||
|
||
.filter-card-body { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking really nice! 👍 I've been playing with examples #165 Might be worth thinking of:
|
For now, I think we should focus on the the default bootstrap (for shiny 1.6.0, it's bootstrap 4) that is being used by shiny/teal. This way we won't be distracted as we continue on with our progress. Once we're done with the code foundation of the upgraded filter panel, we can revisit this and see how teal reacts with other bs version. |
Thanks @asbates The text for showing the current selection could be too long. Although, COUNTRIES can also make it too long if users select multiple countries. Unless there's a way to make this more pleasant, I am leaning toward not include the selection values in the title. |
So FYI as of 1.6.0 Shiny supports bootstrap 4. But it still uses 3 as the default. |
Having only the variable name would definitely solve this and would be the easiest route. I was planning on doing some abbreviation to resolve though. |
…_panel_refactor@main Signed-off-by: Andrew Bates <andrew.bates@atorusresearch.com>
Ah okay, thanks. Yes, let's focus on 3 then. |
I also feel including selected values in the variable names make it way to crowded. We don't need to go so extreme to collapse to one-liner, but being able to show the 1) variable label and 2) selected values or ranges, will be informative and important. So this is what I had in mind initially, it should also allow bootstrap theme to come through I'm less concerned about showing NA/Inf in the collapsed mode - if visually doesn't fit (in a visually pleasing way), we don't need to show. But I think we might need to design different displays for different variable class. For example
|
We gathered with the team and decided to move on with the issue (on the feature branch). So that:
So far we concluded to have following summary:
If we stick to the convention that summary is always a one liner produced by the classes than it will be very easy to change particular summary module for a single data type without changing the design for all of them. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @asbates , provided my feedback.
) | ||
class = "filter-card-title", | ||
tags$span(self$get_varname(deparse = TRUE)), | ||
if (length(self$get_varlabel())) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The varname and varlabel show twice when it holds the same value:
In the previous state of the code, we have the if statement comparing $get_varname
and $get_varlabel
, which will work, but I don't think this is the root cause.
private$varlabel is initialized with condition to not hold the same value with varname:
Lines 91 to 96 in aab1255
private$varlabel <- if (identical(varlabel, as.character(varname))) { | |
# to not display duplicated label | |
character(0) | |
} else { | |
varlabel | |
} |
However, when I browser()
this, I see the following:
varlabel is the result of get_varlabels()
method from FilteredDataset class:
teal.slice/R/FilteredDatasetDefault.R
Lines 41 to 50 in aab1255
private$add_filter_states( | |
filter_states = init_filter_states( | |
data = self$get_dataset(), | |
input_dataname = as.name(dataname), | |
output_dataname = as.name(dataname), | |
varlabels = self$get_varlabels(), | |
keys = self$get_keys() | |
), | |
id = "filter" | |
) |
I think we need to review this method:
teal.slice/R/FilteredDataset.R
Lines 292 to 301 in aab1255
get_varlabels = function(variables = NULL) { | |
checkmate::assert_character(variables, null.ok = TRUE, any.missing = FALSE) | |
labels <- formatters::var_labels(private$dataset, fill = FALSE) | |
if (is.null(labels)) { | |
return(NULL) | |
} | |
if (!is.null(variables)) labels <- labels[intersect(self$get_varnames(), variables)] | |
labels | |
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe something changes in formatters::var_labels
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wow, thanks for the details! I'll look into this.
ns <- NS(id) | ||
uiOutput(ns("summary"), class = "filter-card-summary") | ||
}, | ||
server_summary = function(id) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will do.
inst/css/filter-panel.css
Outdated
border-radius: 0.25rem; | ||
} | ||
|
||
.filter-card-header:hover { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good call. I'll look into this. Your screenshots look odd to me though because the hover color is supposed to apply to the title and summary. The idea is to focus on a card when it is collapsed. May be better on the whole card.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I looked at coloring the whole card on hover. This made it hard to separate the header from the body on an expanded card. I've added hover color for the body on an expanded card. This visually separates the header and body better. Please let me know what you think about this.
@gogonzo Few minor questions on the defined filter states
|
DateFilterState and DatetimeFilterState classes are separated as their ui/srv differ. Both classes use different functions to do stuff like formatting or handling timezones. We can't abstract these two classes into one
We can change the names of the classes but it won't change anything for the end user as these are not exported. If we go this way, then there is no reason for a ChoicesFilterState and we might have to split it into two classes which would be |
|
||
// if 2., we need to set the active card, which was clicked, to inactive | ||
// this is handled in the second 'if' block | ||
toggleFilterCard = function (el, containerId) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For border, I've made them darker so the visual separation is more obvious.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, there is something going on with the browser, but we can't use this excuse towards end-users. I'm fine with having this look on the feature branch "just to move on" but we have to be sure that we are able to fix it quickly. @asbates how do you think, is it doable to fix the appearance for chrome relatively fast?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What would be quick to you? I'm thinking the end of this week if I had to say. What's the alternative?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@gogonzo Thanks for the explanation, makes sense. Let's keep your proposed design then. |
I was under the impression the one-at-a-time only applies within an accordion not across accordions. @gogonzo what do you think?
I suspect this may be due to different browsers. Hoping this goes away with addressing other issues but keeping track of it just in case. |
@lcd2yyz Regarding "auto formatted to scientific notation if significant digit is >4". I've added rounding via I think this is close to what you're going for but not sure if it's exact. What do you think? |
Across accordions would be better, but still we can live with accordion within a dataset. But on the other side, if we are running custom js and css just to create accordions within each FilterState, why not to use something ready-to-use like shiny.semantic::accordion or the bootstrap accordion: |
I think for a decimal point we can use options so the app developer can change it if has a specific data which require better precision. We shouldn't fix it to one value Line 3 in 8a09ad5
|
We can absolutely use bootstrap instead. To be honest I didn't know that existed in bootstrap. The only thing is we would have to account for versions 3, 4, 5. I don't mind using another package like |
So the issue with having the possibility of each accordion having something open concerns cdisc data where filtering on ADSL triggers changes to the counts in other datasets - which brings in more reactivity (and possibly something similar within summarized experiments). However, if there's at most one filter card open on each dataset that will limit the reactivity substantially so it's probably ok |
And we should remember when possible to add the option into this vignette. |
I feel this example is slightly different - this is controlling a conscious switch from one variable class to another, that is not the inherent property of the variable. In conclusion, what @asbates has proposed looks good to me. |
@lcd2yyz I think this is just an example of using an option, not the option that would apply to this case. I will continue with a fixed value. I opened #190 to keep track of using an option. |
This is the first part of #129, allowing filter states to show either the inputs or a summary, with only one input visible at a time. This is done through a redesign of the filter cards and their container. The cards now have a header that displays the summary information. When a header is clicked, the input expands. Clicking a different header closes the first and expands the second. The 2 step process is so that the functionality can be introduced so other issues are not held up.
For part 2, I am planning on improving the styling. More specifically, truncating the filter state value when it is long. e.g. categorical with 20 levels selected needs to be shortened somehow. I would also like to make some general style updates to make it look nicer.