Continuing the discussion from Download data underlying holoviews/bokeh plot:
I am trying to allow the user to be able to save parts of the UI as a static HTML with the embedded data required for those plots.
The context being a massive Xarray dataset that uses box select to calculate stats on the subset and I want to allow my colleagues to download the resulting Holoviews plots as static HTML (preferably as the template) directly from the browser (I do not want to save the HTML in the App root directory but rather as a download in the browser client side).
I’ve used approaches like that of Mr. @Marc in other apps and have tried Mr. @philippjfr 's solution here but I get a blank HTML and so I wonder if what I am trying to accomplish is doable?
import panel as pn
import holoviews as hv
import numpy as np
from bokeh.resources import INLINE
ACCENT_COLOR = "#308752"
pn.extension(
sizing_mode="stretch_width",
notifications=True
)
class DownloadClientSide(pn.viewable.Viewer):
def _load_callback(self, event):
points = hv.Points(np.random.randn(1000, 2))
selection = hv.streams.Selection1D(source=points)
def selected_info(index):
arr = points.array()[index]
if index:
label = 'Mean x, y: %.3f, %.3f' % tuple(arr.mean(axis=0))
else:
label = 'No selection'
return points.clone(arr, label=label).opts(color='red')
selected_points = hv.DynamicMap(selected_info, streams=[selection])
layout = points.opts(tools=['box_select', 'lasso_select']) + selected_points
self.figs_col.append(pn.pane.HoloViews(layout))
pn.state.notifications.success('_load_callback')
def _download_callback(self):
# pn.save(self.figs_col, 'test.html', resources=INLINE)
# self.figs_col.save('test.html')
pn.state.notifications.success('_download_callback')
sio = io.StringIO()
self.figs_col.save(sio)
sio.seek(0)
return sio
def __init__(self):
self.figs_col = pn.Column()
self.load_button = pn.widgets.Button(name="Load")
self.load_button.on_click(self._load_callback)
self.download_button = pn.widgets.FileDownload(filename='layout.html', callback=self._download_callback)
# self.download_button = pn.widgets.Button(name="Download")
# self.download_button.on_click(self._download_callback)
super().__init__()
def view(self):
return self.download_button
app = DownloadClientSide()
template = pn.template.FastListTemplate(
accent_base_color=ACCENT_COLOR,
header_background=ACCENT_COLOR,
title="Download Client Side",
main=[app.load_button, app.download_button, app.figs_col],
sidebar_width=200,
theme="dark",
).servable()