from io import StringIO from pathlib import Path import pandas as pd import panel as pn from panel_gwalker import GraphicWalker pn.extension("filedropper", sizing_mode="stretch_width", notifications=True) ROOT = Path(__file__).parent PANEL_GW_URL = "https://github.com/panel-extensions/panel-graphic-walker" GW_LOGO = "https://kanaries.net/_next/static/media/kanaries-logo.0a9eb041.png" GW_API = "https://github.com/Kanaries/graphic-walker" GW_GUIDE_URL = "https://docs.kanaries.net/graphic-walker/data-viz/create-data-viz" SPEC_CAPACITY_STATE = "https://cdn.jsdelivr.net/gh/panel-extensions/panel-graphic-walker@main/examples/reference_app/spec_simple.json" SPEC_SIMPLE = "https://cdn.jsdelivr.net/gh/panel-extensions/panel-graphic-walker@main/examples/reference_app/spec_capacity_state.json" ACCENT = "#5B8FF9" def _label(value): return pn.pane.Markdown(value, margin=(-20, 5)) def _section_header(value): return pn.pane.Markdown(value, margin=(-5, 5)) @pn.cache def get_data(): return pd.read_parquet( "https://datasets.holoviz.org/windturbines/v1/windturbines.parq" ) def get_example_download(): df = pd.DataFrame( {"country": ["Denmark", "Germany"], "population": [5_000_000, 80_000_000]} ) sio = StringIO() df.to_csv(sio, index=False) sio.seek(0) return sio button_style = dict(button_type="primary", button_style="outline") walker = GraphicWalker( get_data(), spec=SPEC_CAPACITY_STATE, sizing_mode="stretch_both", kernel_computation=True, ) core_settings = pn.Column( walker.param.kernel_computation, walker.param.spec, walker.param.config, walker.param.renderer, pn.widgets.IntInput.from_param( walker.param.page_size, visible=walker.is_enabled("page_size") ), pn.widgets.Checkbox.from_param( walker.param.hide_profiling, visible=walker.is_enabled("hide_profiling") ), pn.widgets.IntInput.from_param( walker.param.index, visible=walker.is_enabled("index") ), pn.widgets.RadioButtonGroup.from_param( walker.param.tab, visible=walker.is_enabled("tab"), button_type="primary", button_style="outline", ), pn.widgets.TextInput.from_param( walker.param.container_height, visible=walker.is_enabled("container_height") ), name="Core", ) style_settings = pn.Column( _label("Appearance"), pn.widgets.RadioButtonGroup.from_param(walker.param.appearance, **button_style), _label("Theme Key"), pn.widgets.RadioButtonGroup.from_param(walker.param.theme_key, **button_style), name="Style", ) file_upload = pn.widgets.FileDropper( accepted_filetypes=["text/csv"], multiple=False, max_file_size="5MB", styles={"border": "1px dashed black", "border-radius": "4px"}, height=85, ) file_download = pn.widgets.FileDownload( callback=get_example_download, filename="example.csv" ) export_controls = walker.export_controls() exported = pn.rx(""" ```bash {value} ``` """).format(value=export_controls.param.value) export_section = pn.Column(export_controls, exported, name="Export") save_section = pn.Column(walker.save_controls(), name="Save") docs_section = f"## Docs\n\n- [panel-graphic-walker]({PANEL_GW_URL})\n- [Graphic Walker Usage Guide]({GW_GUIDE_URL})\n- [Graphic Walker API]({GW_API})" def _apply_spec(value): if walker.spec == value: walker.param.trigger("spec") else: walker.spec = value simple_spec = pn.widgets.Button( name="Simple", button_type="primary", button_style="outline", on_click=lambda event: _apply_spec(SPEC_SIMPLE), ) initial_spec = pn.widgets.Button( name="Initial", button_type="primary", button_style="outline", on_click=lambda event: _apply_spec(SPEC_CAPACITY_STATE), ) no_spec = pn.widgets.Button( name="No Spec", button_type="primary", button_style="outline", on_click=lambda event: _apply_spec(None), ) @pn.depends(file_upload, watch=True) def _update_walker(value): if value: text = next(iter(value.values())) df = pd.read_csv(StringIO(text)) if not df.empty: walker.object = df # Can be removed once https://github.com/panel-extensions/panel-graphic-walker/issues/33 is resolved pn.state.notifications.success( "New dataset uploaded. Add a new chart to use it.", duration=5000 ) pn.template.FastListTemplate( logo=GW_LOGO, title="Panel Graphic Walker Reference App", sidebar=[ "## Data Input", file_upload, file_download, "## Spec Input", pn.Row(simple_spec, no_spec, initial_spec), "## Settings", pn.Accordion( core_settings, style_settings, export_section, save_section, width=320, active=[0], ), docs_section, ], main=[walker], main_layout=None, accent="#5B8FF9", ).servable()