From f46c32bc958fc323cf07da18f9c6ca61060a56c1 Mon Sep 17 00:00:00 2001 From: huong-li-nguyen Date: Mon, 11 Dec 2023 18:14:26 +0100 Subject: [PATCH 1/9] Arrange containers --- vizro-core/src/vizro/models/_dashboard.py | 43 ++++++++++++++++++----- 1 file changed, 35 insertions(+), 8 deletions(-) diff --git a/vizro-core/src/vizro/models/_dashboard.py b/vizro-core/src/vizro/models/_dashboard.py index c1d78c4b3..2434956d1 100644 --- a/vizro-core/src/vizro/models/_dashboard.py +++ b/vizro-core/src/vizro/models/_dashboard.py @@ -7,7 +7,7 @@ import dash import dash_bootstrap_components as dbc import dash_daq as daq -from dash import ClientsideFunction, Input, Output, clientside_callback, get_relative_path, html +from dash import ClientsideFunction, Input, Output, clientside_callback, get_asset_url, get_relative_path, html try: from pydantic.v1 import Field, validator @@ -97,10 +97,18 @@ def build(self): def _make_page_layout(self, page: Page): # Identical across pages + # TODO: Implement proper way of automatically pulling file called logo in assets folder (should support svg, png and it shouldn't matter where it's placed in the assets folder) + # TODO: Implement condition check if image can be found/not found + # TODO: Update paddings/margins to fit all cross-combinations + dashboard_logo = ( + html.Div([html.Img(src=get_asset_url("logo.svg"), className="logo-img")], className="logo", id="logo-outer") + if True + else html.Div(id="logo-outer", hidden=True) + ) dashboard_title = ( - html.Div(children=[html.H2(self.title), html.Hr()], className="dashboard_title", id="dashboard_title_outer") + html.Div(children=[html.H2(self.title)], id="dashboard-title") if self.title - else html.Div(hidden=True, id="dashboard_title_outer") + else html.Div(hidden=True, id="dashboard-title") ) theme_switch = daq.BooleanSwitch( id="theme_selector", on=self.theme == "vizro_dark", persistence=True, persistence_type="session" @@ -119,16 +127,35 @@ def _make_page_layout(self, page: Page): component_container = page_content["component_container_outer"] # Arrangement - header = html.Div(children=[page_title, theme_switch], className="header", id="header_outer") - nav_control_elements = [dashboard_title, nav_panel, control_panel] + left_header_elements = [dashboard_title] + icon_logo_elements = [nav_bar] + if getattr(nav_bar, "hidden", False) is False: + icon_logo_elements.insert(0, dashboard_logo) + else: + left_header_elements.insert(0, dashboard_logo) + + right_header = html.Div(children=[page_title, theme_switch], className="right-header") + left_header = ( + html.Div(children=left_header_elements, className="left-header") + if any(not getattr(element, "hidden", False) for element in left_header_elements) + else None + ) + nav_control_elements = [left_header, nav_panel, control_panel] + nav_control_panel = ( html.Div(nav_control_elements, className="nav_control_panel") if any(not getattr(element, "hidden", False) for element in nav_control_elements) else None ) - - left_side = html.Div(children=[nav_bar, nav_control_panel], className="left_side", id="left_side_outer") - right_side = html.Div(children=[header, component_container], className="right_side", id="right_side_outer") + nav_logo_bar = ( + html.Div(children=icon_logo_elements, className="nav-logo-bar") + if any(not getattr(element, "hidden", False) for element in icon_logo_elements) + else None + ) + left_side = html.Div(children=[nav_logo_bar, nav_control_panel], className="left_side", id="left_side_outer") + right_side = html.Div( + children=[right_header, component_container], className="right_side", id="right_side_outer" + ) return html.Div([left_side, right_side], className="page_container", id="page_container_outer") @staticmethod From 359a1c81959b49f4c8da322e14e008abb563db1d Mon Sep 17 00:00:00 2001 From: huong-li-nguyen Date: Mon, 11 Dec 2023 18:14:49 +0100 Subject: [PATCH 2/9] Update CSS --- .../vizro/models/_navigation/navigation.py | 2 +- vizro-core/src/vizro/static/css/accordion.css | 4 +- vizro-core/src/vizro/static/css/layout.css | 43 +++++++++++++++---- .../models/_navigation/test_navigation.py | 2 +- 4 files changed, 38 insertions(+), 13 deletions(-) diff --git a/vizro-core/src/vizro/models/_navigation/navigation.py b/vizro-core/src/vizro/models/_navigation/navigation.py index f71b75096..8512f72fa 100644 --- a/vizro-core/src/vizro/models/_navigation/navigation.py +++ b/vizro-core/src/vizro/models/_navigation/navigation.py @@ -46,6 +46,6 @@ def build(self, *, active_page_id=None) -> _NavBuildType: # e.g. nav_selector is Accordion and nav_selector.build returns single html.Div with id="nav_panel_outer". # This will make it match the case e.g. nav_selector is NavBar and nav_selector.build returns html.Div # containing children with id="nav_bar_outer" and id="nav_panel_outer" - nav_selector = html.Div([html.Div(className="hidden", id="nav_bar_outer"), nav_selector]) + nav_selector = html.Div([html.Div(hidden=True, id="nav_bar_outer"), nav_selector]) return nav_selector diff --git a/vizro-core/src/vizro/static/css/accordion.css b/vizro-core/src/vizro/static/css/accordion.css index 0993c5cb6..c8e2a9f6f 100644 --- a/vizro-core/src/vizro/static/css/accordion.css +++ b/vizro-core/src/vizro/static/css/accordion.css @@ -42,8 +42,7 @@ overflow-anchor: none; background-color: inherit; letter-spacing: -0.014px; - padding: 16px 8px; - height: 56px; + padding: var(--spacing-02); } .accordion-button:not(.collapsed) { @@ -79,7 +78,6 @@ display: flex; flex-direction: column; overflow-x: hidden; - margin-top: -10px; } .accordion-item-header { diff --git a/vizro-core/src/vizro/static/css/layout.css b/vizro-core/src/vizro/static/css/layout.css index 33d25a5ef..14310995c 100644 --- a/vizro-core/src/vizro/static/css/layout.css +++ b/vizro-core/src/vizro/static/css/layout.css @@ -14,7 +14,7 @@ padding: 40px 32px 0 32px; width: 352px; overflow: auto; - gap: var(--spacing-08); + gap: var(--spacing-06); } .left_side { @@ -31,7 +31,7 @@ width: 100%; } -.header { +.right-header { align-items: baseline; display: flex; flex-direction: row; @@ -39,6 +39,17 @@ justify-content: space-between; } +.left-header { + display: flex; + flex-direction: row; + width: 100%; + gap: 8px; +} + +.left-header:not(:empty) { + border-bottom: 1px solid var(--border-subtle-alpha-01); +} + .component_container { display: flex; height: 100%; @@ -58,6 +69,7 @@ } .nav_panel:not(:empty) { + padding-bottom: 8px; border-bottom: 1px solid var(--border-subtle-alpha-01); } @@ -108,17 +120,12 @@ .nav-bar { display: inline-flex; flex-direction: column; - width: 64px; - padding-top: 26px; align-items: center; - background-color: var(--surfaces-bg-02); - border-right: 1px solid var(--border-subtle-alpha-01); + gap: 40px; } .icon-button { - background-color: var(--surfaces-bg-02); width: 100%; - height: 64px; display: flex; align-items: center; justify-content: center; @@ -156,3 +163,23 @@ div.dashboard_container .custom-tooltip { box-shadow: var(--box-shadow-elevation-tooltip-hover); white-space: pre-wrap; } + +.nav-logo-bar { + display: flex; + flex-direction: column; + width: 64px; + padding-top: 40px; + background-color: var(--surfaces-bg-02); + border-right: 1px solid var(--border-subtle-alpha-01); + gap: 40px; +} + +.logo { + display: flex; + justify-content: center; +} + +.logo-img { + width: 32px; + height: 32px; +} diff --git a/vizro-core/tests/unit/vizro/models/_navigation/test_navigation.py b/vizro-core/tests/unit/vizro/models/_navigation/test_navigation.py index 895ae1061..aef5393df 100644 --- a/vizro-core/tests/unit/vizro/models/_navigation/test_navigation.py +++ b/vizro-core/tests/unit/vizro/models/_navigation/test_navigation.py @@ -86,7 +86,7 @@ def test_default_nav_selector(self, pages, request): built_navigation = navigation.build(active_page_id="Page 1") assert_component_equal( built_navigation["nav_bar_outer"], - html.Div(className="hidden", id="nav_bar_outer"), + html.Div(hidden=True, id="nav_bar_outer"), keys_to_strip={"children"}, ) assert_component_equal( From ddd337a850837e6a954565e229c0bc83df40c284 Mon Sep 17 00:00:00 2001 From: huong-li-nguyen Date: Mon, 11 Dec 2023 18:45:36 +0100 Subject: [PATCH 3/9] Fix bug on one of the layouts --- vizro-core/src/vizro/models/_dashboard.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/vizro-core/src/vizro/models/_dashboard.py b/vizro-core/src/vizro/models/_dashboard.py index 2434956d1..a73a6a553 100644 --- a/vizro-core/src/vizro/models/_dashboard.py +++ b/vizro-core/src/vizro/models/_dashboard.py @@ -136,12 +136,11 @@ def _make_page_layout(self, page: Page): right_header = html.Div(children=[page_title, theme_switch], className="right-header") left_header = ( - html.Div(children=left_header_elements, className="left-header") + html.Div(children=left_header_elements, className="left-header", id="left-header") if any(not getattr(element, "hidden", False) for element in left_header_elements) - else None + else html.Div(hidden=True, id="left-header") ) nav_control_elements = [left_header, nav_panel, control_panel] - nav_control_panel = ( html.Div(nav_control_elements, className="nav_control_panel") if any(not getattr(element, "hidden", False) for element in nav_control_elements) From 8286a36dfd6e1efc0ee9b58405468d1a8ad7f6f7 Mon Sep 17 00:00:00 2001 From: huong-li-nguyen Date: Mon, 11 Dec 2023 18:46:02 +0100 Subject: [PATCH 4/9] Add logo and banner for testing --- vizro-core/examples/assets/banner.svg | 8 ++++++++ vizro-core/examples/assets/logo.svg | 3 +++ 2 files changed, 11 insertions(+) create mode 100644 vizro-core/examples/assets/banner.svg create mode 100644 vizro-core/examples/assets/logo.svg diff --git a/vizro-core/examples/assets/banner.svg b/vizro-core/examples/assets/banner.svg new file mode 100644 index 000000000..e55ed4606 --- /dev/null +++ b/vizro-core/examples/assets/banner.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/vizro-core/examples/assets/logo.svg b/vizro-core/examples/assets/logo.svg new file mode 100644 index 000000000..0904b87de --- /dev/null +++ b/vizro-core/examples/assets/logo.svg @@ -0,0 +1,3 @@ + + + From 136ecd03ad0afd47681ef830079ea0decd5d976e Mon Sep 17 00:00:00 2001 From: huong-li-nguyen Date: Mon, 11 Dec 2023 20:20:41 +0100 Subject: [PATCH 5/9] Refactor `_make_page_layout` into sub-functions --- vizro-core/examples/default/app.py | 3 +- vizro-core/src/vizro/models/_dashboard.py | 94 +++++++++++++++-------- 2 files changed, 64 insertions(+), 33 deletions(-) diff --git a/vizro-core/examples/default/app.py b/vizro-core/examples/default/app.py index f8b2e3325..fb5e89937 100644 --- a/vizro-core/examples/default/app.py +++ b/vizro-core/examples/default/app.py @@ -515,6 +515,7 @@ def create_home_page(): dashboard = vm.Dashboard( + title="My Dashboard", pages=[ create_home_page(), create_variable_analysis(), @@ -527,7 +528,7 @@ def create_home_page(): "Analysis": ["Homepage", "Variable Analysis", "Relationship Analysis", "Country Analysis"], "Summary": ["Continent Summary"], }, - nav_selector=vm.NavBar(), + # nav_selector=vm.NavBar(), ), ) diff --git a/vizro-core/src/vizro/models/_dashboard.py b/vizro-core/src/vizro/models/_dashboard.py index a73a6a553..70cdd1d20 100644 --- a/vizro-core/src/vizro/models/_dashboard.py +++ b/vizro-core/src/vizro/models/_dashboard.py @@ -2,7 +2,7 @@ import logging from functools import partial -from typing import TYPE_CHECKING, List, Literal, Optional, cast +from typing import TYPE_CHECKING, List, Literal, Optional, TypedDict, cast import dash import dash_bootstrap_components as dbc @@ -28,6 +28,19 @@ logger = logging.getLogger(__name__) +class PageDivs(TypedDict): + """Stores all relevant containers for simplified access when re-arranging containers on page.""" + + logo: html.Div + dashboard_title: html.Div + theme_switch: daq.BooleanSwitch + page_title: html.H2 + nav_bar: html.Div + nav_panel: html.Div + control_panel: html.Div + components: html.Div + + class Dashboard(VizroBaseModel): """Vizro Dashboard to be used within [`Vizro`][vizro._vizro.Vizro.build]. @@ -95,20 +108,19 @@ def build(self): fluid=True, ) - def _make_page_layout(self, page: Page): + def _get_page_divs(self, page: Page) -> PageDivs: # Identical across pages # TODO: Implement proper way of automatically pulling file called logo in assets folder (should support svg, png and it shouldn't matter where it's placed in the assets folder) - # TODO: Implement condition check if image can be found/not found - # TODO: Update paddings/margins to fit all cross-combinations - dashboard_logo = ( - html.Div([html.Img(src=get_asset_url("logo.svg"), className="logo-img")], className="logo", id="logo-outer") + logo = ( + html.Div([html.Img(src=get_asset_url("logo.svg"), className="logo-img")], className="logo", id="logo") + # TODO: Implement condition check if image can be found/not found if True - else html.Div(id="logo-outer", hidden=True) + else html.Div(id="logo", hidden=True) ) dashboard_title = ( html.Div(children=[html.H2(self.title)], id="dashboard-title") if self.title - else html.Div(hidden=True, id="dashboard-title") + else html.Div(id="dashboard-title", hidden=True) ) theme_switch = daq.BooleanSwitch( id="theme_selector", on=self.theme == "vizro_dark", persistence=True, persistence_type="session" @@ -117,44 +129,62 @@ def _make_page_layout(self, page: Page): # Shared across pages but slightly differ in content. These could possibly be done by a clientside # callback instead. page_title = html.H2(children=page.title, id="page_title") - navigation: _NavBuildType = cast(Navigation, self.navigation).build(active_page_id=page.id) - nav_bar = navigation["nav_bar_outer"] - nav_panel = navigation["nav_panel_outer"] + nav_content: _NavBuildType = cast(Navigation, self.navigation).build(active_page_id=page.id) + nav_bar = nav_content["nav_bar_outer"] + nav_panel = nav_content["nav_panel_outer"] # Different across pages page_content: _PageBuildType = page.build() control_panel = page_content["control_panel_outer"] - component_container = page_content["component_container_outer"] - + components = page_content["component_container_outer"] + return { + "logo": logo, + "dashboard_title": dashboard_title, + "theme_switch": theme_switch, + "page_title": page_title, + "nav_bar": nav_bar, + "nav_panel": nav_panel, + "control_panel": control_panel, + "components": components, + } + + def _arrange_left_side(self, page_divs: PageDivs): # Arrangement - left_header_elements = [dashboard_title] - icon_logo_elements = [nav_bar] - if getattr(nav_bar, "hidden", False) is False: - icon_logo_elements.insert(0, dashboard_logo) + left_header_divs = [page_divs["dashboard_title"]] + left_sidebar_divs = [page_divs["nav_bar"]] + + if getattr(page_divs["nav_bar"], "hidden", False) is False: + left_sidebar_divs.insert(0, page_divs["logo"]) else: - left_header_elements.insert(0, dashboard_logo) + left_header_divs.insert(0, page_divs["logo"]) - right_header = html.Div(children=[page_title, theme_switch], className="right-header") left_header = ( - html.Div(children=left_header_elements, className="left-header", id="left-header") - if any(not getattr(element, "hidden", False) for element in left_header_elements) + html.Div(children=left_header_divs, className="left-header", id="left-header") + if any(not getattr(element, "hidden", False) for element in left_header_divs) else html.Div(hidden=True, id="left-header") ) - nav_control_elements = [left_header, nav_panel, control_panel] - nav_control_panel = ( - html.Div(nav_control_elements, className="nav_control_panel") - if any(not getattr(element, "hidden", False) for element in nav_control_elements) + left_main_divs = [left_header, page_divs["nav_panel"], page_divs["control_panel"]] + left_sidebar = ( + html.Div(children=left_sidebar_divs, className="nav-logo-bar") + if any(not getattr(element, "hidden", False) for element in left_sidebar_divs) else None ) - nav_logo_bar = ( - html.Div(children=icon_logo_elements, className="nav-logo-bar") - if any(not getattr(element, "hidden", False) for element in icon_logo_elements) + left_main = ( + html.Div(left_main_divs, className="nav_control_panel") + if any(not getattr(element, "hidden", False) for element in left_main_divs) else None ) - left_side = html.Div(children=[nav_logo_bar, nav_control_panel], className="left_side", id="left_side_outer") - right_side = html.Div( - children=[right_header, component_container], className="right_side", id="right_side_outer" - ) + return html.Div(children=[left_sidebar, left_main], className="left_side", id="left_side_outer") + + def _arrange_right_side(self, page_divs: PageDivs): + right_header = html.Div(children=[page_divs["page_title"], page_divs["theme_switch"]], className="right-header") + right_main = page_divs["components"] + return html.Div(children=[right_header, right_main], className="right_side", id="right_side_outer") + + def _make_page_layout(self, page: Page): + page_divs = self._get_page_divs(page=page) + left_side = self._arrange_left_side(page_divs=page_divs) + right_side = self._arrange_right_side(page_divs=page_divs) return html.Div([left_side, right_side], className="page_container", id="page_container_outer") @staticmethod From 47096bfa3eafd5f98f037a01ab80a7b48130bbad Mon Sep 17 00:00:00 2001 From: huong-li-nguyen Date: Tue, 12 Dec 2023 09:57:28 +0100 Subject: [PATCH 6/9] Add notes and rename --- vizro-core/src/vizro/models/_dashboard.py | 18 ++++++++++-------- vizro-core/src/vizro/static/css/layout.css | 4 ++-- .../tests/unit/vizro/models/test_page.py | 2 +- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/vizro-core/src/vizro/models/_dashboard.py b/vizro-core/src/vizro/models/_dashboard.py index 70cdd1d20..d7e1eff5a 100644 --- a/vizro-core/src/vizro/models/_dashboard.py +++ b/vizro-core/src/vizro/models/_dashboard.py @@ -108,6 +108,7 @@ def build(self): fluid=True, ) + # LN: Better to split up? So it's easier for people to re-arrange and just get the relevant containers def _get_page_divs(self, page: Page) -> PageDivs: # Identical across pages # TODO: Implement proper way of automatically pulling file called logo in assets folder (should support svg, png and it shouldn't matter where it's placed in the assets folder) @@ -148,8 +149,8 @@ def _get_page_divs(self, page: Page) -> PageDivs: "components": components, } + # LN: Shall we split up into _arrange_left_side and _arrange_right_side or just one function for arrangement? def _arrange_left_side(self, page_divs: PageDivs): - # Arrangement left_header_divs = [page_divs["dashboard_title"]] left_sidebar_divs = [page_divs["nav_bar"]] @@ -158,21 +159,22 @@ def _arrange_left_side(self, page_divs: PageDivs): else: left_header_divs.insert(0, page_divs["logo"]) + # LN: Shall we actually just provide the same className and id to the divs to simplify things? left_header = ( html.Div(children=left_header_divs, className="left-header", id="left-header") - if any(not getattr(element, "hidden", False) for element in left_header_divs) + if any(not getattr(div, "hidden", False) for div in left_header_divs) else html.Div(hidden=True, id="left-header") ) left_main_divs = [left_header, page_divs["nav_panel"], page_divs["control_panel"]] left_sidebar = ( - html.Div(children=left_sidebar_divs, className="nav-logo-bar") - if any(not getattr(element, "hidden", False) for element in left_sidebar_divs) - else None + html.Div(children=left_sidebar_divs, className="left-sidebar", id="left-sidebar") + if any(not getattr(div, "hidden", False) for div in left_sidebar_divs) + else html.Div(hidden=True, id="left-sidebar") ) left_main = ( - html.Div(left_main_divs, className="nav_control_panel") - if any(not getattr(element, "hidden", False) for element in left_main_divs) - else None + html.Div(left_main_divs, className="left-main", id="left-main") + if any(not getattr(div, "hidden", False) for div in left_main_divs) + else html.Div(hidden=True, id="left-main") ) return html.Div(children=[left_sidebar, left_main], className="left_side", id="left_side_outer") diff --git a/vizro-core/src/vizro/static/css/layout.css b/vizro-core/src/vizro/static/css/layout.css index 14310995c..dc78c3ff5 100644 --- a/vizro-core/src/vizro/static/css/layout.css +++ b/vizro-core/src/vizro/static/css/layout.css @@ -5,7 +5,7 @@ width: 100vw; } -.nav_control_panel { +.left-main { align-items: flex-start; background: var(--surfaces-bg-02); display: flex; @@ -164,7 +164,7 @@ div.dashboard_container .custom-tooltip { white-space: pre-wrap; } -.nav-logo-bar { +.left-sidebar { display: flex; flex-direction: column; width: 64px; diff --git a/vizro-core/tests/unit/vizro/models/test_page.py b/vizro-core/tests/unit/vizro/models/test_page.py index 3a1e34456..752858a32 100644 --- a/vizro-core/tests/unit/vizro/models/test_page.py +++ b/vizro-core/tests/unit/vizro/models/test_page.py @@ -157,4 +157,4 @@ def test_page_build_left_side_removed(standard_px_chart): page = vm.Page(title="Single Page", components=[vm.Graph(id="scatter_chart", figure=standard_px_chart)]) dashboard = vm.Dashboard(pages=[page]) dashboard.pre_build() - assert "className='nav_control_panel'" not in str(page.build()) + assert "className='left-main'" not in str(page.build()) From 8319070ba05e8353a823caeb8efc3396d7c419f6 Mon Sep 17 00:00:00 2001 From: nadijagraca Date: Wed, 13 Dec 2023 12:56:55 +0100 Subject: [PATCH 7/9] initial implementation of vizro infer_image --- .../{ => images/icons/content}/logo.svg | 0 vizro-core/src/vizro/models/_dashboard.py | 25 +++++++++++++++++-- 2 files changed, 23 insertions(+), 2 deletions(-) rename vizro-core/examples/assets/{ => images/icons/content}/logo.svg (100%) diff --git a/vizro-core/examples/assets/logo.svg b/vizro-core/examples/assets/images/icons/content/logo.svg similarity index 100% rename from vizro-core/examples/assets/logo.svg rename to vizro-core/examples/assets/images/icons/content/logo.svg diff --git a/vizro-core/src/vizro/models/_dashboard.py b/vizro-core/src/vizro/models/_dashboard.py index d7e1eff5a..33eaf6e65 100644 --- a/vizro-core/src/vizro/models/_dashboard.py +++ b/vizro-core/src/vizro/models/_dashboard.py @@ -1,7 +1,9 @@ from __future__ import annotations import logging +import os from functools import partial +from pathlib import Path from typing import TYPE_CHECKING, List, Literal, Optional, TypedDict, cast import dash @@ -112,12 +114,14 @@ def build(self): def _get_page_divs(self, page: Page) -> PageDivs: # Identical across pages # TODO: Implement proper way of automatically pulling file called logo in assets folder (should support svg, png and it shouldn't matter where it's placed in the assets folder) + logo_image = self._infer_logo_image() logo = ( - html.Div([html.Img(src=get_asset_url("logo.svg"), className="logo-img")], className="logo", id="logo") + html.Div([html.Img(src=get_asset_url(logo_image), className="logo-img")], className="logo", id="logo") # TODO: Implement condition check if image can be found/not found - if True + if logo_image else html.Div(id="logo", hidden=True) ) + dashboard_title = ( html.Div(children=[html.H2(self.title)], id="dashboard-title") if self.title @@ -210,3 +214,20 @@ def _make_page_404_layout(): ], className="page_error_container", ) + + def _infer_logo_image(self): + valid_extensions = [".jpg", ".png", ".svg"] + files_in_assets = [] + assets_folder = "../assets" + if os.path.exists(assets_folder): + files_in_assets = [ + path.name for path in Path(assets_folder).glob("**/*") if path.suffix in valid_extensions + ] + + logo_file = None + for fn in files_in_assets: + fn_without_extension, _, _ = fn.partition(".") + if fn_without_extension == "logo": + logo_file = fn + + return logo_file From f06125ec9fd76bfe4bb53aa36c7b82640c5219e4 Mon Sep 17 00:00:00 2001 From: Antony Milne Date: Wed, 13 Dec 2023 16:34:32 +0000 Subject: [PATCH 8/9] Update infer_logo_image --- vizro-core/src/vizro/models/_dashboard.py | 25 ++++++++--------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/vizro-core/src/vizro/models/_dashboard.py b/vizro-core/src/vizro/models/_dashboard.py index 33eaf6e65..d68f80f7f 100644 --- a/vizro-core/src/vizro/models/_dashboard.py +++ b/vizro-core/src/vizro/models/_dashboard.py @@ -114,7 +114,7 @@ def build(self): def _get_page_divs(self, page: Page) -> PageDivs: # Identical across pages # TODO: Implement proper way of automatically pulling file called logo in assets folder (should support svg, png and it shouldn't matter where it's placed in the assets folder) - logo_image = self._infer_logo_image() + logo_image = self._infer_logo_image() # images/icons/content/logo.svg logo = ( html.Div([html.Img(src=get_asset_url(logo_image), className="logo-img")], className="logo", id="logo") # TODO: Implement condition check if image can be found/not found @@ -216,18 +216,11 @@ def _make_page_404_layout(): ) def _infer_logo_image(self): - valid_extensions = [".jpg", ".png", ".svg"] - files_in_assets = [] - assets_folder = "../assets" - if os.path.exists(assets_folder): - files_in_assets = [ - path.name for path in Path(assets_folder).glob("**/*") if path.suffix in valid_extensions - ] - - logo_file = None - for fn in files_in_assets: - fn_without_extension, _, _ = fn.partition(".") - if fn_without_extension == "logo": - logo_file = fn - - return logo_file + valid_extensions = [".apng", ".avif", ".gif", ".jpeg", ".jpg", ".png", ".svg", ".webp"] + assets_folder = Path("../assets") # CONFIG.assets_folder? + + if assets_folder.is_dir() + for path in Path(assets_folder).rglob("logo.*"): + if path.suffix in valid_extensions: + return path.relative_to(assets_folder) + # return None \ No newline at end of file From a2c2b6dc32d5147843788f250e3dbff603920fd4 Mon Sep 17 00:00:00 2001 From: nadijagraca Date: Mon, 18 Dec 2023 10:41:46 +0100 Subject: [PATCH 9/9] fixing assets folder implementation --- vizro-core/src/vizro/models/_dashboard.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/vizro-core/src/vizro/models/_dashboard.py b/vizro-core/src/vizro/models/_dashboard.py index d68f80f7f..60fc56e9f 100644 --- a/vizro-core/src/vizro/models/_dashboard.py +++ b/vizro-core/src/vizro/models/_dashboard.py @@ -114,7 +114,7 @@ def build(self): def _get_page_divs(self, page: Page) -> PageDivs: # Identical across pages # TODO: Implement proper way of automatically pulling file called logo in assets folder (should support svg, png and it shouldn't matter where it's placed in the assets folder) - logo_image = self._infer_logo_image() # images/icons/content/logo.svg + logo_image = self._infer_image(basename="logo") logo = ( html.Div([html.Img(src=get_asset_url(logo_image), className="logo-img")], className="logo", id="logo") # TODO: Implement condition check if image can be found/not found @@ -215,12 +215,11 @@ def _make_page_404_layout(): className="page_error_container", ) - def _infer_logo_image(self): + def _infer_image(self, basename: str): valid_extensions = [".apng", ".avif", ".gif", ".jpeg", ".jpg", ".png", ".svg", ".webp"] - assets_folder = Path("../assets") # CONFIG.assets_folder? + assets_folder = Path(dash.get_app().config.assets_folder) - if assets_folder.is_dir() - for path in Path(assets_folder).rglob("logo.*"): + if assets_folder.is_dir(): + for path in Path(assets_folder).rglob(f"{basename}.*"): if path.suffix in valid_extensions: - return path.relative_to(assets_folder) - # return None \ No newline at end of file + return str(path.relative_to(assets_folder)) \ No newline at end of file