Skip to content

Commit

Permalink
Few File component drag and drop (#7141)
Browse files Browse the repository at this point in the history
* file comp fixes

* add changeset

* test fixes

* undo pr fixes

* add changeset

* file type fix

* format

* final fix

---------

Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com>
  • Loading branch information
dawoodkhan82 and gradio-pr-bot committed Jan 31, 2024
1 parent 68a54a7 commit c3e61e4
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 42 deletions.
6 changes: 6 additions & 0 deletions .changeset/puny-clowns-invent.md
@@ -0,0 +1,6 @@
---
"@gradio/upload": patch
"gradio": patch
---

fix:Few File component drag and drop
2 changes: 1 addition & 1 deletion demo/file_component_events/run.ipynb
@@ -1 +1 @@
{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: file_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": ["import gradio as gr\n", "\n", "with gr.Blocks() as demo:\n", " \n", " with gr.Row():\n", " with gr.Column():\n", " file_component = gr.File(label=\"Upload Single File\", file_count=\"single\")\n", " with gr.Column():\n", " output_file_1 = gr.File(label=\"Upload Single File Output\", file_count=\"single\")\n", " num_load_btn_1 = gr.Number(label=\"# Load Upload Single File\", value=0)\n", " file_component.upload(lambda s,n: (s, n + 1), [file_component, num_load_btn_1], [output_file_1, num_load_btn_1])\n", " with gr.Row():\n", " with gr.Column():\n", " file_component_multiple = gr.File(label=\"Upload Multiple Files\", file_count=\"multiple\")\n", " with gr.Column():\n", " output_file_2 = gr.File(label=\"Upload Multiple Files Output\", file_count=\"multiple\")\n", " num_load_btn_2 = gr.Number(label=\"# Load Upload Multiple Files\", value=0)\n", " file_component_multiple.upload(lambda s,n: (s, n + 1), [file_component_multiple, num_load_btn_2], [output_file_2, num_load_btn_2])\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: file_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": ["import gradio as gr\n", "\n", "with gr.Blocks() as demo:\n", " \n", " with gr.Row():\n", " with gr.Column():\n", " file_component = gr.File(label=\"Upload Single File\", file_count=\"single\")\n", " with gr.Column():\n", " output_file_1 = gr.File(label=\"Upload Single File Output\", file_count=\"single\")\n", " num_load_btn_1 = gr.Number(label=\"# Load Upload Single File\", value=0)\n", " file_component.upload(lambda s,n: (s, n + 1), [file_component, num_load_btn_1], [output_file_1, num_load_btn_1])\n", " with gr.Row():\n", " with gr.Column():\n", " file_component_multiple = gr.File(label=\"Upload Multiple Files\", file_count=\"multiple\")\n", " with gr.Column():\n", " output_file_2 = gr.File(label=\"Upload Multiple Files Output\", file_count=\"multiple\")\n", " num_load_btn_2 = gr.Number(label=\"# Load Upload Multiple Files\", value=0)\n", " file_component_multiple.upload(lambda s,n: (s, n + 1), [file_component_multiple, num_load_btn_2], [output_file_2, num_load_btn_2])\n", " with gr.Row():\n", " with gr.Column():\n", " file_component_specific = gr.File(label=\"Upload Multiple Files Image/Video\", file_count=\"multiple\", file_types=[\"image\", \"video\"])\n", " with gr.Column():\n", " output_file_3 = gr.File(label=\"Upload Multiple Files Output Image/Video\", file_count=\"multiple\")\n", " num_load_btn_3 = gr.Number(label=\"# Load Upload Multiple Files Image/Video\", value=0)\n", " file_component_specific.upload(lambda s,n: (s, n + 1), [file_component_specific, num_load_btn_3], [output_file_3, num_load_btn_3])\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
7 changes: 7 additions & 0 deletions demo/file_component_events/run.py
Expand Up @@ -16,6 +16,13 @@
output_file_2 = gr.File(label="Upload Multiple Files Output", file_count="multiple")
num_load_btn_2 = gr.Number(label="# Load Upload Multiple Files", value=0)
file_component_multiple.upload(lambda s,n: (s, n + 1), [file_component_multiple, num_load_btn_2], [output_file_2, num_load_btn_2])
with gr.Row():
with gr.Column():
file_component_specific = gr.File(label="Upload Multiple Files Image/Video", file_count="multiple", file_types=["image", "video"])
with gr.Column():
output_file_3 = gr.File(label="Upload Multiple Files Output Image/Video", file_count="multiple")
num_load_btn_3 = gr.Number(label="# Load Upload Multiple Files Image/Video", value=0)
file_component_specific.upload(lambda s,n: (s, n + 1), [file_component_specific, num_load_btn_3], [output_file_3, num_load_btn_3])

if __name__ == "__main__":
demo.launch()
50 changes: 24 additions & 26 deletions js/app/test/file_component_events.spec.ts
Expand Up @@ -7,7 +7,7 @@ test("File component properly dispatches load event for the single file case.",
.getByRole("button", { name: "Drop File Here - or - Click to Upload" })
.first()
.click();
const uploader = await page.getByTestId("file-upload").first();
const uploader = await page.locator("input[type=file]").first();
await uploader.setInputFiles(["./test/files/cheetah1.jpg"]);

await expect(page.getByLabel("# Load Upload Single File")).toHaveValue("1");
Expand All @@ -18,36 +18,34 @@ test("File component properly dispatches load event for the single file case.",
await expect(download.suggestedFilename()).toBe("cheetah1.jpg");
});

test("File component properly dispatches load event for the multiple file case.", async ({
test("File component drag-and-drop uploads a file to the server correctly.", async ({
page
}) => {
await page
.getByRole("button", { name: "Drop File Here - or - Click to Upload" })
.last()
.click();
const uploader = await page.getByTestId("file-upload").last();
await uploader.setInputFiles([
"./test/files/face.obj",
"./test/files/cheetah1.jpg"
]);
const uploader = await page.locator("input[type=file]").nth(1);
await uploader.setInputFiles(["./test/files/alphabet.txt"]);

await expect(page.getByLabel("# Load Upload Multiple Files")).toHaveValue(
"1"
);

const downloadPromise = page.waitForEvent("download");
await page.getByRole("link").nth(1).click();
const download = await downloadPromise;
await expect(download.suggestedFilename()).toBe("cheetah1.jpg");
await expect(
page.getByLabel("# Load Upload Multiple Files").first()
).toHaveValue("1");
});

test("File component drag-and-drop uploads a file to the server correctly.", async ({
test("File component properly handles drag and drop of image and video files.", async ({
page
}) => {
await drag_and_drop_file(
page,
"input[type=file]",
"./test/files/alphabet.txt",
"alphabet.txt"
);
const uploader = await page.locator("input[type=file]").last();
await uploader.setInputFiles(["./test/files/cheetah1.jpg"]);

// Check that the image file was uploaded
await expect(
page.getByLabel("# Load Upload Multiple Files Image/Video")
).toHaveValue("1");

await page.getByLabel("Clear").click();

await uploader.setInputFiles(["./test/files/world.mp4"]);

// Check that the video file was uploaded
await expect(
page.getByLabel("# Load Upload Multiple Files Image/Video")
).toHaveValue("2");
});
Binary file added js/app/test/files/world.mp4
Binary file not shown.
37 changes: 22 additions & 15 deletions js/upload/src/Upload.svelte
Expand Up @@ -27,7 +27,6 @@
let hidden_upload: HTMLInputElement;
const dispatch = createEventDispatcher();
$: if (filetype == null || typeof filetype === "string") {
accept_file_types = filetype;
} else {
Expand Down Expand Up @@ -106,32 +105,40 @@
function is_valid_mimetype(
file_accept: string | string[] | null,
mime_type: string
uploaded_file_extension: string,
uploaded_file_type: string
): boolean {
if (!file_accept || file_accept === "*" || file_accept === "file/*") {
return true;
}
if (typeof file_accept === "string" && file_accept.endsWith("/*")) {
file_accept = file_accept.split(",");
}
if (Array.isArray(file_accept)) {
return (
file_accept.includes(mime_type) ||
file_accept.some((type) => {
const [category] = type.split("/");
return type.endsWith("/*") && mime_type.startsWith(category + "/");
})
);
let acceptArray: string[];
if (typeof file_accept === "string") {
acceptArray = file_accept.split(",").map((s) => s.trim());
} else if (Array.isArray(file_accept)) {
acceptArray = file_accept;
} else {
return false;
}
return file_accept === mime_type;
return (
acceptArray.includes(uploaded_file_extension) ||
acceptArray.some((type) => {
const [category] = type.split("/").map((s) => s.trim());
return (
type.endsWith("/*") && uploaded_file_type.startsWith(category + "/")
);
})
);
}
async function loadFilesFromDrop(e: DragEvent): Promise<void> {
dragging = false;
if (!e.dataTransfer?.files) return;
const files_to_load = Array.from(e.dataTransfer.files).filter((file) => {
const file_extension = "." + file.name.split(".").pop();
if (file.type && is_valid_mimetype(filetype, file.type)) {
if (
file_extension &&
is_valid_mimetype(filetype, file_extension, file.type)
) {
return true;
}
if (
Expand Down

0 comments on commit c3e61e4

Please sign in to comment.