import panel as pn import param from typing import List, Tuple pn.extension("floatpanel") class MainHeader(pn.viewable.Viewer): """ MainHeader class represents the header section of the dashboard. It includes a heading, subheading, and a series of buttons with configurable actions. """ # Parameters for the header and subheading text heading: str = param.String( default="Default Heading", doc="The heading text", allow_refs=True ) subheading: str = param.String( default="Default Subheading", doc="The subheading text", allow_refs=True ) # Parameters for the names of up to 12 buttons button_1_name: str = param.String( default="Button 1", doc="Name for Button 1", allow_refs=True ) button_2_name: str = param.String( default="Button 2", doc="Name for Button 2", allow_refs=True ) button_3_name: str = param.String( default="Button 3", doc="Name for Button 3", allow_refs=True ) button_4_name: str = param.String( default="Button 4", doc="Name for Button 4", allow_refs=True ) button_5_name: str = param.String( default="Button 5", doc="Name for Button 5", allow_refs=True ) button_6_name: str = param.String( default="Button 6", doc="Name for Button 6", allow_refs=True ) button_7_name: str = param.String( default="Button 7", doc="Name for Button 7", allow_refs=True ) button_8_name: str = param.String( default="Button 8", doc="Name for Button 8", allow_refs=True ) button_9_name: str = param.String( default="Button 9", doc="Name for Button 9", allow_refs=True ) button_10_name: str = param.String( default="Button 10", doc="Name for Button 10", allow_refs=True ) button_11_name: str = param.String( default="Button 11", doc="Name for Button 11", allow_refs=True ) button_12_name: str = param.String( default="Button 12", doc="Name for Button 12", allow_refs=True ) # Parameters for the actions associated with each button button_1_action = param.Parameter(doc="Action for Button 1") button_2_action = param.Parameter(doc="Action for Button 2") button_3_action = param.Parameter(doc="Action for Button 3") button_4_action = param.Parameter(doc="Action for Button 4") button_5_action = param.Parameter(doc="Action for Button 5") button_6_action = param.Parameter(doc="Action for Button 6") button_7_action = param.Parameter(doc="Action for Button 7") button_8_action = param.Parameter(doc="Action for Button 8") button_9_action = param.Parameter(doc="Action for Button 9") button_10_action = param.Parameter(doc="Action for Button 10") button_11_action = param.Parameter(doc="Action for Button 11") button_12_action = param.Parameter(doc="Action for Button 12") def __init__(self, **params): """ Initializes the MainHeader class with the provided parameters. """ super().__init__(**params) def __panel__(self): """ Returns the Panel layout for the header, including the heading, subheading, and buttons. """ # Create HTML panes for heading and subheading heading_pane = pn.pane.HTML( pn.bind(lambda heading: f"

{heading}

", self.param.heading) ) subheading_pane = pn.pane.HTML( pn.bind(lambda subheading: f"

{subheading}

