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
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

* The return type for the data frame patch function now returns a list of `render.CellPatch` objects (which support `htmltools.TagNode` for the `value` attribute). These values will be set inside the data frame's `.data_view()` result. This also means that `.cell_patches()` will be a list of `render.CellPatch` objects. (#1526)

* Made sure all `@render.data_frame` cells that have been edited are now restored back to ready state to handle the off chance that the returned patches are at different locations the the original edit patches. (#1529)


### Other changes

## [0.10.2] - 2024-05-28
Expand Down
16 changes: 15 additions & 1 deletion js/data-frame/data-update.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,21 @@ export function updateCellsData({
draft[rowIndex]![columnIndex] = value;
});
});

// Set the old patches locations back to success state
// This may be overkill, but it guarantees that the incoming patches exit the saving state
patches.forEach(({ rowIndex, columnIndex, value }) => {
setCellEditMapAtLoc(rowIndex, columnIndex, (obj_draft) => {
// If the cell is still saving, then set it back to ready.
// If not, then something else has changed the cell state, so don't change it.
if (obj_draft.state !== CellStateEnum.EditSaving) return;

obj_draft.state = CellStateEnum.Ready;
obj_draft.value = value;
obj_draft.errorTitle = undefined;
});
});
// Set the new patches
newPatches.forEach(({ rowIndex, columnIndex, value }) => {
setCellEditMapAtLoc(rowIndex, columnIndex, (obj_draft) => {
obj_draft.value = value;
Expand All @@ -98,7 +113,6 @@ export function updateCellsData({
.catch((err: string) => {
patches.forEach(({ rowIndex, columnIndex, value }) => {
setCellEditMapAtLoc(rowIndex, columnIndex, (obj_draft) => {
// Do not overwrite value!
obj_draft.value = String(value);

obj_draft.state = CellStateEnum.EditFailure;
Expand Down
8 changes: 4 additions & 4 deletions shiny/www/py-shiny/data-frame/data-frame.js

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions shiny/www/py-shiny/data-frame/data-frame.js.map

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
from __future__ import annotations

import pandas as pd

from shiny.express import render, ui

df = pd.DataFrame(
{
"a": [1, 2, 3],
"b": [4, 5, 6],
"c": [7, 8, 9],
}
)

ui.markdown(
"""
* Edit a cell in column `b`.
* Column `a` should be updated to `a value`
* The edited cell should be back to a `ready` state
"""
)


@render.data_frame
def my_df():
return render.DataTable(
df,
editable=True,
)


# just testing if it works when editing another cell
@my_df.set_patches_fn
def edt(*, patches: tuple[render.CellPatch, ...]) -> list[render.CellPatch]:
patch = patches[0]
return [
render.CellPatch(
{
"row_index": patch["row_index"],
"column_index": 0,
"value": "a value",
},
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from playwright.sync_api import Page
from utils.deploy_utils import skip_if_not_chrome

from shiny.playwright import controller
from shiny.run import ShinyAppProc


@skip_if_not_chrome
def test_patch_exits_saving_state(
page: Page,
local_app: ShinyAppProc,
) -> None:
page.goto(local_app.url)

my_df = controller.OutputDataFrame(page, "my_df")

my_df.expect_cell("1", row=0, col=0)
my_df.expect_cell("4", row=0, col=1)

my_df.expect_class_state("ready", row=0, col=0)
my_df.set_cell("test value", row=0, col=1)

my_df.expect_cell("4", row=0, col=1)
my_df.expect_cell("a value", row=0, col=0)
my_df.expect_class_state("success", row=0, col=0)

my_df.expect_class_state("ready", row=0, col=1)
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ def server(input: Inputs, output: Outputs, session: Session) -> None:
@render.data_frame
def penguins_df():
return render.DataGrid(
data=load_penguins_raw(), # pyright: ignore[reportUnknownArgumentType]
data=load_penguins_raw().head(
5
), # pyright: ignore[reportUnknownArgumentType]
filters=True,
editable=True,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from shiny.run import ShinyAppProc


def test_validate_data_edit_mode(page: Page, local_app: ShinyAppProc) -> None:
def test_validate_data_save(page: Page, local_app: ShinyAppProc) -> None:
page.goto(local_app.url)

data_frame = controller.OutputDataFrame(page, "penguins_df")
Expand Down