From 6555234deee3e6cb35d63ab827416fe97c43ef23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Brand=C3=A9ho?= Date: Sat, 29 Jul 2023 01:40:49 +0200 Subject: [PATCH] fix breadcrumb API & add get_page_crumbs method (#1387) --- reflex/components/navigation/breadcrumb.py | 39 +++++++++++++++++----- reflex/constants.py | 1 + reflex/state.py | 10 ++++-- reflex/utils/format.py | 19 +++++++++++ 4 files changed, 59 insertions(+), 10 deletions(-) diff --git a/reflex/components/navigation/breadcrumb.py b/reflex/components/navigation/breadcrumb.py index 2499526fd..d0d8fdcde 100644 --- a/reflex/components/navigation/breadcrumb.py +++ b/reflex/components/navigation/breadcrumb.py @@ -1,7 +1,9 @@ """Breadcrumb components.""" from reflex.components.component import Component +from reflex.components.layout.foreach import Foreach from reflex.components.libs.chakra import ChakraComponent +from reflex.components.navigation.link import Link from reflex.vars import Var @@ -31,11 +33,18 @@ class Breadcrumb(ChakraComponent): The breadcrumb component. """ if len(children) == 0: - children = [] - for label, link in items or []: - children.append( - BreadcrumbItem.create(BreadcrumbLink.create(label, href=link)) - ) + if isinstance(items, Var): + children = [ + Foreach.create( + items, + lambda item: BreadcrumbItem.create(label=item[0], href=item[1]), + ), + ] + + else: + children = [] + for label, link in items or []: + children.append(BreadcrumbItem.create(label=label, href=link)) return super().create(*children, **props) @@ -56,8 +65,22 @@ class BreadcrumbItem(ChakraComponent): # The left and right margin applied to the separator spacing: Var[str] - # The href of the item. - href: Var[str] + @classmethod + def create(cls, *children, label=None, href=None, **props): + """Create a Breadcrumb Item component. + + Args: + children: The children of the component. + label: The label used in the link. Defaults to None. + href: The URL of the link. Defaults to None. + props: The properties of the component. + + Returns: + The BreadcrumbItem component + """ + if len(children) == 0: + children = [BreadcrumbLink.create(label or "", href=href or "")] # type: ignore + return super().create(*children, **props) class BreadcrumbSeparator(ChakraComponent): @@ -66,7 +89,7 @@ class BreadcrumbSeparator(ChakraComponent): tag = "BreadcrumbSeparator" -class BreadcrumbLink(ChakraComponent): +class BreadcrumbLink(Link): """The breadcrumb link.""" tag = "BreadcrumbLink" diff --git a/reflex/constants.py b/reflex/constants.py index d4f7725ae..0914aa89a 100644 --- a/reflex/constants.py +++ b/reflex/constants.py @@ -357,6 +357,7 @@ class RouteVar(SimpleNamespace): CLIENT_TOKEN = "token" HEADERS = "headers" PATH = "pathname" + ORIGIN = "asPath" SESSION_ID = "sid" QUERY = "query" COOKIE = "cookie" diff --git a/reflex/state.py b/reflex/state.py index 48a77639c..28ff24dbe 100644 --- a/reflex/state.py +++ b/reflex/state.py @@ -476,13 +476,19 @@ class State(Base, ABC, extra=pydantic.Extra.allow): """ return self.router_data.get(constants.RouteVar.CLIENT_IP, "") - def get_current_page(self) -> str: + def get_current_page(self, origin=False) -> str: """Obtain the path of current page from the router data. + Args: + origin: whether to return the base route as shown in browser + Returns: The current page. """ - return self.router_data.get(constants.RouteVar.PATH, "") + if origin: + return self.router_data.get(constants.RouteVar.ORIGIN, "") + else: + return self.router_data.get(constants.RouteVar.PATH, "") def get_query_params(self) -> Dict[str, str]: """Obtain the query parameters for the queried page. diff --git a/reflex/utils/format.py b/reflex/utils/format.py index 04cc4fd19..dfcc55768 100644 --- a/reflex/utils/format.py +++ b/reflex/utils/format.py @@ -6,6 +6,7 @@ import base64 import io import json import os +import os.path as op import re import sys from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple, Type @@ -460,6 +461,24 @@ def format_dict(prop: ComponentStyle) -> str: return fprop +def format_breadcrumbs(route: str) -> list[tuple[str, str]]: + """Take a route and return a list of tuple for use in breadcrumb. + + Args: + route: The route to transform. + + Returns: + list[tuple[str, str]]: the list of tuples for the breadcrumb. + """ + route_parts = route.lstrip("/").split("/") + + # create and return breadcrumbs + return [ + (part, op.join("/", *route_parts[: i + 1])) + for i, part in enumerate(route_parts) + ] + + def json_dumps(obj: Any) -> str: """Takes an object and returns a jsonified string.