mirror of
https://github.com/gradio-app/gradio.git
synced 2025-02-17 11:29:58 +08:00
Ensure checked files persist after FileExplorer rerenders (#6691)
* add tree_updated flag * add changeset * add changeset * test * generate notebooks --------- Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com>
This commit is contained in:
parent
053bec98be
commit
128ab5d65b
6
.changeset/strong-cooks-talk.md
Normal file
6
.changeset/strong-cooks-talk.md
Normal file
@ -0,0 +1,6 @@
|
||||
---
|
||||
"@gradio/fileexplorer": patch
|
||||
"gradio": patch
|
||||
---
|
||||
|
||||
fix:Ensure checked files persist after FileExplorer rerenders
|
@ -1 +1 @@
|
||||
{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: file_explorer_component_events"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "os.mkdir('dir1')\n", "!wget -q -O dir1/bar.txt https://github.com/gradio-app/gradio/raw/main/demo/file_explorer_component_events/dir1/bar.txt\n", "!wget -q -O dir1/foo.txt https://github.com/gradio-app/gradio/raw/main/demo/file_explorer_component_events/dir1/foo.txt\n", "os.mkdir('dir2')\n", "!wget -q -O dir2/baz.png https://github.com/gradio-app/gradio/raw/main/demo/file_explorer_component_events/dir2/baz.png\n", "!wget -q -O dir2/foo.png https://github.com/gradio-app/gradio/raw/main/demo/file_explorer_component_events/dir2/foo.png"]}, {"cell_type": "code", "execution_count": null, "id": "44380577570523278879349135829904343037", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "from pathlib import Path\n", "\n", "base_root = Path(__file__).parent.resolve()\n", "\n", "with gr.Blocks() as demo:\n", " dd = gr.Dropdown(label=\"Select File Explorer Root\",\n", " value=str(base_root / \"dir1\"),\n", " choices=[str(base_root / \"dir1\"), str(base_root / \"dir2\")])\n", " fe = gr.FileExplorer(root=str(base_root / \"dir1\"), interactive=True)\n", " dd.select(lambda s: gr.FileExplorer(root=s), inputs=[dd], outputs=[fe])\n", "\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
|
||||
{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: file_explorer_component_events"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "os.mkdir('dir1')\n", "!wget -q -O dir1/bar.txt https://github.com/gradio-app/gradio/raw/main/demo/file_explorer_component_events/dir1/bar.txt\n", "!wget -q -O dir1/foo.txt https://github.com/gradio-app/gradio/raw/main/demo/file_explorer_component_events/dir1/foo.txt\n", "os.mkdir('dir2')\n", "!wget -q -O dir2/baz.png https://github.com/gradio-app/gradio/raw/main/demo/file_explorer_component_events/dir2/baz.png\n", "!wget -q -O dir2/foo.png https://github.com/gradio-app/gradio/raw/main/demo/file_explorer_component_events/dir2/foo.png"]}, {"cell_type": "code", "execution_count": null, "id": "44380577570523278879349135829904343037", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "from pathlib import Path\n", "\n", "base_root = Path(__file__).parent.resolve()\n", "\n", "with gr.Blocks() as demo:\n", " dd = gr.Dropdown(\n", " label=\"Select File Explorer Root\",\n", " value=str(base_root / \"dir1\"),\n", " choices=[str(base_root / \"dir1\"), str(base_root / \"dir2\")],\n", " )\n", " fe = gr.FileExplorer(root=str(base_root / \"dir1\"), interactive=True)\n", " dd.select(lambda s: gr.FileExplorer(root=s), inputs=[dd], outputs=[fe])\n", "\n", " with gr.Row():\n", " a = gr.Textbox(elem_id=\"input-box\")\n", " a.change(lambda x: x, inputs=[a])\n", "\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
|
@ -4,12 +4,18 @@ from pathlib import Path
|
||||
base_root = Path(__file__).parent.resolve()
|
||||
|
||||
with gr.Blocks() as demo:
|
||||
dd = gr.Dropdown(label="Select File Explorer Root",
|
||||
value=str(base_root / "dir1"),
|
||||
choices=[str(base_root / "dir1"), str(base_root / "dir2")])
|
||||
dd = gr.Dropdown(
|
||||
label="Select File Explorer Root",
|
||||
value=str(base_root / "dir1"),
|
||||
choices=[str(base_root / "dir1"), str(base_root / "dir2")],
|
||||
)
|
||||
fe = gr.FileExplorer(root=str(base_root / "dir1"), interactive=True)
|
||||
dd.select(lambda s: gr.FileExplorer(root=s), inputs=[dd], outputs=[fe])
|
||||
|
||||
with gr.Row():
|
||||
a = gr.Textbox(elem_id="input-box")
|
||||
a.change(lambda x: x, inputs=[a])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
demo.launch()
|
@ -1,4 +1,4 @@
|
||||
import { test } from "@gradio/tootils";
|
||||
import { test, expect } from "@gradio/tootils";
|
||||
|
||||
test("File Explorer is interactive and re-runs the server_fn when root is updated", async ({
|
||||
page
|
||||
@ -26,4 +26,14 @@ test("File Explorer is interactive and re-runs the server_fn when root is update
|
||||
.filter({ hasText: "foo.png" })
|
||||
.getByRole("checkbox")
|
||||
.check();
|
||||
|
||||
await page.locator("#input-box").getByTestId("textbox").fill("test");
|
||||
|
||||
await expect(
|
||||
page.locator("span").filter({ hasText: "baz.png" }).getByRole("checkbox")
|
||||
).toBeChecked();
|
||||
|
||||
await expect(
|
||||
page.locator("span").filter({ hasText: "foo.png" }).getByRole("checkbox")
|
||||
).toBeChecked();
|
||||
});
|
||||
|
@ -30,7 +30,7 @@ interface FSStore {
|
||||
}
|
||||
|
||||
export const make_fs_store = (): FSStore => {
|
||||
const { subscribe, set, update } = writable<Node[] | null>(null);
|
||||
const { subscribe, set } = writable<Node[] | null>(null);
|
||||
let root: Node = {
|
||||
type: "folder",
|
||||
path: "",
|
||||
@ -38,16 +38,18 @@ export const make_fs_store = (): FSStore => {
|
||||
children_visible: false,
|
||||
parent: null
|
||||
};
|
||||
let tree_updated = false;
|
||||
|
||||
function create_fs_graph(serialised_node: SerialisedNode[]): void {
|
||||
root.children = process_tree(serialised_node);
|
||||
tree_updated = true;
|
||||
set(root.children);
|
||||
}
|
||||
|
||||
let old_checked_paths: string[][] = [];
|
||||
|
||||
function set_checked_from_paths(checked_paths: string[][]): string[][] {
|
||||
if (dequal(checked_paths, old_checked_paths)) {
|
||||
if (dequal(checked_paths, old_checked_paths) && !tree_updated) {
|
||||
return checked_paths;
|
||||
}
|
||||
old_checked_paths = checked_paths;
|
||||
@ -88,6 +90,8 @@ export const make_fs_store = (): FSStore => {
|
||||
|
||||
set(root.children!);
|
||||
|
||||
tree_updated = false;
|
||||
|
||||
return new_checked_paths;
|
||||
}
|
||||
|
||||
@ -235,7 +239,6 @@ function check_node_and_children(
|
||||
checked: boolean,
|
||||
checked_nodes: Node[]
|
||||
): Node[] {
|
||||
// console.log(node, checked);
|
||||
if (node === null || node === undefined) return checked_nodes;
|
||||
for (let i = 0; i < node.length; i++) {
|
||||
node[i].checked = checked;
|
||||
|
Loading…
Reference in New Issue
Block a user