Add undo and redo buttons for gradio and streamlit. Also rename components to eliminate overlapping names between gradio and streamlit tabs.
Browse files- app.py +118 -55
- templates.py +22 -13
app.py
CHANGED
|
@@ -99,18 +99,41 @@ def add_hotkeys() -> str:
|
|
| 99 |
return Path("hotkeys.js").read_text()
|
| 100 |
|
| 101 |
|
| 102 |
-
def apply_query_params(gradio_code: str, stlite_code: str, request: gr.Request) -> (
|
|
|
|
| 103 |
params = dict(request.query_params)
|
| 104 |
demo_type = params.get('type')
|
| 105 |
if demo_type == 'gradio':
|
| 106 |
-
return params.get('code') or gradio_code, params.get('requirements') or '',
|
|
|
|
| 107 |
if demo_type == 'streamlit':
|
| 108 |
-
return gradio_code, '', params.get('code') or stlite_code, params.get('requirements') or '',
|
| 109 |
-
|
|
|
|
| 110 |
|
| 111 |
|
| 112 |
-
def update_state(requirements: [str], error: str)
|
| 113 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 114 |
|
| 115 |
|
| 116 |
with gr.Blocks(title="KiteWind") as demo:
|
|
@@ -128,37 +151,56 @@ with gr.Blocks(title="KiteWind") as demo:
|
|
| 128 |
with gr.Row():
|
| 129 |
with gr.Column():
|
| 130 |
with gr.Group():
|
| 131 |
-
|
| 132 |
-
|
| 133 |
-
|
| 134 |
-
|
| 135 |
-
|
| 136 |
-
|
| 137 |
with gr.Column():
|
| 138 |
gradio_code_area = gr.Code(
|
| 139 |
label="App Code - You can also edit directly and then click Update App or ctrl + space",
|
| 140 |
language='python', value=starting_app_code(DemoType.GRADIO))
|
| 141 |
-
gradio_requirements_area = gr.Code(
|
| 142 |
-
|
| 143 |
-
|
| 144 |
-
|
| 145 |
-
|
| 146 |
-
|
| 147 |
-
|
| 148 |
-
|
| 149 |
-
|
| 150 |
-
|
| 151 |
-
|
| 152 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 153 |
with gr.Row():
|
| 154 |
with gr.Column():
|
| 155 |
gr.Markdown("## 3. Export your app to share!")
|
| 156 |
-
|
| 157 |
-
|
| 158 |
-
|
| 159 |
-
|
| 160 |
-
|
| 161 |
-
|
|
|
|
|
|
|
|
|
|
| 162 |
with gr.Row():
|
| 163 |
with gr.Column():
|
| 164 |
gr.Markdown("## Current limitations")
|
|
@@ -174,37 +216,56 @@ with gr.Blocks(title="KiteWind") as demo:
|
|
| 174 |
with gr.Row():
|
| 175 |
with gr.Column():
|
| 176 |
with gr.Group():
|
| 177 |
-
|
| 178 |
-
|
| 179 |
-
|
| 180 |
-
|
| 181 |
-
|
| 182 |
-
|
| 183 |
with gr.Column():
|
| 184 |
stlite_code_area = gr.Code(
|
| 185 |
label="App Code - You can also edit directly and then click Update App or ctrl + space",
|
| 186 |
language='python', value=starting_app_code(DemoType.STREAMLIT))
|
| 187 |
-
stlite_requirements_area = gr.Code(
|
| 188 |
-
|
| 189 |
-
|
| 190 |
-
|
| 191 |
-
|
| 192 |
-
|
| 193 |
-
|
| 194 |
-
|
| 195 |
-
|
| 196 |
-
|
| 197 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 198 |
with gr.Row():
|
| 199 |
with gr.Column():
|
| 200 |
gr.Markdown("## 3. Export your app to share!")
|
| 201 |
-
|
| 202 |
-
|
| 203 |
-
|
| 204 |
-
|
| 205 |
-
|
| 206 |
-
|
| 207 |
-
|
|
|
|
|
|
|
| 208 |
with gr.Row():
|
| 209 |
with gr.Column():
|
| 210 |
gr.Markdown("## Current limitations")
|
|
@@ -215,7 +276,9 @@ with gr.Blocks(title="KiteWind") as demo:
|
|
| 215 |
_js=load_js(DemoType.GRADIO))
|
| 216 |
stlite_tab.select(lambda: "stlite", None, selectedTab).then(None, None, None, _js=load_js(DemoType.STREAMLIT))
|
| 217 |
demo.load(None, None, None, _js=add_hotkeys())
|
| 218 |
-
demo.load(apply_query_params, [gradio_code_area, stlite_code_area],
|
|
|
|
|
|
|
| 219 |
demo.css = "footer {visibility: hidden}"
|
| 220 |
|
| 221 |
if __name__ == "__main__":
|
|
|
|
| 99 |
return Path("hotkeys.js").read_text()
|
| 100 |
|
| 101 |
|
| 102 |
+
def apply_query_params(gradio_code: str, stlite_code: str, request: gr.Request) -> (
|
| 103 |
+
str, str, [str], str, str, [str], typing.Any):
|
| 104 |
params = dict(request.query_params)
|
| 105 |
demo_type = params.get('type')
|
| 106 |
if demo_type == 'gradio':
|
| 107 |
+
return params.get('code') or gradio_code, params.get('requirements') or '', [
|
| 108 |
+
params.get('code') or gradio_code], stlite_code, '', [stlite_code_area], gr.Tabs(selected=0)
|
| 109 |
if demo_type == 'streamlit':
|
| 110 |
+
return gradio_code, '', [gradio_code], params.get('code') or stlite_code, params.get('requirements') or '', [
|
| 111 |
+
params.get('code') or stlite_code], gr.Tabs(selected=1)
|
| 112 |
+
return gradio_code, '', [gradio_code], stlite_code, '', [stlite_code], gr.Tabs(selected=0)
|
| 113 |
|
| 114 |
|
| 115 |
+
def update_state(code: str, requirements: [str], error: str, history: [str], current_index: int) -> (
|
| 116 |
+
str, str, [str], int):
|
| 117 |
+
# Only modify undo history if new code was added.
|
| 118 |
+
if history[current_index] != code:
|
| 119 |
+
history = history[:current_index + 1]
|
| 120 |
+
history.append(code)
|
| 121 |
+
current_index = len(history) - 1
|
| 122 |
+
return '\n'.join(sorted(requirements)), error, history, current_index
|
| 123 |
+
|
| 124 |
+
|
| 125 |
+
def undo(code: str, history: [str], current_index: int) -> (str, int):
|
| 126 |
+
if current_index > 0:
|
| 127 |
+
current_index -= 1
|
| 128 |
+
return history[current_index], current_index
|
| 129 |
+
return code, current_index
|
| 130 |
+
|
| 131 |
+
|
| 132 |
+
def redo(code: str, history: [str], current_index: int) -> (str, int):
|
| 133 |
+
if current_index < len(history) - 1:
|
| 134 |
+
current_index += 1
|
| 135 |
+
return history[current_index], current_index
|
| 136 |
+
return code, current_index
|
| 137 |
|
| 138 |
|
| 139 |
with gr.Blocks(title="KiteWind") as demo:
|
|
|
|
| 151 |
with gr.Row():
|
| 152 |
with gr.Column():
|
| 153 |
with gr.Group():
|
| 154 |
+
gradio_audio = gr.Audio(label="Record a voice request (click or press ctrl + ` to start/stop)",
|
| 155 |
+
source='microphone', type='filepath', elem_classes=["record-btn"])
|
| 156 |
+
gradio_prompt = gr.Textbox(label="Or type a text request and press Enter",
|
| 157 |
+
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")
|
| 158 |
+
gradio_bot_text = gr.TextArea(label="π€ Chat Assistant Response")
|
| 159 |
+
gradio_clear = gr.ClearButton([gradio_prompt, gradio_audio, gradio_bot_text])
|
| 160 |
with gr.Column():
|
| 161 |
gradio_code_area = gr.Code(
|
| 162 |
label="App Code - You can also edit directly and then click Update App or ctrl + space",
|
| 163 |
language='python', value=starting_app_code(DemoType.GRADIO))
|
| 164 |
+
gradio_requirements_area = gr.Code(
|
| 165 |
+
label="App Requirements (additional modules pip installed for pyodide)")
|
| 166 |
+
with gr.Group():
|
| 167 |
+
gradio_update_btn = gr.Button("Update App (Ctrl + Space)", variant="primary",
|
| 168 |
+
elem_classes=["update-btn"])
|
| 169 |
+
gradio_undo_btn = gr.Button("Undo")
|
| 170 |
+
gradio_redo_btn = gr.Button("Redo")
|
| 171 |
+
gradio_error = gr.State()
|
| 172 |
+
gradio_history = gr.State(value=[])
|
| 173 |
+
gradio_index = gr.State(value=0)
|
| 174 |
+
gradio_code_update_params = {'fn': update_state,
|
| 175 |
+
'inputs': [gradio_code_area, gradio_requirements_area, gradio_error,
|
| 176 |
+
gradio_history, gradio_index],
|
| 177 |
+
'outputs': [gradio_requirements_area, gradio_error, gradio_history,
|
| 178 |
+
gradio_index],
|
| 179 |
+
'_js': update_iframe_js(DemoType.GRADIO)}
|
| 180 |
+
gradio_gen_text_params = {'fn': generate_text, 'inputs': [gradio_code_area, gradio_prompt],
|
| 181 |
+
'outputs': [gradio_bot_text, gradio_code_area]}
|
| 182 |
+
gradio_transcribe_params = {'fn': transcribe, 'inputs': [gradio_audio],
|
| 183 |
+
'outputs': [gradio_prompt, gradio_audio]}
|
| 184 |
+
gradio_update_btn.click(**gradio_code_update_params)
|
| 185 |
+
gradio_undo_btn.click(undo, [gradio_code_area, gradio_history, gradio_index],
|
| 186 |
+
[gradio_code_area, gradio_index]).then(**gradio_code_update_params)
|
| 187 |
+
gradio_redo_btn.click(redo, [gradio_code_area, gradio_history, gradio_index],
|
| 188 |
+
[gradio_code_area, gradio_index]).then(**gradio_code_update_params)
|
| 189 |
+
gradio_prompt.submit(**gradio_gen_text_params).then(**gradio_code_update_params)
|
| 190 |
+
gradio_audio.stop_recording(**gradio_transcribe_params).then(**gradio_gen_text_params).then(
|
| 191 |
+
**gradio_code_update_params)
|
| 192 |
with gr.Row():
|
| 193 |
with gr.Column():
|
| 194 |
gr.Markdown("## 3. Export your app to share!")
|
| 195 |
+
gradio_share_link_btn = gr.Button("π Copy share link to clipboard")
|
| 196 |
+
gradio_share_link_btn.click(link_copy_notify, [gradio_code_area, gradio_requirements_area], None,
|
| 197 |
+
_js=copy_share_link_js(DemoType.GRADIO))
|
| 198 |
+
gradio_copy_snippet_btn = gr.Button("βοΈ Copy app snippet to paste into another page")
|
| 199 |
+
gradio_copy_snippet_btn.click(copy_notify, [gradio_code_area, gradio_requirements_area], None,
|
| 200 |
+
_js=copy_snippet_js(DemoType.GRADIO))
|
| 201 |
+
gradio_download_btn = gr.Button("π Download app as a standalone file")
|
| 202 |
+
gradio_download_btn.click(None, [gradio_code_area, gradio_requirements_area], None,
|
| 203 |
+
_js=download_code_js(DemoType.GRADIO))
|
| 204 |
with gr.Row():
|
| 205 |
with gr.Column():
|
| 206 |
gr.Markdown("## Current limitations")
|
|
|
|
| 216 |
with gr.Row():
|
| 217 |
with gr.Column():
|
| 218 |
with gr.Group():
|
| 219 |
+
stlite_audio = gr.Audio(label="Record a voice request (click or press ctrl + ` to start/stop)",
|
| 220 |
+
source='microphone', type='filepath', elem_classes=["record-btn"])
|
| 221 |
+
stlite_prompt = gr.Textbox(label="Or type a text request and press Enter",
|
| 222 |
+
placeholder="Need an idea? Try one of these:\n- Add a button to reverse the name\n- Change the greeting to Spanish\n- Change the theme to soft")
|
| 223 |
+
stlite_bot_text = gr.TextArea(label="π€ Chat Assistant Response")
|
| 224 |
+
stlite_clear_btn = gr.ClearButton([stlite_prompt, stlite_audio, stlite_bot_text])
|
| 225 |
with gr.Column():
|
| 226 |
stlite_code_area = gr.Code(
|
| 227 |
label="App Code - You can also edit directly and then click Update App or ctrl + space",
|
| 228 |
language='python', value=starting_app_code(DemoType.STREAMLIT))
|
| 229 |
+
stlite_requirements_area = gr.Code(
|
| 230 |
+
label="App Requirements (additional modules pip installed for pyodide)")
|
| 231 |
+
with gr.Group():
|
| 232 |
+
stlite_update_btn = gr.Button("Update App (Ctrl + Space)", variant="primary",
|
| 233 |
+
elem_classes=["update-btn"])
|
| 234 |
+
stlite_undo_btn = gr.Button("Undo")
|
| 235 |
+
stlite_redo_btn = gr.Button("Redo")
|
| 236 |
+
stlite_error = gr.State()
|
| 237 |
+
stlite_history = gr.State(value=[])
|
| 238 |
+
stlite_index = gr.State(value=0)
|
| 239 |
+
stlite_code_update_params = {'fn': update_state,
|
| 240 |
+
'inputs': [stlite_code_area, stlite_requirements_area, stlite_error,
|
| 241 |
+
stlite_history, stlite_index],
|
| 242 |
+
'outputs': [stlite_requirements_area, stlite_error, stlite_history,
|
| 243 |
+
stlite_index],
|
| 244 |
+
'_js': update_iframe_js(DemoType.STREAMLIT)}
|
| 245 |
+
stlite_gen_text_params = {'fn': generate_text, 'inputs': [stlite_code_area, stlite_prompt],
|
| 246 |
+
'outputs': [stlite_bot_text, stlite_code_area]}
|
| 247 |
+
stlite_transcribe_params = {'fn': transcribe, 'inputs': [stlite_audio],
|
| 248 |
+
'outputs': [stlite_prompt, stlite_audio]}
|
| 249 |
+
stlite_update_btn.click(**stlite_code_update_params)
|
| 250 |
+
stlite_undo_btn.click(undo, [stlite_code_area, stlite_history, stlite_index],
|
| 251 |
+
[stlite_code_area, stlite_index]).then(**stlite_code_update_params)
|
| 252 |
+
stlite_redo_btn.click(redo, [stlite_code_area, stlite_history, stlite_index],
|
| 253 |
+
[stlite_code_area, stlite_index]).then(**stlite_code_update_params)
|
| 254 |
+
stlite_prompt.submit(**stlite_gen_text_params).then(**stlite_code_update_params)
|
| 255 |
+
stlite_audio.stop_recording(**stlite_transcribe_params).then(**stlite_gen_text_params).then(
|
| 256 |
+
**stlite_code_update_params)
|
| 257 |
with gr.Row():
|
| 258 |
with gr.Column():
|
| 259 |
gr.Markdown("## 3. Export your app to share!")
|
| 260 |
+
stlite_share_link_btn = gr.Button("π Copy share link to clipboard")
|
| 261 |
+
stlite_share_link_btn.click(link_copy_notify, [stlite_code_area, stlite_requirements_area], None,
|
| 262 |
+
_js=copy_share_link_js(DemoType.STREAMLIT))
|
| 263 |
+
stlite_copy_snippet_btn = gr.Button("βοΈ Copy app snippet into paste in another page")
|
| 264 |
+
stlite_copy_snippet_btn.click(copy_notify, [stlite_code_area, stlite_requirements_area], None,
|
| 265 |
+
_js=copy_snippet_js(DemoType.STREAMLIT))
|
| 266 |
+
stlite_download_btn = gr.Button("π Download app as a standalone file")
|
| 267 |
+
stlite_download_btn.click(None, [stlite_code_area, stlite_requirements_area], None,
|
| 268 |
+
_js=download_code_js(DemoType.STREAMLIT))
|
| 269 |
with gr.Row():
|
| 270 |
with gr.Column():
|
| 271 |
gr.Markdown("## Current limitations")
|
|
|
|
| 276 |
_js=load_js(DemoType.GRADIO))
|
| 277 |
stlite_tab.select(lambda: "stlite", None, selectedTab).then(None, None, None, _js=load_js(DemoType.STREAMLIT))
|
| 278 |
demo.load(None, None, None, _js=add_hotkeys())
|
| 279 |
+
demo.load(apply_query_params, [gradio_code_area, stlite_code_area],
|
| 280 |
+
[gradio_code_area, gradio_requirements_area, gradio_history, stlite_code_area, stlite_requirements_area,
|
| 281 |
+
stlite_history, tabs])
|
| 282 |
demo.css = "footer {visibility: hidden}"
|
| 283 |
|
| 284 |
if __name__ == "__main__":
|
templates.py
CHANGED
|
@@ -132,7 +132,7 @@ def load_js(demo_type: DemoType) -> str:
|
|
| 132 |
|
| 133 |
def update_iframe_js(demo_type: DemoType) -> str:
|
| 134 |
if demo_type == DemoType.GRADIO:
|
| 135 |
-
return f"""async (code, requirements) => {{
|
| 136 |
const formattedRequirements = requirements.split('\\n').filter(x => x && !x.startsWith('#')).map(x => x.trim());
|
| 137 |
let errorResult = null;
|
| 138 |
const attemptedRequirements = new Set();
|
|
@@ -180,8 +180,7 @@ def update_iframe_js(demo_type: DemoType) -> str:
|
|
| 180 |
appBody.style.visibility = "hidden";
|
| 181 |
errorResult = e.toString();
|
| 182 |
const allRequirements = formattedRequirements.concat(installedRequirements);
|
| 183 |
-
|
| 184 |
-
return [allRequirements, errorResult];
|
| 185 |
}}
|
| 186 |
}};
|
| 187 |
await update();
|
|
@@ -190,23 +189,29 @@ def update_iframe_js(demo_type: DemoType) -> str:
|
|
| 190 |
// Update URL query params to include the current demo code state
|
| 191 |
const currentUrl = new URL(window.location.href);
|
| 192 |
currentUrl.searchParams.set('type', 'gradio');
|
| 193 |
-
|
| 194 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 195 |
// Replace the current URL with the updated one
|
| 196 |
history.replaceState({{}}, '', currentUrl.href);
|
| 197 |
|
| 198 |
-
return [allRequirements, errorResult];
|
| 199 |
}}"""
|
| 200 |
elif demo_type == DemoType.STREAMLIT:
|
| 201 |
-
return f"""async (code, requirements) => {{
|
| 202 |
-
const formattedRequirements = requirements.split('\\n').filter(x => x && !x.startsWith('#')).map(x => x.trim());
|
| 203 |
let errorResult = null;
|
| 204 |
const attemptedRequirements = new Set();
|
| 205 |
const installedRequirements = [];
|
| 206 |
async function update() {{
|
| 207 |
const appController = document.getElementById('stlite-iframe').contentWindow.window.appController;
|
| 208 |
try {{
|
| 209 |
-
|
|
|
|
|
|
|
| 210 |
const newCode = code + ` # Update tag ${{Math.random()}}`;
|
| 211 |
const entrypointFile = "streamlit_app.py";
|
| 212 |
// TODO: As code rerun happens inside streamlit this won't throw an error for self-healing imports
|
|
@@ -233,7 +238,7 @@ def update_iframe_js(demo_type: DemoType) -> str:
|
|
| 233 |
|
| 234 |
errorResult = e.toString();
|
| 235 |
const allRequirements = formattedRequirements.concat(installedRequirements);
|
| 236 |
-
return [allRequirements, errorResult];
|
| 237 |
}}
|
| 238 |
}};
|
| 239 |
await update();
|
|
@@ -242,12 +247,16 @@ def update_iframe_js(demo_type: DemoType) -> str:
|
|
| 242 |
// Update URL query params to include the current demo code state
|
| 243 |
const currentUrl = new URL(window.location.href);
|
| 244 |
currentUrl.searchParams.set('type', 'streamlit');
|
| 245 |
-
|
| 246 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 247 |
// Replace the current URL with the updated one
|
| 248 |
history.replaceState({{}}, '', currentUrl.href);
|
| 249 |
|
| 250 |
-
return [allRequirements
|
| 251 |
}}"""
|
| 252 |
raise NotImplementedError(f'{demo_type} is not a supported demo type')
|
| 253 |
|
|
|
|
| 132 |
|
| 133 |
def update_iframe_js(demo_type: DemoType) -> str:
|
| 134 |
if demo_type == DemoType.GRADIO:
|
| 135 |
+
return f"""async (code, requirements, lastError, codeHistory, codeHistoryIndex) => {{
|
| 136 |
const formattedRequirements = requirements.split('\\n').filter(x => x && !x.startsWith('#')).map(x => x.trim());
|
| 137 |
let errorResult = null;
|
| 138 |
const attemptedRequirements = new Set();
|
|
|
|
| 180 |
appBody.style.visibility = "hidden";
|
| 181 |
errorResult = e.toString();
|
| 182 |
const allRequirements = formattedRequirements.concat(installedRequirements);
|
| 183 |
+
return [code, allRequirements, errorResult, codeHistory, codeHistoryIndex];
|
|
|
|
| 184 |
}}
|
| 185 |
}};
|
| 186 |
await update();
|
|
|
|
| 189 |
// Update URL query params to include the current demo code state
|
| 190 |
const currentUrl = new URL(window.location.href);
|
| 191 |
currentUrl.searchParams.set('type', 'gradio');
|
| 192 |
+
if (requirements) {{
|
| 193 |
+
currentUrl.searchParams.set('requirements', allRequirements.join('\\n'));
|
| 194 |
+
}}
|
| 195 |
+
if (code) {{
|
| 196 |
+
currentUrl.searchParams.set('code', code);
|
| 197 |
+
}}
|
| 198 |
// Replace the current URL with the updated one
|
| 199 |
history.replaceState({{}}, '', currentUrl.href);
|
| 200 |
|
| 201 |
+
return [code, allRequirements, errorResult, codeHistory, codeHistoryIndex];
|
| 202 |
}}"""
|
| 203 |
elif demo_type == DemoType.STREAMLIT:
|
| 204 |
+
return f"""async (code, requirements, lastError, codeHistory, codeHistoryIndex) => {{
|
| 205 |
+
const formattedRequirements = (requirements || '').split('\\n').filter(x => x && !x.startsWith('#')).map(x => x.trim());
|
| 206 |
let errorResult = null;
|
| 207 |
const attemptedRequirements = new Set();
|
| 208 |
const installedRequirements = [];
|
| 209 |
async function update() {{
|
| 210 |
const appController = document.getElementById('stlite-iframe').contentWindow.window.appController;
|
| 211 |
try {{
|
| 212 |
+
if (formattedRequirements) {{
|
| 213 |
+
await appController.install(formattedRequirements);
|
| 214 |
+
}}
|
| 215 |
const newCode = code + ` # Update tag ${{Math.random()}}`;
|
| 216 |
const entrypointFile = "streamlit_app.py";
|
| 217 |
// TODO: As code rerun happens inside streamlit this won't throw an error for self-healing imports
|
|
|
|
| 238 |
|
| 239 |
errorResult = e.toString();
|
| 240 |
const allRequirements = formattedRequirements.concat(installedRequirements);
|
| 241 |
+
return [code, allRequirements, errorResult, codeHistory, codeHistoryIndex];
|
| 242 |
}}
|
| 243 |
}};
|
| 244 |
await update();
|
|
|
|
| 247 |
// Update URL query params to include the current demo code state
|
| 248 |
const currentUrl = new URL(window.location.href);
|
| 249 |
currentUrl.searchParams.set('type', 'streamlit');
|
| 250 |
+
if (requirements) {{
|
| 251 |
+
currentUrl.searchParams.set('requirements', allRequirements.join('\\n'));
|
| 252 |
+
}}
|
| 253 |
+
if (code) {{
|
| 254 |
+
currentUrl.searchParams.set('code', code);
|
| 255 |
+
}}
|
| 256 |
// Replace the current URL with the updated one
|
| 257 |
history.replaceState({{}}, '', currentUrl.href);
|
| 258 |
|
| 259 |
+
return [code, allRequirements, errorResult, codeHistory, codeHistoryIndex];
|
| 260 |
}}"""
|
| 261 |
raise NotImplementedError(f'{demo_type} is not a supported demo type')
|
| 262 |
|