Skip to content

Commit d2aa6d4

Browse files
authored
Merge pull request #199 from rstudio/barbara/changes
Updates
2 parents 6472511 + cded9e8 commit d2aa6d4

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+2451
-233
lines changed

.Rbuildignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
^.*\.Rproj$
22
^\.Rproj\.user$
33
^tools$
4+
^srcjs$
45
^tests-manual$
56
^\.travis\.yml$
67
^appveyor\.yml$

DESCRIPTION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,4 @@ Imports:
1818
shiny (>= 0.12.1),
1919
htmltools (>= 0.2.6)
2020
BugReports: https://github.com/rstudio/shinydashboard
21-
RoxygenNote: 5.0.1
21+
RoxygenNote: 6.0.1

NEWS.md

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,33 @@
1-
shinydashboard 0.5.3.9000
1+
shinydashboard 0.6
22
=========================
33

4+
This release of shinydashboard was aimed at both fixing bugs and also bringing the package up to speed with users' requests and Shiny itself (especially fully bringing [bookmarkable state](https://shiny.rstudio.com/articles/bookmarking-state.html) to shinydashboard's sidebar). In addition to the changes listed below, we also added a [new "Behavior" section to the shinydashboard website](https://rstudio.github.io/shinydashboard/behavior.html) to explain this release's two biggest new features.
5+
6+
7+
## Full changelog
8+
9+
### New features
10+
11+
* Address [#179](https://github.com/rstudio/shinydashboard/issues/179) support for bookmarking the expanded/collapsed state of the whole sidebar. (commit [e71c93f](https://github.com/rstudio/shinydashboard/pull/199/commits/e71c93fa7a71f229e725efd4a7867e431cd57679))
12+
13+
* Added Shiny input to keep track of which sidebar `menuItem` is expanded (if any), which makes bookmarking the exact state of the sidebar trivial. (commit [6901b90](https://github.com/rstudio/shinydashboard/pull/199/commits/6901b90b8c866b89d02514cfc01fdfab88175602))
14+
15+
### Minor new features and improvements
16+
417
* Addressed [#165](https://github.com/rstudio/shinydashboard/issues/165): added a new optional argument, called `headerText` to the `dropdownMenu()` function. If provided by the user, this text (instead of the default) will be shown on the header of the menu (only visible when the menu is expanded). See `?dropdownMenu` for more details. [#207](https://github.com/rstudio/shinydashboard/pull/207)
518

19+
* Split JS files. (commit [ea91503](https://github.com/rstudio/shinydashboard/pull/199/commits/ea915038ae2126f48c15e3aac41782a22b16c506)). More updates to Gruntfile and structure. (commit [4e80616](https://github.com/rstudio/shinydashboard/pull/199/commits/4e80616c5b3aa0dc73022dc815288b5ba7c35be0))
20+
21+
* Better shown/hidden mechanic for Shiny inputs inside collapsible `menuItem`s. (commit [6901b90](https://github.com/rstudio/shinydashboard/pull/199/commits/6901b90b8c866b89d02514cfc01fdfab88175602))
22+
23+
* Added hack on adminLTE/app.js in order to make the `slideUp`/`slideDown` css transitions look reasonable when its content is initially empty (use case is for hidden Shiny outputs that are not rendered until the first time the `menuItem` is expanded and reveal them -- i.e. first time that `trigger("shown")` is called). (commit [25725a6](https://github.com/rstudio/shinydashboard/pull/199/commits/25725a67ce3dd841786dd82b0e46624c6a7d4722))
24+
25+
* Added manual tests for bookmarking and the shown/hidden events that happen on the sidebar. (commit [9e3e55d](https://github.com/rstudio/shinydashboard/pull/199/commits/9e3e55de8cc63d4bdd179251cd53eeb845441d3d))
26+
27+
### Bug fixes
28+
29+
* Fixed [#71](https://github.com/rstudio/shinydashboard/issues/71) and [#87](https://github.com/rstudio/shinydashboard/issues/87): detect and enforce selected tab for dynamic sidebar menus by calling `ensureActivatedTab()` for these. (commit [9b88a79](https://github.com/rstudio/shinydashboard/pull/199/commits/9b88a790df058432165ca3b483b5bbfe1d267326))
30+
631
* Fixed [#127](https://github.com/rstudio/shinydashboard/issues/127) and [#177](https://github.com/rstudio/shinydashboard/issues/177): previously, if `dashboardSidebar()` was called with an explicit `width` parameter, mobile rendering would look weird (the sidebar wouldn't completely disappear when it was collapsed, and content in the dashboard body would be hidden under the still-visible sidebar). ([#204](https://github.com/rstudio/shinydashboard/pull/204))
732

833
* Fixed [#79](https://github.com/rstudio/shinydashboard/issues/79): Re-enable slight css transition when the sidebar is expanded/collapsed. ([#205](https://github.com/rstudio/shinydashboard/pull/205)).
@@ -15,10 +40,14 @@ shinydashboard 0.5.3.9000
1540

1641
* Fixed [#62](https://github.com/rstudio/shinydashboard/issues/62): make images resize when the sidebar collapses/expands. [#185](https://github.com/rstudio/shinydashboard/pull/185)
1742

18-
* Addressed [#178](https://github.com/rstudio/shinydashboard/issues/178): switch from `npm` to `yarn`. Also upgraded all yarn packages to the `latest` tag (all major changes). [#184](https://github.com/rstudio/shinydashboard/pull/184)
19-
2043
* Fixed [#176](https://github.com/rstudio/shinydashboard/issues/176) (making buttons look good on the sidebar) by giving Shiny action buttons and links some margin space. ([#182](https://github.com/rstudio/shinydashboard/pull/182))
2144

45+
### Library updates
46+
47+
* Update documentation to newest version of roxygen. (commit [#541d3c1](https://github.com/rstudio/shinydashboard/pull/199/commits/541d3c13467446c8e89b178d95b0984729559059))
48+
49+
* Addressed [#178](https://github.com/rstudio/shinydashboard/issues/178): switch from `npm` to `yarn`. Also upgraded all yarn packages to the `latest` tag (all major changes). [#184](https://github.com/rstudio/shinydashboard/pull/184)
50+
2251
* Updated to AdminLTE 2.3.11. ([#181](https://github.com/rstudio/shinydashboard/pull/181))
2352

2453
shinydashboard 0.5.3

R/dashboardPage.R

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,9 @@ dashboardPage <- function(header, sidebar, body, title = NULL,
5757
body
5858
)
5959

60-
# if the sidebar has the class "start-collapsed", it means that the user set
61-
# the `collapsed` argument of `dashboardSidebar` to TRUE
62-
collapsed <- "start-collapsed" %in% strsplit(sidebar$attribs$class, " ")[[1]]
60+
# if the sidebar has the attribute `data-collapsed = "true"`, it means that
61+
# the user set the `collapsed` argument of `dashboardSidebar` to TRUE
62+
collapsed <- findAttribute(sidebar, "data-collapsed", "true")
6363

6464
addDeps(
6565
tags$body(

R/dashboardSidebar.R

Lines changed: 48 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -117,12 +117,20 @@ dashboardSidebar <- function(..., disable = FALSE, width = NULL, collapsed = FAL
117117
'))))
118118
}
119119

120+
# If we're restoring a bookmarked app, this holds the value of whether or not the
121+
# sidebar was collapsed. If this is not the case, the default is whatever the user
122+
# specified in the `collapsed` argument.
123+
dataValue <- shiny::restoreInput(id = "sidebarCollapsed", default = collapsed)
124+
if (disable) dataValue <- TRUE # this is a workaround to fix #209
125+
dataValueString <- if (dataValue) "true" else "false"
126+
120127
# The expanded/collapsed state of the sidebar is actually set by adding a
121128
# class to the body (not to the sidebar). However, it makes sense for the
122129
# `collapsed` argument to belong in this function. So this information is
123-
# just passed through (also as a class) to the `dashboardPage()` function
124-
tags$aside(class = paste("main-sidebar", if (collapsed) "start-collapsed"),
125-
custom_css,
130+
# just passed through (as the `data-collapsed` attribute) to the
131+
# `dashboardPage()` function
132+
tags$aside(
133+
class = "main-sidebar", `data-collapsed` = dataValueString, custom_css,
126134
tags$section(
127135
class = "sidebar",
128136
`data-disable` = if (disable) 1 else NULL,
@@ -236,6 +244,13 @@ sidebarSearchForm <- function(textId, buttonId, label = "Search...",
236244
#' @param selected If \code{TRUE}, this \code{menuItem} or \code{menuSubItem}
237245
#' will start selected. If no item have \code{selected=TRUE}, then the first
238246
#' \code{menuItem} will start selected.
247+
#' @param expandedName A unique name given to each \code{menuItem} that serves
248+
#' to indicate which one (if any) is currently expanded. (This is only applicable
249+
#' to \code{menuItem}s that have children and it is mostly only useful for
250+
#' bookmarking state.)
251+
#' @param startExpanded Should this \code{menuItem} be expanded on app startup?
252+
#' (This is only applicable to \code{menuItem}s that have children, and only
253+
#' one of these can be expanded at any given time).
239254
#' @param ... For menu items, this may consist of \code{\link{menuSubItem}}s.
240255
#' @param .list An optional list containing items to put in the menu Same as the
241256
#' \code{...} arguments, but in list format. This can be useful when working
@@ -263,7 +278,9 @@ sidebarMenu <- function(..., id = NULL, .list = NULL) {
263278
# Given a menuItem and a logical value for `selected`, set the
264279
# data-start-selected attribute to the appropriate value (1 or 0).
265280
selectItem <- function(item, selected) {
266-
if (length(item$children) == 0) {
281+
282+
# in the cases that the children of menuItems are NOT menuSubItems
283+
if (is.atomic(item) || length(item$children) == 0) {
267284
return(item)
268285
}
269286

@@ -274,6 +291,7 @@ sidebarMenu <- function(..., id = NULL, .list = NULL) {
274291
# data-start-selected="1". The []<- assignment is to preserve
275292
# attributes.
276293
item$children[] <- lapply(item$children, function(child) {
294+
277295
# Find the appropriate <a> child
278296
if (tagMatches(child, name = "a", `data-toggle` = "tab")) {
279297
child$attribs[["data-start-selected"]] <- value
@@ -328,18 +346,25 @@ sidebarMenu <- function(..., id = NULL, .list = NULL) {
328346
item
329347
})
330348
}
349+
# This is a 0 height div, whose only purpose is to hold the tabName of the currently
350+
# selected menuItem in its `data-value` attribute. This is the DOM element that is
351+
# bound to tabItemInputBinding in the JS side.
352+
items[[length(items) + 1]] <- div(id = id,
353+
class = "sidebarMenuSelectedTabItem", `data-value` = selectedTabName %OR% "null")
331354
}
332355

333356
# Use do.call so that we don't add an extra list layer to the children of the
334357
# ul tag. This makes it a little easier to traverse the tree to search for
335358
# selected items to restore.
336-
do.call(tags$ul, c(id = id, class = "sidebar-menu", items))
359+
do.call(tags$ul, c(class = "sidebar-menu", items))
337360
}
338361

339362
#' @rdname sidebarMenu
340363
#' @export
341364
menuItem <- function(text, ..., icon = NULL, badgeLabel = NULL, badgeColor = "green",
342-
tabName = NULL, href = NULL, newtab = TRUE, selected = NULL) {
365+
tabName = NULL, href = NULL, newtab = TRUE, selected = NULL,
366+
expandedName = as.character(gsub("[[:space:]]", "", text)),
367+
startExpanded = FALSE) {
343368
subItems <- list(...)
344369

345370
if (!is.null(icon)) tagAssert(icon, type = "i")
@@ -394,6 +419,18 @@ menuItem <- function(text, ..., icon = NULL, badgeLabel = NULL, badgeColor = "gr
394419
)
395420
}
396421

422+
# If we're restoring a bookmarked app, this holds the value of what menuItem (if any)
423+
# was expanded (this has be to stored separately from the selected menuItem, since
424+
# these actually independent in AdminLTE). If no menuItem was expanded, `dataExpanded`
425+
# is NULL. However, we want to this input to get passed on (and not dropped), so we
426+
# do `%OR% ""` to assure this.
427+
default <- if (startExpanded) expandedName else ""
428+
dataExpanded <- shiny::restoreInput(id = "sidebarItemExpanded", default) %OR% ""
429+
430+
# If `dataExpanded` is not the empty string, we need to check that it is eqaul to the
431+
# this menuItem's `expandedName``
432+
isExpanded <- nzchar(dataExpanded) && (dataExpanded == expandedName)
433+
397434
tags$li(class = "treeview",
398435
a(href = href,
399436
icon,
@@ -403,7 +440,11 @@ menuItem <- function(text, ..., icon = NULL, badgeLabel = NULL, badgeColor = "gr
403440
# Use do.call so that we don't add an extra list layer to the children of the
404441
# ul tag. This makes it a little easier to traverse the tree to search for
405442
# selected items to restore.
406-
do.call(tags$ul, c(class = "treeview-menu", subItems))
443+
do.call(tags$ul, c(
444+
class = paste0("treeview-menu", if (isExpanded) " menu-open" else ""),
445+
style = paste0("display: ", if (isExpanded) "block;" else "none;"),
446+
`data-expanded` = expandedName,
447+
subItems))
407448
)
408449
}
409450

R/deps.R

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,11 @@ appendDependencies <- function(x, value) {
1313
addDeps <- function(x) {
1414
if (getOption("shiny.minified", TRUE)) {
1515
adminLTE_js <- "app.min.js"
16+
shinydashboard_js <- "shinydashboard.min.js"
1617
adminLTE_css <- c("AdminLTE.min.css", "_all-skins.min.css")
1718
} else {
1819
adminLTE_js <- "app.js"
20+
shinydashboard_js <- "shinydashboard.js"
1921
adminLTE_css <- c("AdminLTE.css", "_all-skins.css")
2022
}
2123

@@ -28,7 +30,7 @@ addDeps <- function(x) {
2830
htmlDependency("shinydashboard",
2931
as.character(utils::packageVersion("shinydashboard")),
3032
c(file = system.file(package = "shinydashboard")),
31-
script = "shinydashboard.js",
33+
script = shinydashboard_js,
3234
stylesheet = "shinydashboard.css"
3335
)
3436
)

R/utils.R

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,3 +198,24 @@ tagMatches <- function(item, ..., id = NULL, name = NULL, class = NULL) {
198198

199199
TRUE
200200
}
201+
202+
# This function takes a DOM element/tag object and reccurs within it until
203+
# it finds a child which has an attribute called `attr` and with value `val`
204+
# (and returns TRUE). If it finds an element with an attribute called `attr`
205+
# whose value is NOT `val`, it returns FALSE. If it exhausts all children
206+
# and it doesn't find an element with an attribute called `attr`, it also
207+
# returns FALSE
208+
findAttribute <- function(x, attr, val) {
209+
if (is.atomic(x)) return(FALSE) # exhausted this branch of the tree
210+
211+
if (!is.null(x$attribs[[attr]])) { # found attribute called `attr`
212+
if (identical(x$attribs[[attr]], val)) return(TRUE)
213+
else return(FALSE)
214+
}
215+
216+
if (length(x$children) > 0) { # recursion
217+
return(any(unlist(lapply(x$children, findAttribute, attr, val))))
218+
}
219+
220+
return(FALSE) # found no attribute called `attr`
221+
}

inst/AdminLTE/AdminLTE.min.css

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

inst/AdminLTE/_all-skins.min.css

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

inst/AdminLTE/app.js

100755100644
Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)