Add share link support for gradio-lite apps.
Browse files- app.py +16 -9
- templates.py +43 -2
app.py
CHANGED
|
@@ -9,7 +9,8 @@ import requests
|
|
| 9 |
import torch
|
| 10 |
from transformers import AutoModelForSpeechSeq2Seq, AutoProcessor, pipeline, Pipeline
|
| 11 |
|
| 12 |
-
from templates import starting_app_code, update_iframe_js, copy_snippet_js, download_code_js, load_js, DemoType
|
|
|
|
| 13 |
|
| 14 |
# Filter the UserWarning raised by the audio component.
|
| 15 |
warnings.filterwarnings("ignore", message='Trying to convert audio automatically from int32 to 16-bit int format')
|
|
@@ -85,6 +86,10 @@ def transcribe(audio: str) -> (str, str):
|
|
| 85 |
return result["text"], None
|
| 86 |
|
| 87 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 88 |
def copy_notify(code):
|
| 89 |
gr.Info("App code snippet copied!")
|
| 90 |
|
|
@@ -94,7 +99,7 @@ def add_hotkeys() -> str:
|
|
| 94 |
|
| 95 |
|
| 96 |
with gr.Blocks() as demo:
|
| 97 |
-
gr.Markdown("<h1 id=\"TEST\" align=\"center\">KiteWind πͺπ</h1>")
|
| 98 |
gr.Markdown(
|
| 99 |
"<h4 align=\"center\">Chat-assisted web app creator by <a href=\"https://huggingface.co/gstaff\">@gstaff</a></h4>")
|
| 100 |
selectedTab = gr.State(value='gradio-lite')
|
|
@@ -110,7 +115,7 @@ with gr.Blocks() as demo:
|
|
| 110 |
in_audio = gr.Audio(label="Record a voice request (click or press ctrl + ` to start/stop)", source='microphone', type='filepath', elem_classes=["record-btn"])
|
| 111 |
in_prompt = gr.Textbox(label="Or type a text request and press Enter",
|
| 112 |
placeholder="Need an idea? Try one of these:\n- Add a button to reverse the name\n- Change the greeting to Spanish\n- Put the reversed name output into a separate textbox")
|
| 113 |
-
out_text = gr.TextArea(label="Chat Assistant Response")
|
| 114 |
clear = gr.ClearButton([in_prompt, in_audio, out_text])
|
| 115 |
with gr.Column():
|
| 116 |
code_area = gr.Code(label="App Code - You can also edit directly and then click Update App or ctrl + space",
|
|
@@ -127,16 +132,18 @@ with gr.Blocks() as demo:
|
|
| 127 |
with gr.Row():
|
| 128 |
with gr.Column():
|
| 129 |
gr.Markdown("## 3. Export your app to share!")
|
| 130 |
-
|
|
|
|
|
|
|
| 131 |
copy_snippet_btn.click(copy_notify, code_area, None, _js=copy_snippet_js(DemoType.GRADIO))
|
| 132 |
-
download_btn = gr.Button("Download app as a standalone file")
|
| 133 |
download_btn.click(None, code_area, None, _js=download_code_js(DemoType.GRADIO))
|
| 134 |
with gr.Row():
|
| 135 |
with gr.Column():
|
| 136 |
gr.Markdown("## Current limitations")
|
| 137 |
with gr.Accordion("Click to view", open=False):
|
| 138 |
gr.Markdown(
|
| 139 |
-
"- Only gradio-lite apps using the python standard libraries and gradio are supported\n- The chat hasn't been tuned on gradio library data; it may make mistakes
|
| 140 |
with gr.Tab('Streamlit (stlite)') as stlite_tab:
|
| 141 |
with gr.Row():
|
| 142 |
with gr.Column():
|
|
@@ -149,7 +156,7 @@ with gr.Blocks() as demo:
|
|
| 149 |
in_audio = gr.Audio(label="Record a voice request (click or press ctrl + ` to start/stop)", source='microphone', type='filepath', elem_classes=["record-btn"])
|
| 150 |
in_prompt = gr.Textbox(label="Or type a text request and press Enter",
|
| 151 |
placeholder="Need an idea? Try one of these:\n- Add a button to reverse the name\n- Change the greeting to Spanish\n- Make the button primary")
|
| 152 |
-
out_text = gr.TextArea(label="Chat Assistant Response")
|
| 153 |
clear_btn = gr.ClearButton([in_prompt, in_audio, out_text])
|
| 154 |
with gr.Column():
|
| 155 |
code_area = gr.Code(label="App Code - You can also edit directly and then click Update App or ctrl + space",
|
|
@@ -166,9 +173,9 @@ with gr.Blocks() as demo:
|
|
| 166 |
with gr.Row():
|
| 167 |
with gr.Column():
|
| 168 |
gr.Markdown("## 3. Export your app to share!")
|
| 169 |
-
copy_snippet_btn = gr.Button("Copy app snippet
|
| 170 |
copy_snippet_btn.click(copy_notify, code_area, None, _js=copy_snippet_js(DemoType.STREAMLIT))
|
| 171 |
-
download_btn = gr.Button("Download app as a standalone file")
|
| 172 |
download_btn.click(None, code_area, None, _js=download_code_js(DemoType.STREAMLIT))
|
| 173 |
with gr.Row():
|
| 174 |
with gr.Column():
|
|
|
|
| 9 |
import torch
|
| 10 |
from transformers import AutoModelForSpeechSeq2Seq, AutoProcessor, pipeline, Pipeline
|
| 11 |
|
| 12 |
+
from templates import starting_app_code, update_iframe_js, copy_snippet_js, download_code_js, load_js, DemoType, \
|
| 13 |
+
copy_share_link_js
|
| 14 |
|
| 15 |
# Filter the UserWarning raised by the audio component.
|
| 16 |
warnings.filterwarnings("ignore", message='Trying to convert audio automatically from int32 to 16-bit int format')
|
|
|
|
| 86 |
return result["text"], None
|
| 87 |
|
| 88 |
|
| 89 |
+
def link_copy_notify(code):
|
| 90 |
+
gr.Info("Share link copied!")
|
| 91 |
+
|
| 92 |
+
|
| 93 |
def copy_notify(code):
|
| 94 |
gr.Info("App code snippet copied!")
|
| 95 |
|
|
|
|
| 99 |
|
| 100 |
|
| 101 |
with gr.Blocks() as demo:
|
| 102 |
+
gr.Markdown("<h1 id=\"TEST\" align=\"center\"><a href=\"?\">KiteWind</a> πͺπ</h1>")
|
| 103 |
gr.Markdown(
|
| 104 |
"<h4 align=\"center\">Chat-assisted web app creator by <a href=\"https://huggingface.co/gstaff\">@gstaff</a></h4>")
|
| 105 |
selectedTab = gr.State(value='gradio-lite')
|
|
|
|
| 115 |
in_audio = gr.Audio(label="Record a voice request (click or press ctrl + ` to start/stop)", source='microphone', type='filepath', elem_classes=["record-btn"])
|
| 116 |
in_prompt = gr.Textbox(label="Or type a text request and press Enter",
|
| 117 |
placeholder="Need an idea? Try one of these:\n- Add a button to reverse the name\n- Change the greeting to Spanish\n- Put the reversed name output into a separate textbox")
|
| 118 |
+
out_text = gr.TextArea(label="π€ Chat Assistant Response")
|
| 119 |
clear = gr.ClearButton([in_prompt, in_audio, out_text])
|
| 120 |
with gr.Column():
|
| 121 |
code_area = gr.Code(label="App Code - You can also edit directly and then click Update App or ctrl + space",
|
|
|
|
| 132 |
with gr.Row():
|
| 133 |
with gr.Column():
|
| 134 |
gr.Markdown("## 3. Export your app to share!")
|
| 135 |
+
share_link_btn = gr.Button("π Copy share link to clipboard")
|
| 136 |
+
share_link_btn.click(link_copy_notify, code_area, None, _js=copy_share_link_js(DemoType.GRADIO))
|
| 137 |
+
copy_snippet_btn = gr.Button("βοΈ Copy app snippet to paste into another page")
|
| 138 |
copy_snippet_btn.click(copy_notify, code_area, None, _js=copy_snippet_js(DemoType.GRADIO))
|
| 139 |
+
download_btn = gr.Button("π Download app as a standalone file")
|
| 140 |
download_btn.click(None, code_area, None, _js=download_code_js(DemoType.GRADIO))
|
| 141 |
with gr.Row():
|
| 142 |
with gr.Column():
|
| 143 |
gr.Markdown("## Current limitations")
|
| 144 |
with gr.Accordion("Click to view", open=False):
|
| 145 |
gr.Markdown(
|
| 146 |
+
"- Only gradio-lite apps using the python standard libraries and gradio are supported\n- The chat hasn't been tuned on gradio library data; it may make mistakes")
|
| 147 |
with gr.Tab('Streamlit (stlite)') as stlite_tab:
|
| 148 |
with gr.Row():
|
| 149 |
with gr.Column():
|
|
|
|
| 156 |
in_audio = gr.Audio(label="Record a voice request (click or press ctrl + ` to start/stop)", source='microphone', type='filepath', elem_classes=["record-btn"])
|
| 157 |
in_prompt = gr.Textbox(label="Or type a text request and press Enter",
|
| 158 |
placeholder="Need an idea? Try one of these:\n- Add a button to reverse the name\n- Change the greeting to Spanish\n- Make the button primary")
|
| 159 |
+
out_text = gr.TextArea(label="π€ Chat Assistant Response")
|
| 160 |
clear_btn = gr.ClearButton([in_prompt, in_audio, out_text])
|
| 161 |
with gr.Column():
|
| 162 |
code_area = gr.Code(label="App Code - You can also edit directly and then click Update App or ctrl + space",
|
|
|
|
| 173 |
with gr.Row():
|
| 174 |
with gr.Column():
|
| 175 |
gr.Markdown("## 3. Export your app to share!")
|
| 176 |
+
copy_snippet_btn = gr.Button("βοΈ Copy app snippet into paste in another page")
|
| 177 |
copy_snippet_btn.click(copy_notify, code_area, None, _js=copy_snippet_js(DemoType.STREAMLIT))
|
| 178 |
+
download_btn = gr.Button("π Download app as a standalone file")
|
| 179 |
download_btn.click(None, code_area, None, _js=download_code_js(DemoType.STREAMLIT))
|
| 180 |
with gr.Row():
|
| 181 |
with gr.Column():
|
templates.py
CHANGED
|
@@ -27,14 +27,40 @@ def load_js(demo_type: DemoType) -> str:
|
|
| 27 |
if (window.gradioLiteLoaded) {{
|
| 28 |
return
|
| 29 |
}}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 30 |
const htmlString = '<iframe id="gradio-iframe" width="100%" height="512px" src="about:blank"></iframe>';
|
| 31 |
const parser = new DOMParser();
|
| 32 |
const doc = parser.parseFromString(htmlString, 'text/html');
|
| 33 |
const iframe = doc.getElementById('gradio-iframe');
|
| 34 |
const div = document.getElementById('gradioDemoDiv');
|
| 35 |
div.appendChild(iframe);
|
| 36 |
-
|
| 37 |
-
|
|
|
|
|
|
|
|
|
|
| 38 |
const frame = document.getElementById('gradio-iframe');
|
| 39 |
frame.contentWindow.document.open('text/html', 'replace');
|
| 40 |
frame.contentWindow.document.write(template);
|
|
@@ -76,6 +102,12 @@ def update_iframe_js(demo_type: DemoType) -> str:
|
|
| 76 |
appController.run_code(newCode);
|
| 77 |
}};
|
| 78 |
await update();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 79 |
}}"""
|
| 80 |
elif demo_type == DemoType.STREAMLIT:
|
| 81 |
return f"""async (code) => {{
|
|
@@ -90,6 +122,15 @@ def update_iframe_js(demo_type: DemoType) -> str:
|
|
| 90 |
raise NotImplementedError(f'{demo_type} is not a supported demo type')
|
| 91 |
|
| 92 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 93 |
def copy_snippet_js(demo_type: DemoType) -> str:
|
| 94 |
if demo_type == DemoType.GRADIO:
|
| 95 |
return f"""async (code) => {{
|
|
|
|
| 27 |
if (window.gradioLiteLoaded) {{
|
| 28 |
return
|
| 29 |
}}
|
| 30 |
+
|
| 31 |
+
// Get the query string from the URL
|
| 32 |
+
const queryString = window.location.search;
|
| 33 |
+
// Use a function to parse the query string into an object
|
| 34 |
+
function parseQueryString(queryString) {{
|
| 35 |
+
const params = {{}};
|
| 36 |
+
const queryStringWithoutQuestionMark = queryString.substring(1); // Remove the leading question mark
|
| 37 |
+
const keyValuePairs = queryStringWithoutQuestionMark.split('&');
|
| 38 |
+
|
| 39 |
+
keyValuePairs.forEach(keyValue => {{
|
| 40 |
+
const [key, value] = keyValue.split('=');
|
| 41 |
+
if (value) {{
|
| 42 |
+
params[key] = decodeURIComponent(value.replace(/\+/g, ' '));
|
| 43 |
+
}}
|
| 44 |
+
}});
|
| 45 |
+
|
| 46 |
+
return params;
|
| 47 |
+
}}
|
| 48 |
+
// Parse the query string into an object
|
| 49 |
+
const queryParams = parseQueryString(queryString);
|
| 50 |
+
// Access individual parameters
|
| 51 |
+
const codeValue = queryParams.code;
|
| 52 |
+
|
| 53 |
const htmlString = '<iframe id="gradio-iframe" width="100%" height="512px" src="about:blank"></iframe>';
|
| 54 |
const parser = new DOMParser();
|
| 55 |
const doc = parser.parseFromString(htmlString, 'text/html');
|
| 56 |
const iframe = doc.getElementById('gradio-iframe');
|
| 57 |
const div = document.getElementById('gradioDemoDiv');
|
| 58 |
div.appendChild(iframe);
|
| 59 |
+
|
| 60 |
+
let template = `{gradio_lite_html_template.replace('STARTING_CODE', starting_app_code(demo_type))}`;
|
| 61 |
+
if (codeValue) {{
|
| 62 |
+
template = `{gradio_lite_html_template}`.replace('STARTING_CODE', codeValue);
|
| 63 |
+
}}
|
| 64 |
const frame = document.getElementById('gradio-iframe');
|
| 65 |
frame.contentWindow.document.open('text/html', 'replace');
|
| 66 |
frame.contentWindow.document.write(template);
|
|
|
|
| 102 |
appController.run_code(newCode);
|
| 103 |
}};
|
| 104 |
await update();
|
| 105 |
+
|
| 106 |
+
// Update URL query params to include the current demo code state
|
| 107 |
+
const currentUrl = new URL(window.location.href);
|
| 108 |
+
currentUrl.searchParams.set('code', code);
|
| 109 |
+
// Replace the current URL with the updated one
|
| 110 |
+
history.replaceState({{}}, '', currentUrl.href);
|
| 111 |
}}"""
|
| 112 |
elif demo_type == DemoType.STREAMLIT:
|
| 113 |
return f"""async (code) => {{
|
|
|
|
| 122 |
raise NotImplementedError(f'{demo_type} is not a supported demo type')
|
| 123 |
|
| 124 |
|
| 125 |
+
def copy_share_link_js(demo_type: DemoType) -> str:
|
| 126 |
+
if demo_type == DemoType.GRADIO:
|
| 127 |
+
return f"""async (code) => {{
|
| 128 |
+
const shareLink = document.URL;
|
| 129 |
+
await navigator.clipboard.writeText(shareLink);
|
| 130 |
+
}}"""
|
| 131 |
+
raise NotImplementedError(f'{demo_type} is not a supported demo type')
|
| 132 |
+
|
| 133 |
+
|
| 134 |
def copy_snippet_js(demo_type: DemoType) -> str:
|
| 135 |
if demo_type == DemoType.GRADIO:
|
| 136 |
return f"""async (code) => {{
|