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

[Feat] Create vizro.figures.library to enable usage in pure Dash app #578

Merged
merged 67 commits into from
Aug 19, 2024
Merged
Show file tree
Hide file tree
Changes from 59 commits
Commits
Show all changes
67 commits
Select commit Hold shift + click to select a range
9800ea6
Add undecorated module
huong-li-nguyen Jul 10, 2024
eacdc68
Add pure Dash example
huong-li-nguyen Jul 10, 2024
c99c5bb
Add pure Dash app
huong-li-nguyen Jul 10, 2024
facdf65
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 10, 2024
6ab16e3
Add raw links
huong-li-nguyen Jul 10, 2024
0d3f64c
Merge branch 'tidy/create-module-pure-functions' of https://github.co…
huong-li-nguyen Jul 10, 2024
a6a361c
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 10, 2024
3d43142
Add local overwrites to test
huong-li-nguyen Jul 10, 2024
336bae7
Merge branch 'tidy/create-module-pure-functions' of https://github.co…
huong-li-nguyen Jul 15, 2024
83ce390
Merge branch 'main' into tidy/create-module-pure-functions
huong-li-nguyen Jul 15, 2024
9d22ec8
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 15, 2024
6ca3c4a
Merge branch 'main' into tidy/create-module-pure-functions
huong-li-nguyen Jul 22, 2024
ce42185
Implement alternative way for API-docs
huong-li-nguyen Jul 22, 2024
768d890
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 22, 2024
82ad717
Rename to unwrapped
huong-li-nguyen Jul 22, 2024
60d27f0
Remove custom CSS to check
huong-li-nguyen Jul 22, 2024
636adcf
Tidy
huong-li-nguyen Jul 22, 2024
74bda51
Merge branch 'tidy/create-module-pure-functions' of https://github.co…
huong-li-nguyen Jul 22, 2024
2b2e7b4
Identify changes needed in BS
huong-li-nguyen Jul 22, 2024
616202f
Bundle CSS files
huong-li-nguyen Jul 22, 2024
ffa0734
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 22, 2024
060b6c4
Add changes
huong-li-nguyen Jul 22, 2024
2b0e6e7
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 22, 2024
883939e
Add changes
huong-li-nguyen Jul 22, 2024
cb22b42
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 22, 2024
427bc3f
Remove google stylesheet from external_stylesheets
huong-li-nguyen Jul 22, 2024
db58467
Merge branch 'tidy/create-module-pure-functions' of https://github.co…
huong-li-nguyen Jul 22, 2024
a218b6f
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 22, 2024
e011c70
Add figures.css to _css_dist nicely
antonymilne Jul 22, 2024
ec51fdf
Update vizro-core/src/vizro/static/css/figures.css
antonymilne Jul 22, 2024
87cf0db
Oops
antonymilne Jul 22, 2024
4c260c1
Update __version__ for this branch
antonymilne Jul 22, 2024
d82ee46
Update bootstrap theme
huong-li-nguyen Jul 23, 2024
514e293
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 23, 2024
6e0102a
Double-check other themes
huong-li-nguyen Jul 23, 2024
ded2e95
Merge branch 'tidy/create-module-pure-functions' of https://github.co…
huong-li-nguyen Jul 23, 2024
beb7e27
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 23, 2024
4868d79
Update bootstrap theme
huong-li-nguyen Jul 25, 2024
4f14f66
Test Bootstrap changes
huong-li-nguyen Jul 25, 2024
f9b6a93
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 25, 2024
9a5ab0b
Add CSS changes
huong-li-nguyen Jul 25, 2024
9286074
Lint
huong-li-nguyen Jul 25, 2024
5ff6e71
Merge branch 'tidy/create-module-pure-functions' of https://github.co…
huong-li-nguyen Jul 25, 2024
c834ed5
Lint
huong-li-nguyen Jul 25, 2024
05c4081
* Rename to vizro.figures.library
antonymilne Aug 2, 2024
d312343
Tidy
antonymilne Aug 2, 2024
9c3c082
Merge branch 'main' into tidy/create-module-pure-functions
huong-li-nguyen Aug 7, 2024
79ce6ff
Merge branch 'main' into tidy/create-module-pure-functions
huong-li-nguyen Aug 13, 2024
e839bc4
Store fonts locally
huong-li-nguyen Aug 13, 2024
193302c
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 13, 2024
c0c5cec
Merge branch 'main' into tidy/create-module-pure-functions
antonymilne Aug 15, 2024
65248c8
Try something out
antonymilne Aug 15, 2024
a3f0826
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 15, 2024
ed66f4b
Aaargh
antonymilne Aug 15, 2024
02817d7
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 15, 2024
db8312f
Add comments
antonymilne Aug 15, 2024
94b704f
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 15, 2024
fbd84ac
Update changelog
antonymilne Aug 15, 2024
b98f9a0
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 15, 2024
9d4c67c
Fix tests
huong-li-nguyen Aug 16, 2024
437b200
Merge branch 'main' into tidy/create-module-pure-functions
huong-li-nguyen Aug 16, 2024
4a405fc
Fix tests and lint
huong-li-nguyen Aug 16, 2024
a96f189
Delete roboto-mono font
huong-li-nguyen Aug 16, 2024
d9d2237
Remove redundant comments
huong-li-nguyen Aug 16, 2024
50dc617
Merge branch 'main' into tidy/create-module-pure-functions
huong-li-nguyen Aug 19, 2024
f38e6e3
Merge branch 'main' into tidy/create-module-pure-functions
huong-li-nguyen Aug 19, 2024
641c182
Final changes
huong-li-nguyen Aug 19, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<!--
A new scriv changelog fragment.

