Repository: h2oai/wave
File: web-ide/web_ide.py (Python)

Code before:
    del q.page['empty']
    q.page['preview'] = ui.frame_card(
        box='preview',
        title=f'Preview of {_server_adress}{path}',
        path=f'{_server_adress}{path}'
    )


async def on_startup():
    # Clean up previous tmp dir.
    await on_shutdown()
    os.mkdir(tmp_dir)


async def on_shutdown():
    dirpath = Path(tmp_dir)
    if dirpath.exists():
        shutil.rmtree(dirpath)

async def export(q: Q):
    tmp_files = [os.path.join(tmp_dir, file) if file.endswith(('.py')) else None for file in os.listdir(tmp_dir)]
    with ZipFile('tmp_project/app.zip','w') as zip:
        for file in tmp_files:
            zip.write(file)
    zip_path = await q.site.upload(['tmp_project/app.zip'])
    webbrowser.open(f"{_server_adress}{zip_path[0]}", autoraise=True)
    os.remove("tmp_project/app.zip")

@app('/ide', on_startup=on_startup, on_shutdown=on_shutdown)
async def serve(q: Q):
    if q.args.export:
        await export(q)
    if not q.app.initialized:
        # Prod.
        if os.path.exists('base-snippets.json') and os.path.exists('component-snippets.json'):
            q.app.snippets1, q.app.snippets2, = await q.site.upload(['base-snippets.json', 'component-snippets.json'])
        # When run in development from Wave repo.
        elif os.path.exists(vsc_extension_path):
            q.app.snippets1, q.app.snippets2, = await q.site.upload([
                os.path.join(vsc_extension_path, 'base-snippets.json'),
                os.path.join(vsc_extension_path, 'component-snippets.json')
            ])
        q.app.app_not_running_img, = await q.site.upload([os.path.join('assets', 'app_not_running.svg')])
        q.app.initialized = True
    if not q.client.initialized:
        await setup_page(q)
        q.client.initialized = True

    await render_code(q)
    await q.page.save()


Review comment (suggestion):
We need user's browser to download the exported file, not the server browser. The current solution will work only locally, but not in production.

Just set the uploaded zip path to ui.button/link for user to download.

Code after:
    q.page['preview'] = ui.frame_card(
        box='preview',
        title=f'Preview of {_server_adress}{path}',
        path=f'{_server_adress}{path}'
    )


async def on_startup():
    # Clean up previous tmp dir.
    await on_shutdown()
    os.mkdir(tmp_dir)


async def on_shutdown():
    dirpath = Path(tmp_dir)
    if dirpath.exists():
        shutil.rmtree(dirpath)

async def export(q: Q):
    shutil.make_archive('app', 'zip', '.', 'tmp_project')
    q.app.zip_path, = await q.site.upload(['app.zip'])
    q.page["meta"].script = ui.inline_script(f"""window.open("{q.app.zip_path}", "_blank");""")
    os.remove("app.zip")

@app('/ide', on_startup=on_startup, on_shutdown=on_shutdown)
async def serve(q: Q):
    if q.args.export:
        await export(q)
    if not q.app.initialized:
        # Prod.
        if os.path.exists('base-snippets.json') and os.path.exists('component-snippets.json'):
            q.app.snippets1, q.app.snippets2, = await q.site.upload(['base-snippets.json', 'component-snippets.json'])
        # When run in development from Wave repo.
        elif os.path.exists(vsc_extension_path):
            q.app.snippets1, q.app.snippets2, = await q.site.upload([
                os.path.join(vsc_extension_path, 'base-snippets.json'),
                os.path.join(vsc_extension_path, 'component-snippets.json')
            ])
        q.app.app_not_running_img, = await q.site.upload([os.path.join('assets', 'app_not_running.svg')])
        q.app.initialized = True
    if not q.client.initialized:
        await setup_page(q)
        q.client.initialized = True
    if q.events.editor:
        await render_code(q)

    await q.page.save()