BI-dashboard / tables.py
antonymilne's picture
Tidy and a couple of new features (#2)
4cfea5b verified
"""AG Grid table configurations for the Superstore BI dashboard."""
from dash_ag_grid import AgGrid
from data_processing import make_customer_sales_pareto_df
from vizro.models.types import capture
from vizro.tables import dash_ag_grid
# TODO: check and refactor
CELL_STYLE_PRODUCT = {
"styleConditions": [
{
"condition": "params.value < -0.5",
"style": {"backgroundColor": "#e33b3b"},
},
{
"condition": "params.value >= -0.5 && params.value <= 0",
"style": {"backgroundColor": "#f19791"},
},
{
"condition": "params.value > 0 && params.value <= 0.30",
"style": {"backgroundColor": "#728aff"},
},
{
"condition": "params.value > 0.30",
"style": {"backgroundColor": "#2251ff"},
},
]
}
COLUMN_DEFS_PRODUCT = [
{"field": "Sub-Category", "cellDataType": "text", "headerName": "Sub-Category", "flex": 3},
{
"field": "Profit",
"cellDataType": "number",
"flex": 2,
"valueFormatter": {"function": "d3.format('$,.2f')(params.value)"},
},
{
"field": "Sales",
"cellDataType": "number",
"flex": 2,
"valueFormatter": {"function": "d3.format('$,.2f')(params.value)"},
},
{
"field": "Profit Margin",
"flex": 2,
"cellDataType": "number",
"valueFormatter": {"function": "d3.format('.0%')(params.value)"},
"cellStyle": CELL_STYLE_PRODUCT,
},
]
@capture("ag_grid")
def orders_ag_grid(data_frame):
"""Create custom AG Grid table for orders with conditional formatting.
Args:
data_frame: Source dataframe containing order data.
Returns:
AgGrid: Configured AG Grid component with custom column definitions and styling.
"""
data_frame["Profit Ratio"] = (data_frame["Profit"] / data_frame["Sales"]).round(3)
column_defs_orders = [
{"headerName": "Order ID", "field": "Order ID", "minWidth": 150},
{"headerName": "Status", "field": "Order Status", "minWidth": 150, "cellRenderer": "statusCellRenderer"},
{
"headerName": "Segment",
"field": "Segment",
"minWidth": 140,
},
{"headerName": "Customer", "field": "Customer Name", "minWidth": 170},
{"headerName": "State", "field": "State", "minWidth": 150},
{"headerName": "City", "field": "City", "minWidth": 150},
{"headerName": "Category", "field": "Category", "minWidth": 150},
{"headerName": "Sub-Category", "field": "Sub-Category", "minWidth": 150},
{"headerName": "Sales", "field": "Sales", "valueFormatter": {"function": "d3.format('$,.2f')(params.value)"}},
{
"headerName": "Profit",
"field": "Profit",
"valueFormatter": {"function": "d3.format('$,.2f')(params.value)"},
},
{
"headerName": "Profit Ratio",
"field": "Profit Ratio",
"minWidth": 140,
"valueFormatter": {"function": "d3.format('.1%')(params.value)"},
"cellStyle": {
"styleConditions": [
{
"condition": "Number(params.value) < -0.5",
"style": {
"backgroundColor": "#e33b3b",
"color": "white",
"borderRadius": "18px",
"padding": "4px",
"fontWeight": "600",
"justifyContent": "center",
"alignItems": "center",
"display": "flex",
"marginTop": "8px",
"height": "30px",
},
},
{
"condition": "Number(params.value) >= -0.5 && Number(params.value) < 0",
"style": {
"backgroundColor": "#f19791",
"color": "white",
"borderRadius": "18px",
"padding": "4px",
"fontWeight": "600",
"justifyContent": "center",
"alignItems": "center",
"display": "flex",
"marginTop": "8px",
"height": "30px",
},
},
{
"condition": "Number(params.value) >= 0 && Number(params.value) < 0.30",
"style": {
"backgroundColor": "#728aff",
"color": "white",
"borderRadius": "18px",
"padding": "4px",
"fontWeight": "600",
"justifyContent": "center",
"alignItems": "center",
"display": "flex",
"marginTop": "8px",
"height": "30px",
},
},
{
"condition": "Number(params.value) >= 0.30",
"style": {
"backgroundColor": "#2251ff",
"color": "white",
"borderRadius": "18px",
"padding": "4px",
"fontWeight": "600",
"justifyContent": "center",
"alignItems": "center",
"display": "flex",
"marginTop": "8px",
"height": "30px",
},
},
]
},
},
]
aggrid = AgGrid(
columnDefs=column_defs_orders,
defaultColDef={"resizable": True, "sortable": True, "filter": True, "minWidth": 30, "flex": 1},
style={"height": "800px", "width": "100%"},
rowData=data_frame.to_dict("records"),
dashGridOptions={
"rowHeight": 55,
"animateRows": True,
"suppressMovableColumns": True,
"pagination": True,
"paginationPageSize": 20,
},
dangerously_allow_code=True,
)
return aggrid
@capture("ag_grid")
def customers_ag_grid(data_frame):
data_frame = make_customer_sales_pareto_df(data_frame)
# Convert back to fraction since percentage is handled by cellDataType=percent.
data_frame["Cumulative %"] = data_frame["Cumulative % of Sales"] / 100
return dash_ag_grid(
data_frame,
columnDefs=[
{"field": "Rank", "width": 50},
{"field": "Customer Name"},
{"field": "Sales", "cellDataType": "dollar"},
{"field": "Cumulative %", "cellDataType": "percent", "width": 130},
],
)()