Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Please add NAVList to Panel #1571

Open
MarcSkovMadsen opened this issue Sep 9, 2020 · 0 comments
Open

Please add NAVList to Panel #1571

MarcSkovMadsen opened this issue Sep 9, 2020 · 0 comments
Labels
type: enhancement Minor feature or improvement to an existing feature

Comments

@MarcSkovMadsen
Copy link
Collaborator

MarcSkovMadsen commented Sep 9, 2020

Intro

I would like it to be easy to create awesome analytics apps using Panel. One of the things you need is good ways of laying out your app.

Inspired by my own explorations and the Shiny layout-guide.

I can see we are lacking some elements this includes a NavigationLIst. I believe the NavigationLIst can be visualized in many different ways but would have some foundational, shared API.

Visualizations

Shiny

image

Awesome-Panel Dropdown

image

Awesome-Panel Gallery

image

VS Code

image

API

I believe the NavigationList consists of a List of NavigationItems and/ NavigationURLItems. The latter to also enable navigating to both suburls and external urls.

As the NavigationList can be long and the NavigationItem a large application in it self, Lazy loading should be supported. I.e. you can provide functions, classes and modules instead of instantiated objects. The NavigationItem will instantiate when needed and keep the instantiated version when leaving the "page" such that it re-loads fast and with the state where you left.

The NavigationItem should be able to support simple use case where all you have is a Panel Layout, Pane or Widget with a Name up to more complex objects where you want to provide what goes into the main and sidebar areas and maybe on top meta data like icon, thumbnail, description, author, group, show_spinner_while_loading, page_max_width, ....

You can use all the meta data to create the index page, a gallery page, a navigation widget for the top or sidebar. Maybe restrict access to groups. Maybe to enable searching for pages etc. It's just really, really nice to have as your application grows.

Additional Context

At awesome-panel.org I am using a preliminary version of this. It think it turned out a little bit to complex to explain. So I've never "marketed" it. But the core principles are there.

NavigationList: PageService, PageNavigationComponent
NavigationItem: Page, PageComponent

class Page(OrderByNameMixin, param.Parameterized):
    """This Page Model contains the
    - page component (For example a PageComponent)
    - meta parameters like author and description"""

    author = param.ClassSelector(class_=Author, allow_None=True)
    description = param.String()
    tags = param.List()
    source_code_url = param.String()
    thumbnail_png_url = param.String()
    component = param.Parameter()
    show_loading_page = param.Boolean(default=False)
    restrict_max_width = param.Boolean(default=True)

    def __hash__(self,):
        return hash(self.name)
class PageComponent(param.Parameterized):
    """The PageComponent defines a page
Use it for
- Creating an instance by providing its parameters
- Creating SubClass implementations
- Creating PageComponents from many types of components via the `create` function
"""

    page = param.ClassSelector(class_=Page, allow_None=False)
    main = param.Parameter(allow_None=False)
    sidebar = param.Parameter(allow_None=True)
    progress = param.ClassSelector(class_=Progress)
    toast = param.ClassSelector(class_=Toast)
    show_loading_page = param.Boolean(default=False, allow_None=False)

    def __init__(self, **params):
        if "progress" not in params:
            params["progress"] = Progress()
        if "toast" not in params:
            params["toast"] = Toast()

        super().__init__(**params)

    @classmethod
    def create(cls, component) -> "PageComponent":
        """Creates a PageComponent from the component
        This method
        Args:
            component Anything that is a Panel or Panel can convert to a Panel.
                - Also supports functions, classes and modules that have main, view and/ or sidebar
                attributes or functions.
                - If the object is already a PageComponent it is just returned.
        Returns:
            PageComponent: An instance of PageComponent
        """
        if inspect.isclass(component):
            component = component()

        if issubclass(type(component), cls):
            return component

        if hasattr(component, "main"):
            main = component.main
        elif hasattr(component, "view"):
            main = component.view
        else:
            main = component
        if callable(main):
            main = main()

        if hasattr(component, "sidebar"):
            sidebar = component.sidebar
        else:
            sidebar = None
        if callable(sidebar):
            sidebar = sidebar()

        return cls(main=main, sidebar=sidebar)
@MarcSkovMadsen MarcSkovMadsen added the TRIAGE Default label for untriaged issues label Sep 9, 2020
@philippjfr philippjfr added type: enhancement Minor feature or improvement to an existing feature and removed TRIAGE Default label for untriaged issues labels Sep 29, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: enhancement Minor feature or improvement to an existing feature
Projects
None yet
Development

No branches or pull requests

2 participants