gstaff commited on
Commit
73c77f1
β€’
1 Parent(s): 755dd36

Add share link support for gradio-lite apps.

Browse files
Files changed (2) hide show
  1. app.py +16 -9
  2. 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
- copy_snippet_btn = gr.Button("Copy app snippet to paste in another page")
 
 
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\n- The app needs to fully reload each time it is changed")
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 to paste in another page")
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
- const template = `{gradio_lite_html_template.replace('STARTING_CODE', starting_app_code(demo_type))}`;
 
 
 
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) => {{