Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
# blockr.dock (development version)

* A parked block's status badge is drawn from the status blockr.core now
reports for it in place of `dormant`: the outcome of the block's last
check, `stale` once that is out of date, or `unevaluated` without one.
The `block_status_badge()` helper no longer returns `NA`, which it gave
for `dormant` to tell a persistent renderer such as the blockr.dag node
to keep the badge it drew last. A parked block that failed shows the
failed badge without being visited, and `unevaluated`, like `ready`,
carries none. Requires blockr.core with the `unevaluated` status (#485).

* The dock now states its evaluation demand as the blocks it holds eager,
in place of the per-block `required` channel blockr.core has retired.
Its board callback makes the board lazy by returning `eager()` with the
Expand Down Expand Up @@ -196,7 +205,7 @@
rewritten by the next drag. The native input gives the full gamut, plus
the platform's own dialog, eyedropper and keyboard handling (#396).

* A block whose inputs changed while it was dormant now carries a muted
* A block whose inputs changed while it was parked now carries a muted
grey status badge instead of none. Core's sixth eval status, `stale`,
fell through `block_status_badge()` to "no badge", so a block holding
an out-of-date result looked identical to a healthy one on both the
Expand Down
8 changes: 3 additions & 5 deletions R/block-meta.R
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,8 @@
#' - `block_status_badge()`: Derives a block's status badge from its eval
#' status and error count -- the single derivation the dock card icon and
#' the blockr.dag node badge share, so they always render the same colour
#' and styling. Returns a styling list (draw the badge), `NULL` (no badge),
#' or `NA` (indeterminate: the status is not computed, so leave any existing
#' badge unchanged).
#' and styling. Returns a styling list (draw the badge) or `NULL` (no
#' badge).
#'
#' @param blocks Blocks passed as `blocks` or `block` object
#'
Expand All @@ -32,8 +31,7 @@
#' each row corresponding to a block. Both `blk_color()` and
#' `blk_icon_data_uri()` return character vectors. `block_status_badge()`
#' returns a list with `color`, `label`, `size`, `ring` and `ring_color` (the
#' badge to draw), `NULL` for a status with no badge, or `NA` when the status
#' is indeterminate.
#' badge to draw), or `NULL` for a status with no badge.
#'
#' @rdname meta
#' @export
Expand Down
13 changes: 3 additions & 10 deletions R/plugin-block.R
Original file line number Diff line number Diff line change
Expand Up @@ -742,8 +742,8 @@ block_status_style <- function(status) {
}

#' @param status A block eval status: `stale`, `waiting`, `unset` and `failed`
#' carry a badge; `ready` carries none; `dormant` is indeterminate; any other
#' value yields no badge. The `size` field is the coloured dot's pixel
#' carry a badge; `ready` and `unevaluated` carry none; any other value
#' yields no badge. The `size` field is the coloured dot's pixel
#' diameter and `ring` its white outline width, both shared so the dock card
#' icon and the DAG node badge render identically.
#' @param error_count Number of error conditions the block has raised. A
Expand All @@ -754,7 +754,7 @@ block_status_style <- function(status) {
#' @export
block_status_badge <- function(status, error_count = 0L) {

# A stale block's conditions predate the upstream change that made it stale,
# A stale block's conditions predate the change that made it stale,
# and it has not re-run since, so they say nothing about whether it would
# still fail on its current inputs.
if (isTRUE(status == "stale")) {
Expand All @@ -765,13 +765,6 @@ block_status_badge <- function(status, error_count = 0L) {
status <- "failed"
}

# A dormant block has no computed status: return `NA` to signal "leave the
# badge as-is", so a persistent renderer (the DAG node) keeps its last-known
# badge rather than clearing it when the block drops out of the eval set.
if (isTRUE(status == "dormant")) {
return(NA)
}

block_status_style(status)
}

Expand Down
2 changes: 1 addition & 1 deletion inst/examples/block-status/app.R
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ library(blockr.dock)
# Two blocks in separate groups so both cards render: `a` evaluates and carries
# no status affordance, while `b` has no data input and settles on `waiting` --
# the one status that draws both a status dot and a status note. Tabbed panels
# would leave the background one `dormant`, which draws neither, so the grid
# would leave the background one `unevaluated`, which draws neither, so the grid
# splits them. The second view holds a third waiting block, whose card is built
# only on first visit -- the deferred case a card's status has to survive.
serve(
Expand Down
12 changes: 5 additions & 7 deletions man/meta.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

69 changes: 55 additions & 14 deletions tests/testthat/test-plugin-block.R
Original file line number Diff line number Diff line change
Expand Up @@ -872,8 +872,8 @@ test_that("block_status_style is the shared status-dot spec (#290)", {
expect_identical(block_status_style("unset")$color, "#eab308")
expect_identical(block_status_style("failed")$color, "#dc2626")

# `ready`, `dormant` and non-strings carry no indicator.
for (st in list("ready", "dormant", NULL, character(), c("a", "b"))) {
# The `ready` and `unevaluated` statuses and non-strings carry no indicator.
for (st in list("ready", "unevaluated", NULL, character(), c("a", "b"))) {
expect_null(block_status_style(st))
}
})
Expand All @@ -892,13 +892,10 @@ test_that("block_status_badge is the shared badge derivation (#314)", {
block_status_style("failed")
)

# `ready` and an absent status carry no badge.
# The `ready` and `unevaluated` statuses and an absent one carry no badge.
expect_null(block_status_badge("ready"))
expect_null(block_status_badge("unevaluated"))
expect_null(block_status_badge(NULL))

# `dormant` is indeterminate: `NA` tells a persistent renderer to keep the
# existing badge rather than clear it.
expect_identical(block_status_badge("dormant"), NA)
})

test_that("a stale block carries a muted badge (#408)", {
Expand Down Expand Up @@ -926,17 +923,61 @@ test_that("a stale block carries a muted badge (#408)", {
# a red dot would assert a failure nobody has observed on the current inputs.
expect_identical(block_status_badge("stale", 2L), stale)

# A dormant block keeps its error badge -- nothing about its inputs changed,
# so the last-known failure still describes them.
# Errors on an unevaluated block cannot predate a check it never had, so
# unlike a stale block's they still promote the badge to `failed`.
expect_identical(
block_status_badge("dormant", 2L),
block_status_badge("unevaluated", 2L),
block_status_style("failed")
)

# The body keeps its last-known output, so no placeholder note replaces it.
expect_null(block_status_note("stale"))
})

test_that("a parked block draws the badge of its last check (#485)", {

withr::local_options(blockr.background_construction_delay = 0)

# The tests above hand the badge statuses they spell out. Through core's own
# board server, a block checked off screen by an `evaluate` request goes on
# reporting what that check found once it is parked again, so it shows the
# failure without ever having been on screen.
board <- new_dock_board(
blocks = c(
a = new_dataset_block("iris"),
b = new_subset_block(subset = "no_such_column > 1")
),
links = c(ab = new_link("a", "b"))
)

testServer(
board_server,
{
session$flushReact()

expect_identical(rv$eval[["b"]](), "unevaluated")
expect_null(block_status_badge(rv$eval[["b"]]()))

board_update(list(evaluate = "b"))
session$flushReact()

expect_length(rv$evaluating(), 0L)
expect_identical(rv$eval[["b"]](), "failed")
expect_identical(
block_status_badge(rv$eval[["b"]]()),
block_status_style("failed")
)
},
args = list(
x = board,
plugins = blockr_app_plugins(board),
options = blockr_app_options(board),
callbacks = board_server_callback,
callback_location = "start"
)
)
})

test_that("block status indicator + note reflect eval status (#290)", {

waiting_dot <- block_status_dot_attrs("waiting")
Expand Down Expand Up @@ -971,12 +1012,12 @@ test_that("block status indicator + note reflect eval status (#290)", {
# `failed` keeps the error styling, so no placeholder note.
expect_null(block_status_note("failed"))

# A `ready` or `dormant` block, and an absent status, carry no affordance:
# the dot's attributes are all cleared rather than left stale from the last
# status.
# A `ready` or `unevaluated` block, and an absent status, carry no
# affordance: the dot's attributes are all cleared rather than left stale
# from the last status.
blank <- list(style = "", title = "", role = "", `aria-label` = "")

for (st in list("ready", "dormant", NULL, character(), c("a", "b"))) {
for (st in list("ready", "unevaluated", NULL, character(), c("a", "b"))) {
expect_identical(block_status_dot_attrs(st), blank)
expect_null(block_status_note(st))
}
Expand Down
Loading