File size: 4,053 Bytes
487a9ac
42ee455
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b07f575
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
"""App configuration for dashboard."""

from typing import List, Union

import vizro.models as vm
from chart_groups import ALL_CHART_GROUP, CHART_GROUPS, ChartGroup, IncompletePage
from custom_components import FlexContainer, Markdown
from vizro import Vizro


def make_chart_card(page: Union[vm.Page, IncompletePage]) -> vm.Card:
    """Makes a card with svg icon, linked to the right page if page is complete.

    Args:
        page: page to make card for

    Returns: card with svg icon, linked to the right page if page is complete.

    """
    # There's one SVG per chart title, so that e.g. pages distribution-butterfly and deviation-butterfly, which both
    # have title "Butterfly", correspond to butterfly.svg.
    # Incomplete pages have page.path = "" so won't be linked to here.
    svg_name = page.title.lower().replace(" ", "-")
    return vm.Card(
        text=f"""
           ![](assets/images/charts/{svg_name}.svg#chart-icon)

           #### {page.title}
           """,
        href=page.path,
    )


def make_homepage_container(chart_group: ChartGroup) -> vm.Container:
    """Makes a container with cards for each completed and incomplete chart in chart_group.

    Args:
        chart_group: group of charts to make container for.

    Returns: container with cards for each chart in chart_group.

    """
    # Pages are sorted in title's alphabetical order and deduplicated so that e.g. pages distribution-butterfly and
    # deviation-butterfly, which both have title "Butterfly", correspond to a single card.
    return vm.Container(
        title=chart_group.name,
        layout=vm.Layout(grid=[[0, 1, 1]], col_gap="40px"),
        components=[
            Markdown(text=chart_group.intro_text, classname="intro-text"),
            FlexContainer(
                components=[
                    make_chart_card(page)
                    for page in sorted(
                        _remove_duplicates(chart_group.pages + chart_group.incomplete_pages),
                        key=lambda page: page.title,
                    )
                ],
            ),
        ],
    )


def _remove_duplicates(pages: List[Union[vm.Page, IncompletePage]]) -> List[Union[vm.Page, IncompletePage]]:
    # Deduplicate pages that have the same title. Using reversed means that the page that is kept is the first one
    # in the dashboard. This will be the one that the card on the homepage links to.
    return list({page.title: page for page in reversed(pages)}.values())


def make_navlink(chart_group: ChartGroup) -> vm.NavLink:
    """Makes a navlink with icon and links to every complete page within chart_group.

    Args:
        chart_group: chart_group to make a navlink for.

    Returns: navlink for chart_group.

    """
    # Pages are sorted in alphabetical order within each chart group.
    return vm.NavLink(
        label=chart_group.name,
        pages={chart_group.name: [page.id for page in sorted(chart_group.pages, key=lambda page: page.title)]},
        icon=chart_group.icon,
    )


homepage = vm.Page(
    title="Overview",
    components=[
        vm.Tabs(tabs=[make_homepage_container(chart_group) for chart_group in [ALL_CHART_GROUP, *CHART_GROUPS]]),
    ],
)

# TODO: consider whether each chart group should have its own individual homepage,
# e.g. at http://localhost:8050/deviation/. This could just repeat the content of the tab from the homepage and would
# work nicely with the hierarchical navigation.
dashboard = vm.Dashboard(
    # ALL_CHART_GROUP.pages has duplicated pages, e.g. both distribution-butterfly and deviation-butterfly.
    title="Vizro - Visual Vocabulary",
    pages=[homepage, *ALL_CHART_GROUP.pages],
    navigation=vm.Navigation(
        nav_selector=vm.NavBar(
            items=[
                vm.NavLink(label="Overview", pages=[homepage.id], icon="Home"),
            ]
            + [make_navlink(chart_group) for chart_group in CHART_GROUPS]
        )
    ),
)

app = Vizro().build(dashboard)
server = app.dash.server

if __name__ == "__main__":  
    app.run()