Skip to content

Commit

Permalink
Dash for R v0.9.0 (#239)
Browse files Browse the repository at this point in the history
* Fix setCallbackContext for wildcard and ordinary inputs (#237)
* Update dash-renderer to v1.8.3

Co-authored-by: HammadTheOne <hammadkhan@plotly.com>
  • Loading branch information
rpkyle and HammadTheOne authored Oct 31, 2020
1 parent add8dd3 commit edbcc04
Show file tree
Hide file tree
Showing 9 changed files with 167 additions and 24 deletions.
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,18 @@
All notable changes to `dash` will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).

## [0.9.0] - 2020-10-31

### Fixed
- Fixes a minor bug in `setCallbackContext` (described in [#236](https://github.com/plotly/dashR/issues/236)) which prevented pattern-matching callbacks from working properly if one or more `input` statements did not include a selector. [#237](https://github.com/plotly/dashR/pull/237)

### Changed

- Dash for R now depends on v1.1.1 of `dashHtmlComponents`
- Dash for R now depends on v1.13.0 of `dashCoreComponents`
- Dash for R now depends on v4.11.0 of `dashTable`
- `dash-renderer` version is now v1.8.3

## [0.8.0] - 2020-10-27
### Fixed
- Usage of `glue` has been corrected to address [#232](https://github.com/plotly/dashR/issues/232) via [#233](https://github.com/plotly/dashR/pull/233).
Expand Down
14 changes: 7 additions & 7 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
Package: dash
Title: An Interface to the Dash Ecosystem for Authoring Reactive Web Applications
Version: 0.8.0
Version: 0.9.0
Authors@R: c(person("Chris", "Parmer", role = c("aut"), email = "chris@plotly.com"), person("Ryan Patrick", "Kyle", role = c("aut", "cre"), comment = c(ORCID = "0000-0001-5829-9867"), email = "ryan@plotly.com"), person("Carson", "Sievert", role = c("aut"), comment = c(ORCID = "0000-0002-4958-2844")), person("Hammad", "Khan", role = c("aut"), comment = c(ORCID = "0000-0003-2479-9841"), email = "hammadkhan@plotly.com"), person(family = "Plotly Technologies", role = "cph"))
Description: A framework for building analytical web applications, Dash offers a pleasant and productive development experience. No JavaScript required.
Depends:
R (>= 3.0.2)
Imports:
dashHtmlComponents (== 1.0.3),
dashCoreComponents (== 1.10.2),
dashTable (== 4.9.0),
dashHtmlComponents (== 1.1.1),
dashCoreComponents (== 1.13.0),
dashTable (== 4.11.0),
R6,
fiery (> 1.0.0),
routr (> 0.2.0),
Expand All @@ -33,9 +33,9 @@ Collate:
'imports.R'
'print.R'
'internal.R'
Remotes: plotly/dash-html-components@e63acfa,
plotly/dash-core-components@0770afb,
plotly/dash-table@75ac3d9
Remotes: plotly/dash-html-components@7209e0a,
plotly/dash-core-components@91a424e,
plotly/dash-table@aa519b7
License: MIT + file LICENSE
Encoding: UTF-8
LazyData: true
Expand Down
24 changes: 12 additions & 12 deletions R/internal.R
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@
all_files = FALSE),
class = "html_dependency"),
`dash-renderer-dev` = structure(list(name = "dash-renderer",
version = "1.8.2",
src = list(href = "https://unpkg.com/dash-renderer@1.8.2",
file = "lib/dash-renderer@1.8.2"),
version = "1.8.3",
src = list(href = "https://unpkg.com/dash-renderer@1.8.3",
file = "lib/dash-renderer@1.8.3"),
meta = NULL,
script = "dash-renderer/dash_renderer.dev.js",
stylesheet = NULL,
Expand All @@ -48,9 +48,9 @@
all_files = FALSE),
class = "html_dependency"),
`dash-renderer-map-dev` = structure(list(name = "dash-renderer",
version = "1.8.2",
src = list(href = "https://unpkg.com/dash-renderer@1.8.2",
file = "lib/dash-renderer@1.8.2"),
version = "1.8.3",
src = list(href = "https://unpkg.com/dash-renderer@1.8.3",
file = "lib/dash-renderer@1.8.3"),
meta = NULL,
script = "dash-renderer/dash_renderer.dev.js.map",
stylesheet = NULL,
Expand All @@ -60,9 +60,9 @@
all_files = FALSE),
class = "html_dependency"),
`dash-renderer-prod` = structure(list(name = "dash-renderer",
version = "1.8.2",
src = list(href = "https://unpkg.com/dash-renderer@1.8.2",
file = "lib/dash-renderer@1.8.2"),
version = "1.8.3",
src = list(href = "https://unpkg.com/dash-renderer@1.8.3",
file = "lib/dash-renderer@1.8.3"),
meta = NULL,
script = "dash-renderer/dash_renderer.min.js",
stylesheet = NULL,
Expand All @@ -72,9 +72,9 @@
all_files = FALSE),
class = "html_dependency"),
`dash-renderer-map-prod` = structure(list(name = "dash-renderer",
version = "1.8.2",
src = list(href = "https://unpkg.com/dash-renderer@1.8.2",
file = "lib/dash-renderer@1.8.2"),
version = "1.8.3",
src = list(href = "https://unpkg.com/dash-renderer@1.8.3",
file = "lib/dash-renderer@1.8.3"),
meta = NULL,
script = "dash-renderer/dash_renderer.min.js.map",
stylesheet = NULL,
Expand Down
14 changes: 9 additions & 5 deletions R/utils.R
Original file line number Diff line number Diff line change
Expand Up @@ -1054,26 +1054,30 @@ setCallbackContext <- function(callback_elements) {
function(x) {
input_id <- splitIdProp(x)[1]
prop <- splitIdProp(x)[2]

# The following conditionals check whether the callback is a pattern-matching callback and if it has been triggered.
if (startsWith(input_id, "{")){
id_match <- vapply(callback_elements$inputs, function(x) {
x <- unlist(x)
any(x[grepl("id.", names(x))] %in% jsonlite::fromJSON(input_id)[[1]])
}, logical(1))[[1]]
} else {
id_match <- vapply(callback_elements$inputs, function(x) x$id %in% input_id, logical(1))
id_match <- vapply(callback_elements$inputs, function(x) {
unlist(x)
any(x$id %in% input_id)}, logical(1))
}

if (startsWith(input_id, "{")){
prop_match <- vapply(callback_elements$inputs, function(x) {
x <- unlist(x)
any(x[names(x) == "property"] %in% prop)
}, logical(1))[[1]]
} else {
prop_match <- vapply(callback_elements$inputs, function(x) x$property %in% prop, logical(1))
prop_match <- vapply(callback_elements$inputs, function(x) {
unlist(x)
any(x$property %in% prop)}, logical(1))
}

if (startsWith(input_id, "{")){
if (length(callback_elements$inputs) == 1 || !is.null(unlist(callback_elements$inputs, recursive = F)$value)) {
value <- sapply(callback_elements$inputs[id_match & prop_match], `[[`, "value")
Expand Down
127 changes: 127 additions & 0 deletions tests/integration/callbacks/test_pattern_matching.py
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,120 @@
"""


graphs_app = """
library(dash)
library(dashHtmlComponents)
library(dashCoreComponents)
library(plotly)
df <- read.csv(
file = "https://raw.githubusercontent.com/plotly/datasets/master/gapminderDataFiveYear.csv",
stringsAsFactor=FALSE,
check.names=FALSE
)
app <- Dash$new()
app$layout(
htmlDiv(
list(
htmlDiv(
list(
dccDropdown(options = lapply(unique(df[,"country"]), function(x) {
list(label = x, value = x)
}),
value = "Canada",
id = "country",
style = list(display = "inline-block",
width = 200)
),
htmlButton(
"add Chart",
id = "add-chart",
n_clicks = 0,
style = list(display = "inline-block")
)
)
),
htmlDiv(id = "container", children=list()),
htmlDiv(id = "output-delay")
)
)
)
create_figure <- function(df, column_x, column_y, country) {
df <- df[which(df[, "country"] == country),]
if (column_x == "year") {
fig <- plot_ly(df, x = df[,column_x], y = df[,column_y], name = column_x, type = "scatter", mode = "lines")
} else {
fig <- plot_ly(df, x = df[,column_x], y = df[,column_y], name = column_x, type = "scatter", mode = "markers")
}
fig <- plotly::layout(fig, plot_bgcolor="lightblue", xaxis = list(title=""),
yaxis = list(title=""), title=list(text=paste(country, column_y, "vs", column_x),
xanchor="right", margin_l=10, margin_r=0, margin_b=30))
return(fig)
}
app$callback(
output = list(
output(id = "container", property = "children"),
output(id = "output-delay", property = "children")
),
params = list(
input(id = "add-chart", property = "n_clicks"),
state(id = "country", property = "value"),
state(id = "container", property = "children")
),
function(n_clicks, country, children) {
default_column_x <- "year"
default_column_y <- "gdpPercap"
new_element <- htmlDiv(
style = list(width = "23%", display = "inline-block", outline = "thin lightgrey solid", padding = 10),
children = list(
dccGraph(
id = list(type = "dynamic-output", index = n_clicks),
style = list(height = 300),
figure = create_figure(df, default_column_x, default_column_y, country)
),
dccDropdown(
id = list(type = "dynamic-dropdown-x", index = n_clicks),
options = lapply(colnames(df), function(x) {
list(label = x, value = x)
}),
value = default_column_x
),
dccDropdown(
id = list(type = "dynamic-dropdown-y", index = n_clicks),
options = lapply(colnames(df), function(x) {
list(label = x, value = x)
}),
value = default_column_y
)
)
)
children <- c(children, list(new_element))
return(list(children, n_clicks))
}
)
app$callback(
output(id = list("index" = MATCH, "type" = "dynamic-output"), property = "figure"),
params = list(
input(id = list("index" = MATCH, "type" = "dynamic-dropdown-x"), property = "value"),
input(id = list("index" = MATCH, "type" = "dynamic-dropdown-y"), property = "value"),
input(id = "country", property = "value")
),
function(column_x, column_y, country) {
return(create_figure(df, column_x, column_y, country))
}
)
app$run_server()
"""


def test_rpmc001_pattern_matching_all(dashr):
dashr.start_server(all_app)
dashr.find_element("#add-filter").click()
Expand Down Expand Up @@ -370,3 +484,16 @@ def test_rpmc004_pattern_matching_todo(dashr):
dashr.find_element("#add").click()
dashr.find_element('#\\{\\"index\\"\\:1\\,\\"type\\"\\:\\"done\\"\\}').click()
assert dashr.wait_for_text_to_equal("#totals", "1 of 1 items completed - 100%")


def test_rpmc005_pattern_matching_graphs(dashr):
dashr.start_server(graphs_app)
dashr.select_dcc_dropdown("#country", "Cameroon")
dashr.wait_for_text_to_equal("#output-delay", "0")
dashr.find_element("#add-chart").click()
dashr.wait_for_text_to_equal("#output-delay", "1")
dashr.find_element('#\\{\\"index\\"\\:1\\,\\"type\\"\\:\\"dynamic-output\\"\\}')
dashr.select_dcc_dropdown('#\\{\\"index\\"\\:1\\,\\"type\\"\\:\\"dynamic-dropdown-x\\"\\}', "year")
dashr.select_dcc_dropdown('#\\{\\"index\\"\\:1\\,\\"type\\"\\:\\"dynamic-dropdown-y\\"\\}', "pop")
dashr.percy_snapshot("r-pmc-graphs")
dashr.wait_for_element('#\\{\\"index\\"\\:1\\,\\"type\\"\\:\\"dynamic-output\\"\\}')

0 comments on commit edbcc04

Please sign in to comment.