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] Add Figure model and introduce KPI card functions #493

Merged
merged 79 commits into from
Jun 18, 2024
Merged
Changes from 1 commit
Commits
Show all changes
79 commits
Select commit Hold shift + click to select a range
fb37101
Add KPI Card based on Plotly indicator
huong-li-nguyen May 21, 2024
9428969
Add KPI Card based on custom component
huong-li-nguyen May 21, 2024
c2c3710
Refine and leave some comments
huong-li-nguyen May 21, 2024
dbba0dd
Get dynamic Card working quickly
huong-li-nguyen May 21, 2024
a3ca6f6
Add logic to enable `text_card` and `nav_card`
huong-li-nguyen May 22, 2024
521954a
Tidy
huong-li-nguyen May 22, 2024
1081cd2
Lint
huong-li-nguyen May 22, 2024
4ceeed8
Add partially styled KPI
huong-li-nguyen May 22, 2024
1ca2be2
Simplify dynamic styled card
huong-li-nguyen May 22, 2024
bba9e01
Tidy
huong-li-nguyen May 22, 2024
e1a2858
Add styling to mkd card
huong-li-nguyen May 22, 2024
8309d9f
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 22, 2024
7edfec2
Add another KPI style
huong-li-nguyen May 22, 2024
c65678e
Merge branch 'feat/create_kpi_cards' of https://github.com/mckinsey/v…
huong-li-nguyen May 22, 2024
798d8ef
Lint
huong-li-nguyen May 22, 2024
c01a3db
Add comments
huong-li-nguyen May 23, 2024
6062063
Tidy CSS
huong-li-nguyen May 23, 2024
67d41aa
Make sample page with 3 pre-selected designs
huong-li-nguyen May 23, 2024
6eedfe7
Move `dbc.Card` to `build` and remove id provision
huong-li-nguyen May 30, 2024
f3b1d6a
Refactor classNames for `kpi_card_icon`
huong-li-nguyen May 30, 2024
feaf493
Refactor simple and icon KPI card to one
huong-li-nguyen May 30, 2024
466b252
Refactor classNames for `kpi_card_ref`
huong-li-nguyen May 30, 2024
35f64aa
Refactor and tidy some more
huong-li-nguyen May 30, 2024
284f2ba
Add formatting arguments to function for discussion
huong-li-nguyen May 30, 2024
eb2c9c6
Enable coloring of higher-level card
huong-li-nguyen May 30, 2024
456eb29
Improve naming
huong-li-nguyen May 30, 2024
3f87ac9
Remove remaining `kpi-card-icon` reference
huong-li-nguyen May 30, 2024
67321aa
Tidy app
huong-li-nguyen May 30, 2024
3aab16b
Merge branch 'main' into feat/create_kpi_cards
huong-li-nguyen May 30, 2024
289ada3
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 30, 2024
9f37512
Merge branch 'main' into feat/create_kpi_cards
huong-li-nguyen Jun 4, 2024
1c7eb6e
Update docstrings
huong-li-nguyen Jun 4, 2024
1554541
Return `dbc.Card` inside `CapturedCallable`
huong-li-nguyen Jun 5, 2024
98b8c1e
Replace `kpi_card` with suggested improvement
huong-li-nguyen Jun 5, 2024
26ce1be
Replace `kpi_card_ref` with suggested
huong-li-nguyen Jun 5, 2024
3ef65f2
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jun 5, 2024
a1b1228
Remove redundant code from previous iterations
huong-li-nguyen Jun 5, 2024
4309315
Lint
huong-li-nguyen Jun 5, 2024
90dfcb3
Merge branch 'feat/create_kpi_cards' of https://github.com/mckinsey/v…
huong-li-nguyen Jun 5, 2024
faabc46
Commit this
huong-li-nguyen Jun 5, 2024
6bf46d5
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jun 5, 2024
b005f51
Revert changes in card
huong-li-nguyen Jun 5, 2024
e964bb6
Create higher-level `Figure` model
huong-li-nguyen Jun 5, 2024
5c31faf
Merge branch 'feat/create_kpi_cards' of https://github.com/mckinsey/v…
huong-li-nguyen Jun 5, 2024
7161d15
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jun 5, 2024
2a92af6
Revert unwanted changes
huong-li-nguyen Jun 5, 2024
ae3e57b
Tidy
huong-li-nguyen Jun 5, 2024
d0bce82
Fix renaming
huong-li-nguyen Jun 5, 2024
ac56dba
Merge branch 'main' into feat/create_kpi_cards
huong-li-nguyen Jun 5, 2024
b6515ff
Tidy CSS
huong-li-nguyen Jun 5, 2024
bed23b4
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jun 5, 2024
4c6969f
Merge branch 'main' into feat/create_kpi_cards
huong-li-nguyen Jun 6, 2024
acccea1
Add docstrings to kpi card functions
huong-li-nguyen Jun 6, 2024
a344db5
Merge branch 'main' into feat/create_kpi_cards
huong-li-nguyen Jun 6, 2024
72343be
Implement reverse-color coding via CSS
huong-li-nguyen Jun 7, 2024
c5c7368
Update schema
huong-li-nguyen Jun 7, 2024
8062991
Add changelog
huong-li-nguyen Jun 7, 2024
fda4a5e
Add ignore for custom format warning
huong-li-nguyen Jun 7, 2024
de649ee
Tidy redundant TODOs
huong-li-nguyen Jun 7, 2024
ec4a45b
Add unit tests for `Figure`
huong-li-nguyen Jun 7, 2024
95ebf91
Add empty doc file for now
huong-li-nguyen Jun 7, 2024
6f5b33d
Revert changes in `vizro-ai`
huong-li-nguyen Jun 7, 2024
4c71bdc
Add relevant updates in docs
huong-li-nguyen Jun 7, 2024
104b99c
Fix doc warning for now
huong-li-nguyen Jun 7, 2024
9d53cbb
Update schema
huong-li-nguyen Jun 7, 2024
f0d0304
Update components.md
stichbury Jun 7, 2024
8883285
Change icon and apply lowercase
huong-li-nguyen Jun 7, 2024
0e5fa7d
Merge branch 'feat/create_kpi_cards' of https://github.com/mckinsey/v…
huong-li-nguyen Jun 7, 2024
f07e7d1
Incorporate PR comments
huong-li-nguyen Jun 11, 2024
09ceea1
Fix height due to added container
huong-li-nguyen Jun 11, 2024
5fbfe84
Replace output with function call
huong-li-nguyen Jun 12, 2024
db8ac58
Add constants for defaults and tidy html divs
huong-li-nguyen Jun 12, 2024
41c4ca5
Handle ZeroDivisonError
huong-li-nguyen Jun 12, 2024
782127c
Simplify docstrings for `getitem` and remove TODO
huong-li-nguyen Jun 12, 2024
cea7a61
Add more context to docstrings of kpi card functions
huong-li-nguyen Jun 12, 2024
36c6a4f
Merge branch 'main' into feat/create_kpi_cards
huong-li-nguyen Jun 17, 2024
68cf51e
Change container className
huong-li-nguyen Jun 17, 2024
769a314
Merge branch 'main' into feat/create_kpi_cards
huong-li-nguyen Jun 18, 2024
ee606f8
Incorporate last PR comments
huong-li-nguyen Jun 18, 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
Prev Previous commit
Next Next commit
Get dynamic Card working quickly
huong-li-nguyen committed May 21, 2024
commit dbba0ddd1d7b076726ef557e6c4cf540a252cfb2
11 changes: 4 additions & 7 deletions vizro-core/examples/_dev/app.py
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@
from dash import html
from vizro import Vizro
from vizro.models.types import capture

