Skip to content

Commit 2b0898b

Browse files
pngwnabidlabs
andauthored
Scroll to output (#1077)
* implement loader + scroll into view * changes * refactor components to use Block inside the app * cleanup * cleanup * implement all changes for all changes for all relevant components * fix formatting * demos * add status tracker to every component * fix tests * fix unti test flake: randInt * cleanup CI * fix CI Co-authored-by: Abubakar Abid <abubakar@huggingface.co>
1 parent 73ac1e1 commit 2b0898b

58 files changed

Lines changed: 1110 additions & 930 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/ui.yml

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,6 @@ jobs:
5858
node-version: 16
5959
cache: pnpm
6060
cache-dependency-path: ui/pnpm-lock.yaml
61-
- name: Cache browsers
62-
id: browser_cache
63-
uses: actions/cache@main
64-
with:
65-
path: "~/.cache/ms-playwright"
66-
key: chromium-${{ runner.os }}-${{ hashFiles('**/pnpm-lock.yaml') }}
6761
- run: pnpm install --frozen-lockfile
6862
- run: pnpx playwright install chromium
6963
- run: pnpm build

demo/kitchen_sink/run.py

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import os
12
import json
23

34
import numpy as np
@@ -40,9 +41,9 @@ def fn(
4041
}, # Label
4142
(audio1[0], np.flipud(audio1[1]))
4243
if audio1 is not None
43-
else "files/cantina.wav", # Audio
44-
np.flipud(im1) if im1 is not None else "files/cheetah1.jpg", # Image
45-
video if video is not None else "files/world.mp4", # Video
44+
else os.path.join(os.path.dirname(__file__),"files/cantina.wav"), # Audio
45+
np.flipud(im1) if im1 is not None else os.path.join(os.path.dirname(__file__),"files/cheetah1.jpg"), # Image
46+
video if video is not None else os.path.join(os.path.dirname(__file__),"files/world.mp4"), # Video
4647
[
4748
("The", "art"),
4849
("quick brown", "adj"),
@@ -72,11 +73,11 @@ def fn(
7273
"<button style='background-color: red'>Click Me: "
7374
+ radio
7475
+ "</button>", # HTML
75-
"files/titanic.csv",
76+
os.path.join(os.path.dirname(__file__),"files/titanic.csv"),
7677
df1, # Dataframe
7778
np.random.randint(0, 10, (4, 4)), # Dataframe
7879
[
79-
im for im in [im1, im2, im3, im4, "files/cheetah1.jpg"] if im is not None
80+
im for im in [im1, im2, im3, im4, os.path.join(os.path.dirname(__file__),"files/cheetah1.jpg")] if im is not None
8081
], # Carousel
8182
df2, # Timeseries
8283
)
@@ -136,16 +137,16 @@ def fn(
136137
["foo", "baz"],
137138
"baz",
138139
"bar",
139-
"files/cheetah1.jpg",
140-
"files/cheetah1.jpg",
141-
"files/cheetah1.jpg",
142-
"files/cheetah1.jpg",
143-
"files/world.mp4",
144-
"files/cantina.wav",
145-
"files/cantina.wav",
146-
"files/titanic.csv",
140+
os.path.join(os.path.dirname(__file__),"files/cheetah1.jpg"),
141+
os.path.join(os.path.dirname(__file__),"files/cheetah1.jpg"),
142+
os.path.join(os.path.dirname(__file__),"files/cheetah1.jpg"),
143+
os.path.join(os.path.dirname(__file__),"files/cheetah1.jpg"),
144+
os.path.join(os.path.dirname(__file__),"files/world.mp4"),
145+
os.path.join(os.path.dirname(__file__),"files/cantina.wav"),
146+
os.path.join(os.path.dirname(__file__),"files/cantina.wav"),
147+
os.path.join(os.path.dirname(__file__),"files/titanic.csv"),
147148
[[1, 2, 3], [3, 4, 5]],
148-
"files/time.csv",
149+
os.path.join(os.path.dirname(__file__),"files/time.csv"),
149150
]
150151
]
151152
* 3,

demo/main_note/run.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from math import log2, pow
2+
import os
23

3-
import matplotlib.pyplot as plt
44
import numpy as np
55
from scipy.fftpack import fft
66

@@ -46,8 +46,8 @@ def main_note(audio):
4646
gr.Audio(source="microphone"),
4747
gr.Label(num_top_classes=4),
4848
examples=[
49-
["audio/recording1.wav"],
50-
["audio/cantina.wav"],
49+
[os.path.join(os.path.dirname(__file__),"audio/recording1.wav")],
50+
[os.path.join(os.path.dirname(__file__),"audio/cantina.wav")],
5151
],
5252
interpretation="default",
5353
)

