Skip to content

Commit 0900a3c

Browse files
committed
feat: add view type based on url hash
1 parent e21b609 commit 0900a3c

1 file changed

Lines changed: 88 additions & 12 deletions

File tree

pydelmod/dvue/dataui.py

Lines changed: 88 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,12 @@ class DataUI(param.Parameterized):
169169
Actions on the selections are supported via the buttons on the table. These are configurable by the catalog manager.
170170
"""
171171

172+
view_type = param.Selector(
173+
objects=["combined", "table", "display"],
174+
default="combined",
175+
doc="Type of view to display: combined, table only, or display panel only",
176+
)
177+
172178
map_color_category = param.Selector(
173179
objects=[],
174180
doc="Options for the map color category selection",
@@ -194,8 +200,8 @@ class DataUI(param.Parameterized):
194200
doc='Query to filter stations. See <a href="https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.query.html">Pandas Query</a> for details. E.g. max_year <= 2023',
195201
)
196202
use_regex_filter = param.Boolean(
197-
default=False,
198-
doc="Use regex for table filtering instead of 'like' functionality"
203+
default=False,
204+
doc="Use regex for table filtering instead of 'like' functionality",
199205
)
200206

201207
def __init__(
@@ -480,12 +486,12 @@ def update_data_table_filters(self):
480486
if self.use_regex_filter:
481487
# Update filters to use regex
482488
for column in self.display_table.header_filters:
483-
#self.display_table.header_filters[column]["type"] = "regex"
489+
# self.display_table.header_filters[column]["type"] = "regex"
484490
self.display_table.header_filters[column]["func"] = "regex"
485491
else:
486492
# Revert to 'like' functionality
487493
for column in self.display_table.header_filters:
488-
#self.display_table.header_filters[column]["type"] = "input"
494+
# self.display_table.header_filters[column]["type"] = "input"
489495
self.display_table.header_filters[column]["func"] = "like"
490496
self.display_table.header_filters = self.display_table.header_filters
491497

@@ -522,15 +528,16 @@ def create_data_table(self, dfs):
522528
)
523529
gspec = pn.GridStack(
524530
sizing_mode="stretch_both", allow_resize=True, allow_drag=False
525-
) # ,
531+
)
526532
gspec[0, 0:5] = self._action_panel
527533
gspec[1:5, 0:10] = fullscreen.FullScreen(pn.Row(self.display_table))
528534
gspec[6:15, 0:10] = fullscreen.FullScreen(self._display_panel)
535+
self._main_panel = gspec
529536
return gspec
530537

531538
def setup_location_sync(self):
532-
self.location = location.Location()
533-
self.location.sync(self.display_table, ["filters", "selection"])
539+
pn.state.location.param.watch(self.update_view_from_location, "hash")
540+
self.update_view_from_location()
534541

535542
def get_version(self):
536543
try:
@@ -565,9 +572,63 @@ def about_callback(event):
565572
about_btn.on_click(about_callback)
566573
return about_btn
567574

575+
def _create_main_view(self):
576+
"""Create the main view content based on the current view_type"""
577+
if self.view_type == "table":
578+
gspec = pn.GridStack(
579+
sizing_mode="stretch_both", allow_resize=False, allow_drag=False
580+
)
581+
gspec[0, 0:5] = self._action_panel
582+
gspec[1:15, 0:10] = fullscreen.FullScreen(pn.Row(self.display_table))
583+
return gspec
584+
elif self.view_type == "display":
585+
gspec = pn.GridStack(
586+
sizing_mode="stretch_both", allow_resize=False, allow_drag=False
587+
)
588+
gspec[0, 0:5] = self._action_panel
589+
gspec[1:15, 0:10] = fullscreen.FullScreen(self._display_panel)
590+
return gspec
591+
else: # combined view
592+
return pn.Column(
593+
pn.Row(self._main_panel, sizing_mode="stretch_both"),
594+
sizing_mode="stretch_both",
595+
)
596+
597+
def create_view_navigation(self):
598+
"""Create navigation buttons for switching between views"""
599+
nav_buttons = pn.Row(
600+
pn.widgets.Button(name="Combined", button_type="primary"),
601+
pn.widgets.Button(name="Table", button_type="primary"),
602+
pn.widgets.Button(name="Display", button_type="primary"),
603+
)
604+
605+
def set_hash(event):
606+
button_name = event.obj.name.lower().split()[0]
607+
pn.state.location.hash = f"#{button_name}"
608+
609+
for btn in nav_buttons:
610+
btn.on_click(set_hash)
611+
612+
return nav_buttons
613+
614+
def update_view_from_location(self, event=None):
615+
"""Update the view based on the URL hash value"""
616+
hash_value = pn.state.location.hash.lstrip("#")
617+
618+
# Map hash values to view types
619+
if hash_value == "table":
620+
self.view_type = "table"
621+
elif hash_value == "display":
622+
self.view_type = "display"
623+
else:
624+
self.view_type = "combined"
625+
626+
# Update the template main content based on the selected view
627+
if hasattr(self, "_main_view"):
628+
self._main_view.objects = [self._create_main_view()]
629+
568630
def create_view(self, title="Data User Interface"):
569631
main_panel = self.create_data_table(self._dfcat)
570-
self.setup_location_sync()
571632
control_widgets = self._dataui_manager.get_widgets()
572633

573634
# Create progress bar
@@ -580,10 +641,11 @@ def create_view(self, title="Data User Interface"):
580641
bar_color="primary",
581642
visible=False,
582643
)
583-
644+
584645
table_options = pn.WidgetBox(
585646
"Table Options",
586-
self.param.use_regex_filter,)
647+
self.param.use_regex_filter,
648+
)
587649
if hasattr(self, "_map_features"):
588650
map_options = pn.WidgetBox(
589651
"Map Options",
@@ -635,19 +697,33 @@ def create_view(self, title="Data User Interface"):
635697
sidebar_view = pn.Column(
636698
pn.Tabs(("Options", control_widgets)), self.progress_bar
637699
)
638-
main_view = pn.Column(pn.Row(main_panel, sizing_mode="stretch_both"))
700+
# Create view navigation buttons
701+
nav_buttons = pn.Row(self.create_view_navigation())
702+
703+
# Create the initial main view based on URL hash
704+
self._main_view = pn.Column(
705+
self._create_main_view(), sizing_mode="stretch_both"
706+
)
639707

640708
template = pn.template.VanillaTemplate(
641709
title=title,
642710
sidebar=[sidebar_view],
643711
sidebar_width=450,
644712
header_color="lightgray",
645713
)
646-
template.main.append(main_view)
714+
715+
# Add navigation before the main content
716+
template.header.append(nav_buttons)
717+
template.main.append(self._main_view)
718+
647719
# Adding about button
648720
template.modal.append(self.get_about_text())
649721
sidebar_view.append(self.create_about_button(template))
650722
self._template = template
723+
724+
# finally sync location views
725+
self.setup_location_sync()
726+
651727
return template
652728

653729
def set_progress(self, value):

0 commit comments

Comments
 (0)