from vizro.cards import kpi_card
iris_df = px.data.iris()

# Open questions -------
@@ -74,7 +74,7 @@ def build(self):

page = vm.Page(
title="Table Page",
layout=vm.Layout(grid=[[0, 1]] + [[-1, -1]] * 3),
layout=vm.Layout(grid=[[0, 1, 2]] + [[-1, -1, -1]] * 3),
components=[
vm.Graph(
id="kpi-total",
@@ -85,12 +85,9 @@ def build(self):
),
),
CustomKPI(
title="Total Complaints",
value="75.513",
icon="arrow_circle_up",
sign="up",
ref_value="5.5% vs. Last Year"
title="Total Complaints", value="75.513", icon="arrow_circle_up", sign="up", ref_value="5.5% vs. Last Year"
),
vm.Card(figure=kpi_card(iris_df, value="sepal_width", title="Sepal Width AVG")),
],
controls=[vm.Filter(column="species")],
)
2 changes: 1 addition & 1 deletion vizro-core/examples/_dev/assets/css/custom.css
Original file line number Diff line number Diff line change
@@ -17,8 +17,8 @@
}

.card .card-title {
height: 100%;
font-size: 1.4rem;
height: 100%;
}

.card .card-value {
4 changes: 4 additions & 0 deletions vizro-core/src/vizro/cards/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from vizro.cards._cards import kpi_card, nav_card, text_card

# Please keep alphabetically ordered
__all__ = ["text_card", "nav_card", "kpi_card"]
42 changes: 42 additions & 0 deletions vizro-core/src/vizro/cards/_cards.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
"""Module containing the standard implementation of `dash_table.DataTable`."""

import dash_bootstrap_components as dbc
import pandas as pd
from dash import dash_table, dcc, get_relative_path, html

from vizro.models.types import capture

# A few issues:
# The data frame is not used in the function, but needs to be provided here
# id is usually attached to Card.text


@capture("card")
def text_card(data_frame: pd.DataFrame, text: str) -> dash_table.DataTable:
"""Static text card."""
return dbc.Card(dcc.Markdown(text, dangerously_allow_html=False)) # id should be given to text component


@capture("card")
def nav_card(data_frame: pd.DataFrame, text: str, href: str) -> dash_table.DataTable:
"""Static text card."""
return dbc.Card(
dbc.NavLink(
dcc.Markdown(text, dangerously_allow_html=False),
href=get_relative_path(href) if href.startswith("/") else href,
),
className="card-nav",
)


@capture("card")
def kpi_card(data_frame: pd.DataFrame, title: str, value: str) -> dash_table.DataTable:
"""Static text card."""
value = data_frame[value].sum()

return dbc.Card(
[
html.H4(title, className="card-title"),
html.P(value, className="card-value"),
],
)
46 changes: 29 additions & 17 deletions vizro-core/src/vizro/models/_components/card.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
from typing import Literal

import dash_bootstrap_components as dbc
from dash import dcc, get_relative_path
from dash import dcc, html

try:
from pydantic.v1 import Field
from pydantic.v1 import Field, PrivateAttr, validator
except ImportError: # pragma: no cov
from pydantic import Field
from pydantic import Field, PrivateAttr, validator

import vizro.cards as vc
from vizro.managers import data_manager
from vizro.models import VizroBaseModel
from vizro.models._components._components_utils import _callable_mode_validator_factory, _process_callable_data_frame
from vizro.models._models_utils import _log_call
from vizro.models.types import CapturedCallable


class Card(VizroBaseModel):
@@ -24,25 +27,34 @@ class Card(VizroBaseModel):
"""

type: Literal["card"] = "card"
figure: CapturedCallable = Field(..., import_path=vc, description="Dynamic Card to be visualized on dashboard")
text: str = Field(
..., description="Markdown string to create card title/text that should adhere to the CommonMark Spec."
"", description="Markdown string to create card title/text that should adhere to the CommonMark Spec."
)
href: str = Field(
"",
description="URL (relative or absolute) to navigate to. If not provided the Card serves as a text card only.",
)

# Component properties for actions and interactions
_output_component_property: str = PrivateAttr("children")

# Validators
_validate_callable_mode = _callable_mode_validator_factory("card")
_validate_callable = validator("figure", allow_reuse=True, always=True)(_process_callable_data_frame)

def __call__(self, **kwargs):
kwargs.setdefault("data_frame", data_manager[self["data_frame"]].load())
figure = self.figure(**kwargs)
return figure

def __getitem__(self, arg_name: str):
# pydantic discriminated union validation seems to try Graph["type"], which throws an error unless we
# explicitly redirect it to the correct attribute.
if arg_name == "type":
return self.type
return self.figure[arg_name]

@_log_call
def build(self):
text = dcc.Markdown(self.text, dangerously_allow_html=False, id=self.id)
card_content = (
dbc.NavLink(
text,
href=get_relative_path(self.href) if self.href.startswith("/") else self.href,
)
if self.href
else text
)

card_class = "card-nav" if self.href else ""
return dbc.Card(card_content, className=card_class)
return dcc.Loading(html.Div(self.__call__(), id=self.id), color="grey", parent_className="loading-container")
4 changes: 2 additions & 2 deletions vizro-core/src/vizro/models/types.py
Original file line number Diff line number Diff line change
@@ -248,7 +248,7 @@ class capture:

"""

def __init__(self, mode: Literal["graph", "action", "table", "ag_grid"]):
def __init__(self, mode: Literal["graph", "action", "table", "ag_grid", "card"]):
"""Decorator to capture a function call. Valid modes are "graph", "table", "action" and "ag_grid"."""
self._mode = mode

@@ -304,7 +304,7 @@ def wrapped(*args, **kwargs):
return captured_callable

return wrapped
elif self._mode in ["table", "ag_grid"]:
elif self._mode in ["table", "ag_grid", "card"]:

@functools.wraps(func)
def wrapped(*args, **kwargs):