", self.param.subheading) ) # Create buttons based on the provided names and actions buttons = [] if self.button_1_name and self.button_1_action: buttons.append( pn.widgets.Button( name=self.button_1_name, button_type="primary", width=70, height=30, margin=(5, 5), on_click=self.button_1_action, ) ) if self.button_2_name and self.button_2_action: buttons.append( pn.widgets.Button( name=self.button_2_name, button_type="primary", width=70, height=30, margin=(5, 5), on_click=self.button_2_action, ) ) if self.button_3_name and self.button_3_action: buttons.append( pn.widgets.Button( name=self.button_3_name, button_type="primary", width=70, height=30, margin=(5, 5), on_click=self.button_3_action, ) ) if self.button_4_name and self.button_4_action: buttons.append( pn.widgets.Button( name=self.button_4_name, button_type="primary", width=70, height=30, margin=(5, 5), on_click=self.button_4_action, ) ) if self.button_5_name and self.button_5_action: buttons.append( pn.widgets.Button( name=self.button_5_name, button_type="primary", width=70, height=30, margin=(5, 5), on_click=self.button_5_action, ) ) if self.button_6_name and self.button_6_action: buttons.append( pn.widgets.Button( name=self.button_6_name, button_type="primary", width=70, height=30, margin=(5, 5), on_click=self.button_6_action, ) ) if self.button_7_name and self.button_7_action: buttons.append( pn.widgets.Button( name=self.button_7_name, button_type="primary", width=70, height=30, margin=(5, 5), on_click=self.button_7_action, ) ) if self.button_8_name and self.button_8_action: buttons.append( pn.widgets.Button( name=self.button_8_name, button_type="primary", width=70, height=30, margin=(5, 5), on_click=self.button_8_action, ) ) if self.button_9_name and self.button_9_action: buttons.append( pn.widgets.Button( name=self.button_9_name, button_type="primary", width=70, height=30, margin=(5, 5), on_click=self.button_9_action, ) ) if self.button_10_name and self.button_10_action: buttons.append( pn.widgets.Button( name=self.button_10_name, button_type="primary", width=70, height=30, margin=(5, 5), on_click=self.button_10_action, ) ) if self.button_11_name and self.button_11_action: buttons.append( pn.widgets.Button( name=self.button_11_name, button_type="primary", width=70, height=30, margin=(5, 5), on_click=self.button_11_action, ) ) if self.button_12_name and self.button_12_action: buttons.append( pn.widgets.Button( name=self.button_12_name, button_type="primary", width=70, height=30, margin=(5, 5), on_click=self.button_12_action, ) ) # Create the layout for the header layout_items = [heading_pane] if self.subheading and self.subheading != "Default Subheading": layout_items.append(subheading_pane) # Create the layout for the header layout = pn.Row( pn.Column(*layout_items), pn.FlexBox( *buttons, align_items="center", justify_content="end", flex_wrap="wrap", ), ) return layout class MainArea(pn.viewable.Viewer): """ MainArea class represents the main content area of the dashboard, containing multiple tabs. """ # Parameter for the content of the tabs, as a dictionary with tab names as keys and content as values tabs_content: dict = param.Dict( default={}, doc="Dictionary with tab names as keys and content as values", allow_refs=True, ) def __init__(self, **params): """ Initializes the MainArea class with the provided parameters. """ super().__init__(**params) def __panel__(self): """ Returns the Panel layout for the main area, which includes tabs with their respective content. """ tabs = pn.Tabs(dynamic=True) for tab_name, content in self.tabs_content.items(): tabs.append((tab_name, content)) flexbox_layout = pn.FlexBox( tabs, sizing_mode="stretch_both", align_items="stretch", justify_content="space-between", ) return flexbox_layout class OutputBox(pn.viewable.Viewer): """ OutputBox class represents a box to display output content. """ # Parameter for the content to display in the output box output_content: str = param.String( default="", doc="Content to display in the output box", allow_refs=True ) def __init__(self, **params): """ Initializes the OutputBox class with the provided parameters. """ super().__init__(**params) def __panel__(self): """ Returns the Panel layout for the output box, including a heading and the content. """ heading = pn.pane.Markdown("

Output

") output_box = pn.widgets.TextAreaInput( name="", value=self.output_content, disabled=True, min_height=220, sizing_mode="stretch_both", ) return pn.Column(heading, output_box, sizing_mode="stretch_both") class WarningBox(pn.viewable.Viewer): """ WarningBox class represents a box to display warning content. """ # Parameter for the content to display in the warning box warning_content: str = param.String( default="", doc="Content to display in the warning box", allow_refs=True ) def __init__(self, **params): """ Initializes the WarningBox class with the provided parameters. """ super().__init__(**params) def __panel__(self): """ Returns the Panel layout for the warning box, including a heading and the content. """ heading = pn.pane.Markdown("

Warning

") warning_box = pn.widgets.TextAreaInput( name="", value=self.warning_content, disabled=True, min_height=220, sizing_mode="stretch_both", ) return pn.Column(heading, warning_box, sizing_mode="stretch_both") class PlotsContainer(pn.viewable.Viewer): """ PlotsContainer class represents a container for displaying multiple plots. """ flexbox_contents: list = param.List(default=[], doc="Contents for FlexBox containers", allow_refs=True) def __init__(self, *contents, **params): super().__init__(**params) self.flexbox_contents = list(contents) def __panel__(self): """ Returns the Panel layout for the plots container. """ title = pn.pane.Markdown("

Plots

", align="center") flexbox_container = pn.FlexBox( *self.flexbox_contents, flex_direction='row', align_content='space-evenly', align_items="center", justify_content="center", flex_wrap="wrap" ) return pn.Column(title, flexbox_container, sizing_mode="stretch_both") class HelpBox(pn.viewable.Viewer): """ HelpBox class represents a box to display help or documentation content. """ # Parameters for the title and content of the help box title: str = param.String( default="Help", doc="Title for the help box", allow_refs=True ) help_content: str = param.String( default="", doc="Markdown content for the help box", allow_refs=True ) def __init__(self, **params): """ Initializes the HelpBox class with the provided parameters. """ super().__init__(**params) def __panel__(self): """ Returns the Panel layout for the help box, including a heading and Markdown content. """ heading = pn.pane.Markdown(f"

{self.title}

") help_markdown = pn.pane.Markdown(self.help_content, sizing_mode="stretch_both") return pn.Column(heading, help_markdown, sizing_mode="stretch_both") class Footer(pn.viewable.Viewer): """ Footer class represents the footer section of the dashboard. It includes the main content, additional links, and icon buttons. """ # Parameters for the main content, additional links, and icons in the footer main_content: str = param.String( default="", doc="Main content to display in the footer", allow_refs=True ) additional_links: List[str] = param.List( default=[], doc="List of additional links as markdown strings", allow_refs=True ) icons: List[pn.viewable.Viewer] = param.List( default=[], doc="List of icon buttons", allow_refs=True ) def __init__(self, **params): """ Initializes the Footer class with the provided parameters. """ super().__init__(**params) def __panel__(self): """ Returns the Panel layout for the footer, including logo, name, links, icons, and contact information. """ logo = pn.pane.PNG( "../assets/images/stingray_explorer.png", width=100, height=100, align="center", ) name = pn.pane.Markdown("Stingray Explorer", align="center") logo_name_pane = pn.FlexBox( logo, name, flex_direction="column", justify_content="center", align_items="center", ) links = [pn.pane.Markdown(link) for link in self.additional_links] links_pane = pn.FlexBox( *links, flex_direction="column", justify_content="center", align_items="center", ) icons_pane = pn.FlexBox( *self.icons, flex_direction="column", justify_content="center", align_items="center", ) contact_us_pane = pn.FlexBox( pn.pane.Markdown("Email: kartik4321mandar@gmail.com"), pn.pane.Markdown("Slack: @kartikmandar"), flex_direction="row", justify_content="center", align_items="center", ) copyright_pane = pn.pane.Markdown( """ © 2024, Stingray. All rights reserved. """, ) pane1 = pn.FlexBox( logo_name_pane, links_pane, icons_pane, flex_direction="row", justify_content="space-between", align_items="center", ) pane2 = pn.FlexBox( contact_us_pane, flex_direction="column", justify_content="center", align_items="center", ) pane3 = pn.FlexBox( copyright_pane, flex_direction="row", justify_content="center", align_items="center", ) footer = pn.FlexBox( pane1, pane2, pane3, flex_direction="row", justify_content="center", align_items="center", ) return footer # Custom warning handler class WarningHandler: def __init__(self): self.warnings = [] def warn( self, message, category=None, filename=None, lineno=None, file=None, line=None ): warning_message = f"Message: {message}\nCategory: {category.__name__ if category else 'N/A'}\nFile: {filename if filename else 'N/A'}\nLine: {lineno if lineno else 'N/A'}\n" self.warnings.append(warning_message) class FloatingPlot(pn.viewable.Viewer): """ Floating Plot Container class represents a container for displaying a single plot. """ # Parameters for the title and content of Floating Panel title: str = param.String(default="", doc="Title for Floating Panel") content: pn.viewable.Viewer = param.Parameter( default=None, doc="Content for Floating Panel" ) def __init__(self, title="", content=None, **params): """ Initializes FloatingPlot class with the provided parameters. """ super().__init__(**params) self.title = title self.content = content @property def object(self): print(f"Object property called for {self.content}") return self.content def __panel__(self): """ Returns the floating panel which contains the content with the appropriate heading. """ if not self.title or not self.content: raise ValueError("Title and content must be provided.") float_panel = pn.layout.FloatPanel( self.content, name=str(self.title), contained=False, position="center", width=700, height=700, margin=20, theme="success", ) return float_panel