Uncomment the section that is right (remove the HTML comment wrapper).
-->

<!--
### Highlights ✨

- A bullet item for the Highlights ✨ category with a link to the relevant PR at the end of your entry, e.g. Enable feature XXX ([#1](https://github.com/mckinsey/vizro/pull/1))

-->
<!--
### Removed

- A bullet item for the Removed category with a link to the relevant PR at the end of your entry, e.g. Enable feature XXX ([#1](https://github.com/mckinsey/vizro/pull/1))

-->

### Added

- Create `vizro.figures.library` to contain KPI card Dash components that can be used outside the Vizro framework. ([#578](https://github.com/mckinsey/vizro/pull/578))

### Changed

- Google Material icons library is served locally to enable offline functionality. ([#578](https://github.com/mckinsey/vizro/pull/578))

<!--
### Deprecated

- A bullet item for the Deprecated category with a link to the relevant PR at the end of your entry, e.g. Enable feature XXX ([#1](https://github.com/mckinsey/vizro/pull/1))

-->
<!--
### Fixed

- A bullet item for the Fixed category with a link to the relevant PR at the end of your entry, e.g. Enable feature XXX ([#1](https://github.com/mckinsey/vizro/pull/1))

-->
<!--
### Security

- A bullet item for the Security category with a link to the relevant PR at the end of your entry, e.g. Enable feature XXX ([#1](https://github.com/mckinsey/vizro/pull/1))

-->
5 changes: 5 additions & 0 deletions vizro-core/docs/pages/API-reference/figure-callables.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@
API reference for all pre-defined [`CapturedCallable`][vizro.models.types.CapturedCallable] figure functions to be used in the
[`Figure`][vizro.models.Figure]. The [how-to guide on figures](../user-guides/figure.md) contains more information.

Identical functions can also be used outside the Vizro framework in a pure Dash app by importing from the `vizro.figures.library` namespace:
```python
from vizro.figures.library import kpi_card, kpi_card_reference
```
huong-li-nguyen marked this conversation as resolved.
Show resolved Hide resolved

::: vizro.figures
options:
show_source: true
Expand Down
5 changes: 5 additions & 0 deletions vizro-core/examples/dev/assets/css/custom.css
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,8 @@
height: 210px;
width: 240px;
}

/* Overriding still works:
.card {
background: pink;
} */
166 changes: 59 additions & 107 deletions vizro-core/examples/scratch_dev/app.py
Original file line number Diff line number Diff line change
@@ -1,114 +1,66 @@
"""Dev app to try things out."""

import vizro.models as vm
import vizro.plotly.express as px
from vizro import Vizro
from vizro.figures import kpi_card
from vizro.models.types import capture
from vizro.tables import dash_ag_grid, dash_data_table

df = px.data.iris()


# Graph
@capture("graph")
def my_graph_figure(data_frame, **kwargs):
"""My custom figure."""
return px.scatter(data_frame, **kwargs)


class MyGraph(vm.Graph):
"""My custom class."""

def build(self):
"""Custom build."""
graph_build_obj = super().build()
# DO SOMETHING
return graph_build_obj


# Table
@capture("table")
def my_table_figure(data_frame, **kwargs):
"""My custom figure."""
return dash_data_table(data_frame, **kwargs)()


class MyTable(vm.Table):
"""My custom class."""

pass


# AgGrid
@capture("ag_grid")
def my_ag_grid_figure(data_frame, **kwargs):
"""My custom figure."""
return dash_ag_grid(data_frame, **kwargs)()


class MyAgGrid(vm.AgGrid):
"""My custom class."""

pass


# Figure
@capture("figure")
def my_kpi_card_figure(data_frame, **kwargs):
"""My custom figure."""
return kpi_card(data_frame, **kwargs)()


class MyFigure(vm.Figure):
"""My custom class."""

pass


# Action
@capture("action")
def my_action_function():
"""My custom action."""
pass


class MyAction(vm.Action):
"""My custom class."""

pass

import dash_bootstrap_components as dbc
import pandas as pd
from dash import Dash, html
from vizro.figures.library import kpi_card, kpi_card_reference

df_kpi = pd.DataFrame({"Actual": [100, 200, 700], "Reference": [100, 300, 500], "Category": ["A", "B", "C"]})

# Add single CSS file figures.css or
base = "https://cdn.jsdelivr.net/gh/mckinsey/vizro@tidy/create-module-pure-functions/vizro-core/src/vizro/static/css/"
vizro_bootstrap = base + "vizro-bootstrap.min.css"

# Add entire assets folder from Vizro
app = Dash(
external_stylesheets=[
vizro_bootstrap
# dbc.themes.SANDSTONE
]
)

page = vm.Page(
title="Test",
layout=vm.Layout(
grid=[[0, 1], [2, 3], [4, 5], [6, 7], [8, -1]],
col_gap="50px",
row_gap="50px",
),
components=[
# Graph
MyGraph(figure=px.scatter(df, x="sepal_width", y="sepal_length", title="My Graph")),
MyGraph(figure=my_graph_figure(df, x="sepal_width", y="sepal_length", title="My Graph Custom Figure")),
# Table
MyTable(figure=dash_data_table(df), title="My Table"),
MyTable(figure=my_table_figure(df), title="My Table Custom Figure"),
# AgGrid
MyAgGrid(figure=dash_ag_grid(df), title="My AgGrid"),
MyAgGrid(figure=my_ag_grid_figure(df), title="My AgGrid Custom Figure"),
# Figure
MyFigure(figure=kpi_card(df, value_column="sepal_width", title="KPI Card")),
MyFigure(figure=my_kpi_card_figure(df, value_column="sepal_width", title="KPI Card Custom Figure")),
# Action
MyGraph(
figure=my_graph_figure(df, x="sepal_width", y="sepal_length", title="My Graph Custom Figure"),
actions=[MyAction(function=my_action_function())],
app.layout = dbc.Container(
[
html.H1(children="Title of Dash App"),
html.Div(
children=[
dbc.Row(
[
dbc.Col(
kpi_card(
data_frame=df_kpi,
value_column="Actual",
value_format="${value:.2f}",
icon="shopping_cart",
title="KPI Card I",
)
),
dbc.Col(
kpi_card_reference(
data_frame=df_kpi,
value_column="Actual",
reference_column="Reference",
icon="payment",
title="KPI Card II",
)
),
dbc.Col(
kpi_card_reference(
data_frame=df_kpi,
value_column="Reference",
reference_column="Actual",
icon="payment",
title="KPI Card III",
)
),
]
),
],
# Note: They need to add vizro_light here
className="vizro_light",
),
],
controls=[vm.Filter(column="species")],
]
)

dashboard = vm.Dashboard(pages=[page])

if __name__ == "__main__":
Vizro().build(dashboard).run()
app.run(debug=True, use_reloader=True)
2 changes: 2 additions & 0 deletions vizro-core/examples/scratch_dev/assets/css/custom.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#page-header {
padding-left: 8px;
}

/* All of these changes are only temporarily here as changes from figures.css are not automatically read in */

This file was deleted.

43 changes: 42 additions & 1 deletion vizro-core/src/vizro/__init__.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,51 @@
import logging
import os

from dash.development.base_component import Component

from ._vizro import Vizro

logging.basicConfig(level=os.getenv("VIZRO_LOG_LEVEL", "WARNING"))

__all__ = ["Vizro"]

__version__ = "0.1.20.dev0"
huong-li-nguyen marked this conversation as resolved.
Show resolved Hide resolved

logging.basicConfig(level=os.getenv("VIZRO_LOG_LEVEL", "WARNING"))

# For the below _css_dist to be used by Dash, it must be retrieved by dash.resources.Css.get_all_css(). This means it
# must be added to dash.development.base_component.ComponentRegistry. The simplest way to do this is to run
# ComponentRegistry.registry.add("vizro") and this appears to be sufficient for our needs, but it is not documented
# anywhere. The same function is run (together with some others which we probably don't need) when subclassing
# Component, thanks to the metaclass ComponentMeta. So we define a dummy component to go through this safer route,
# even though we don't need the component for anything. _css_dist is automatically served on import of vizro, regardless
# of whether the Vizro class or any other bits are used.
class _Dummy(Component):
pass
petar-qb marked this conversation as resolved.
Show resolved Hide resolved


# For dev versions, a branch or tag called e.g. 0.1.20.dev0 does not exist and so won't work with the CDN. We point
# to main instead, but this can be manually overridden to the current feature branch name if required.
# _git_branch = __version__ if "dev" not in __version__ else "main"
_git_branch = "tidy/create-module-pure-functions"
huong-li-nguyen marked this conversation as resolved.
Show resolved Hide resolved
_library_css = ["static/css/figures"]
_base_external_url = f"https://cdn.jsdelivr.net/gh/mckinsey/vizro@{_git_branch}/vizro-core/src/vizro/"

_css_dist = [
huong-li-nguyen marked this conversation as resolved.
Show resolved Hide resolved
{
"namespace": "vizro",
"relative_package_path": f"{css_file}.css",
"external_url": f"{_base_external_url}{css_file}.min.css",
}
for css_file in _library_css
]

# Include font file so that figures with icons can be used outside Vizro as pure Dash components.
huong-li-nguyen marked this conversation as resolved.
Show resolved Hide resolved
# The file can be served through the CDN in the same way as the CSS files but external_url is irrelevant here. The way
# the file is requested is through a relative url("./fonts/...") in the requesting CSS file. When the CSS file is
# served from the CDN then this will refer to the font file also on the CDN.
_css_dist.append(
{
"namespace": "vizro",
"relative_package_path": "static/css/fonts/material-symbols-outlined.woff2",
}
)
13 changes: 7 additions & 6 deletions vizro-core/src/vizro/_vizro.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,18 @@ def __init__(self, **kwargs):

"""
self.dash = dash.Dash(**kwargs, use_pages=True, pages_folder="", title="Vizro")
self.dash.config.external_stylesheets.extend(
[
"https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined",
]
)

# Include Vizro assets (in the static folder) as external scripts and stylesheets. We extend self.dash.config
# objects so the user can specify additional external_scripts and external_stylesheets via kwargs.
vizro_assets_folder = Path(__file__).with_name("static")
requests_pathname_prefix = self.dash.config.requests_pathname_prefix
vizro_css = [requests_pathname_prefix + path for path in self._get_external_assets(vizro_assets_folder, "css")]
# Exclude vizro/css/figures.css since these are distributed through the vizro._css_dist mechanism.
# In future we will probably handle all assets this way and none of this code will be required.
vizro_css = [
requests_pathname_prefix + path
for path in self._get_external_assets(vizro_assets_folder, "css")
if path != "vizro/css/figures.css"
]

# Ensure vizro-bootstrap.min.css is loaded in first to allow overwrites
vizro_css.sort(key=lambda x: not x.endswith("vizro-bootstrap.min.css"))
Expand Down
2 changes: 1 addition & 1 deletion vizro-core/src/vizro/figures/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from vizro.figures.kpi_cards import kpi_card, kpi_card_reference
from vizro.figures._kpi_cards import kpi_card, kpi_card_reference

# Please keep alphabetically ordered
__all__ = ["kpi_card", "kpi_card_reference"]
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,12 @@ def kpi_card( # noqa: PLR0913
title = title or f"{agg_func} {value_column}".title()
value = data_frame[value_column].agg(agg_func)

header = dbc.CardHeader([html.P(icon, className="material-symbols-outlined") if icon else None, html.H2(title)])
header = dbc.CardHeader(
[
html.P(icon, className="material-symbols-outlined") if icon else None,
html.H4(title, className="card-kpi-title"),
]
)
body = dbc.CardBody(value_format.format(value=value))
return dbc.Card([header, body], className="card-kpi")

Expand Down Expand Up @@ -137,7 +142,12 @@ def kpi_card_reference( # noqa: PLR0913
delta = value - reference
delta_relative = delta / reference if reference else np.nan

header = dbc.CardHeader([html.P(icon, className="material-symbols-outlined") if icon else None, html.H2(title)])
header = dbc.CardHeader(
[
html.P(icon, className="material-symbols-outlined") if icon else None,
html.H4(title, className="card-kpi-title"),
huong-li-nguyen marked this conversation as resolved.
Show resolved Hide resolved
]
)
body = dbc.CardBody(
value_format.format(value=value, reference=reference, delta=delta, delta_relative=delta_relative)
)
Expand Down
8 changes: 8 additions & 0 deletions vizro-core/src/vizro/figures/library.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
"""Contains unwrapped KPI card functions (suitable to use in pure Dash app)."""

from vizro.figures import kpi_card, kpi_card_reference

kpi_card = kpi_card.__wrapped__
kpi_card_reference = kpi_card_reference.__wrapped__

__all__ = ["kpi_card", "kpi_card_reference"]
9 changes: 0 additions & 9 deletions vizro-core/src/vizro/static/css/bootstrap_overwrites.css
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,3 @@ but do not want to take over to `vizro-bootstrap` as these settings might not be
.accordion-item .nav-link.active {
border-left: 2px solid var(--border-enabled);
}

.card-header,
.card-footer,
.card-body {
background: inherit;
border: none;
margin: 0;
padding: 0;
}
Loading
Loading