demo/zip_two_files/run.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import os
12
from zipfile import ZipFile
23

34
import gradio as gr
@@ -15,7 +16,8 @@ def zip_two_files(file1, file2):
1516
["file", "file"],
1617
"file",
1718
examples=[
18-
["files/titanic.csv", "files/titanic.csv"],
19+
[os.path.join(os.path.dirname(__file__),"files/titanic.csv"),
20+
os.path.join(os.path.dirname(__file__),"files/titanic.csv")],
1921
],
2022
)
2123

ui/package.json

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,32 +23,32 @@
2323
"dependencies": {
2424
"@gradio/tootils": "workspace:^0.0.1",
2525
"@playwright/test": "^1.20.0",
26-
"@sveltejs/vite-plugin-svelte": "^1.0.0-next.36",
26+
"@sveltejs/vite-plugin-svelte": "^1.0.0-next.41",
2727
"@tailwindcss/forms": "^0.5.0",
2828
"@testing-library/dom": "^8.11.3",
2929
"@testing-library/svelte": "^3.1.0",
3030
"@testing-library/user-event": "^13.5.0",
3131
"autoprefixer": "^10.4.4",
32+
"babylonjs": "^4.2.1",
33+
"babylonjs-loaders": "^4.2.1",
3234
"happy-dom": "^2.49.0",
3335
"npm-run-all": "^4.1.5",
36+
"plotly.js-dist-min": "^2.10.1",
3437
"polka": "^1.0.0-next.22",
3538
"postcss": "^8.4.5",
3639
"postcss-nested": "^5.0.6",
37-
"prettier": "^2.5.1",
38-
"prettier-plugin-svelte": "^2.6.0",
40+
"prettier": "^2.6.2",
41+
"prettier-plugin-svelte": "^2.7.0",
3942
"sirv": "^2.0.2",
4043
"sirv-cli": "^2.0.2",
41-
"svelte": "^3.46.3",
42-
"svelte-check": "^2.4.1",
44+
"svelte": "^3.47.0",
45+
"svelte-check": "^2.7.0",
4346
"svelte-i18n": "^3.3.13",
44-
"svelte-preprocess": "^4.10.1",
47+
"svelte-preprocess": "^4.10.6",
4548
"tailwindcss": "^3.0.23",
4649
"tinyspy": "^0.3.0",
47-
"vite": "^2.9.1",
48-
"vitest": "^0.3.2",
49-
"plotly.js-dist-min": "^2.10.1",
50-
"babylonjs": "^4.2.1",
51-
"babylonjs-loaders": "^4.2.1"
50+
"vite": "^2.9.5",
51+
"vitest": "^0.10.0"
5252
},
5353
"devDependencies": {
5454
"@types/three": "^0.138.0"

ui/packages/app/src/Blocks.svelte

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@
5555
value?: unknown;
5656
}
5757
58-
const instance_map = components.reduce((acc, next) => {
58+
let instance_map = components.reduce((acc, next) => {
5959
return {
6060
...acc,
6161
[next.id]: {
@@ -89,8 +89,6 @@
8989
_n.has_modes = true;
9090
}
9191
92-
// console.log(await _component_map.get(meta.type));
93-
9492
if (node.children) {
9593
_n.children = await Promise.all(node.children.map((v) => walk_layout(v)));
9694
}
@@ -107,24 +105,25 @@
107105
});
108106
109107
let tree;
108+
110109
Promise.all(Array.from(component_set)).then((v) => {
111110
Promise.all(layout.children.map((c) => walk_layout(c))).then((v) => {
112111
console.log(v);
113112
tree = v;
114113
});
115114
});
116115
116+
function set_prop(obj: Instance, prop: string, val: any) {
117+
if (!obj?.props) {
118+
obj.props = {};
119+
}
120+
obj.props[prop] = val;
121+
tree = tree;
122+
}
123+
117124
let handled_dependencies: Array<number[]> = [];
118125
let status_tracker_values: Record<number, string> = {};
119126
120-
let set_status = (dependency_index: number, status: string) => {
121-
dependencies[dependency_index].status = status;
122-
let status_tracker_id = dependencies[dependency_index].status_tracker;
123-
if (status_tracker_id !== null) {
124-
status_tracker_values[status_tracker_id] = status;
125-
}
126-
};
127-
128127
async function handle_mount({ detail }) {
129128
await tick();
130129
dependencies.forEach(({ targets, trigger, inputs, outputs, queue }, i) => {
@@ -164,14 +163,15 @@
164163
}
165164
166165
target_instances.forEach(([id, { instance }]: [number, Instance]) => {
167-
// console.log(id, handled_dependencies[i]?.includes(id) || !instance);
168166
if (handled_dependencies[i]?.includes(id) || !instance) return;
169-
// console.log(trigger, target_instances, instance);
170167
instance?.$on(trigger, () => {
171168
if (status === "pending") {
172169
return;
173170
}
174-
set_status(i, "pending");
171+
outputs.forEach((_id) =>
172+
set_prop(instance_map[_id], "loading_status", "pending")
173+
);
174+
175175
fn(
176176
"predict",
177177
{
@@ -182,13 +182,21 @@
182182
() => {}
183183
)
184184
.then((output) => {
185-
set_status(i, "complete");
185+
// set_status(i, "complete");
186186
output.data.forEach((value, i) => {
187187
instance_map[outputs[i]].value = value;
188+
set_prop(
189+
instance_map[outputs[i]],
190+
"loading_status",
191+
"complete"
192+
);
188193
});
189194
})
190195
.catch((error) => {
191-
set_status(i, "error");
196+
outputs.forEach((_id) =>
197+
set_prop(instance_map[_id], "loading_status", "error")
198+
);
199+
192200
console.error(error);
193201
});
194202
});

ui/packages/app/src/Render.svelte

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,9 @@
7979
node.props.form_position = "single";
8080
}
8181
}
82+
children =
83+
children &&
84+
children.filter((v) => instance_map[v.id].type !== "statustracker");
8285
</script>
8386

8487
<svelte:component
@@ -91,7 +94,7 @@
9194
tracked_status={status_tracker_values[id]}
9295
>
9396
{#if children && children.length}
94-
{#each children as { component, id, props, children, has_modes }}
97+
{#each children as { component, id, props, children, has_modes } (id)}
9598
<svelte:self
9699
{component}
97100
{id}

ui/packages/app/src/components/Audio/Audio.svelte

Lines changed: 38 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
import { Audio, StaticAudio } from "@gradio/audio";
33
import type { FileData } from "@gradio/upload";
44
import { normalise_file } from "@gradio/upload";
5+
import { Block } from "@gradio/atoms";
6+
7+
import StatusTracker from "../StatusTracker/StatusTracker.svelte";
58
import { _ } from "svelte-i18n";
69
710
export let mode: "static" | "dynamic";
@@ -14,29 +17,44 @@
1417
export let label: string;
1518
export let root: string;
1619
20+
export let loading_status: "complete" | "pending" | "error";
21+
1722
if (default_value) value = default_value;
1823
1924
let _value: null | FileData;
2025
$: _value = normalise_file(value, root);
26+
27+
let dragging: boolean;
2128
</script>
2229

23-
{#if mode === "dynamic"}
24-
<Audio
25-
{label}
26-
value={_value}
27-
on:change={({ detail }) => (value = detail)}
28-
{style}
29-
{name}
30-
{source}
31-
{type}
32-
on:edit
33-
on:play
34-
on:pause
35-
on:ended
36-
drop_text={$_("interface.drop_audio")}
37-
or_text={$_("or")}
38-
upload_text={$_("interface.click_to_upload")}
39-
/>
40-
{:else}
41-
<StaticAudio value={_value} name={_value?.name || "audio_file"} {label} />
42-
{/if}
30+
<Block
31+
variant={mode === "dynamic" && value === null && source === "upload"
32+
? "dashed"
33+
: "solid"}
34+
color={dragging ? "green" : "grey"}
35+
padding={false}
36+
>
37+
<StatusTracker tracked_status={loading_status} />
38+
39+
{#if mode === "dynamic"}
40+
<Audio
41+
{label}
42+
value={_value}
43+
on:change={({ detail }) => (value = detail)}
44+
on:drag={({ detail }) => (dragging = detail)}
45+
{style}
46+
{name}
47+
{source}
48+
{type}
49+
on:edit
50+
on:play
51+
on:pause
52+
on:ended
53+
drop_text={$_("interface.drop_audio")}
54+
or_text={$_("or")}
55+
upload_text={$_("interface.click_to_upload")}
56+
/>
57+
{:else}
58+
<StaticAudio value={_value} name={_value?.name || "audio_file"} {label} />
59+
{/if}
60+
</Block>

ui/packages/app/src/components/Button/Button.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import { _ } from "svelte-i18n";
44
55
export let value: string;
6-
export let default_value: string;
6+
export let default_value: string | undefined = undefined;
77
export let style: string = "";
88
export let variant: "primary" | "secondary" = "primary";
99
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
<script lang="ts">
22
import { Carousel } from "@gradio/carousel";
3+
import StatusTracker from "../StatusTracker/StatusTracker.svelte";
34
45
export let style: string = "";
6+
export let loading_status: "complete" | "pending" | "error";
57
</script>
68

79
<Carousel {style} on:change>
10+
<StatusTracker tracked_status={loading_status} />
11+
812
<slot />
913
</Carousel>

0 commit comments

Comments
 (0)