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

[Bug] Fix bug that prevented custom tables/grids with column referral #439

Merged
merged 22 commits into from
May 12, 2024
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
3d2403b
Adressing bug and adding tests
maxschulz-COL Apr 26, 2024
747837a
Fix remaining unit tests
maxschulz-COL Apr 26, 2024
425c773
Linting
maxschulz-COL Apr 26, 2024
e8c4ace
CHangelog
maxschulz-COL Apr 26, 2024
794eed8
Merge branch 'main' into bug/missing_DF_435
maxschulz-COL Apr 26, 2024
a18d2cc
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Apr 26, 2024
df41457
Merge branch 'main' into bug/missing_DF_435
maxschulz-COL May 2, 2024
a3bf131
Different example
maxschulz-COL May 2, 2024
4c39246
TBR Removing DF breaks filter persistence on page change
maxschulz-COL May 2, 2024
7d4e6c9
Revert "TBR Removing DF breaks filter persistence on page change"
maxschulz-COL May 2, 2024
a35f6c7
Final comments and linting
maxschulz-COL May 2, 2024
2143987
Merge branch 'main' into bug/missing_DF_435
maxschulz-COL May 7, 2024
b5fadca
Merge branch 'main' into bug/missing_DF_435
maxschulz-COL May 7, 2024
be60463
Merge main
maxschulz-COL May 10, 2024
30c75dd
Merge branch 'bug/missing_DF_435' of github.com:mckinsey/vizro into b…
maxschulz-COL May 10, 2024
1bdd2c1
Fix tests after changes in main
maxschulz-COL May 10, 2024
300ef3f
Change back dev example
maxschulz-COL May 10, 2024
5a531cb
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 10, 2024
2f1a92b
Revert "Change back dev example"
maxschulz-COL May 11, 2024
b30dd5a
Merge origin
maxschulz-COL May 11, 2024
bccea7e
Fix non running integration tests by adding if clause
maxschulz-COL May 11, 2024
542fe78
Linting
maxschulz-COL May 12, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<!--
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

- A bullet item for the Added 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))

-->
<!--
### Changed

- A bullet item for the Changed 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))

-->
<!--
### 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

- Fix bug that [prevented referring to columns in custom grids/tables](https://github.com/mckinsey/vizro/issues/435) ([#439](https://github.com/mckinsey/vizro/pull/439))

<!--
### 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))

-->
177 changes: 57 additions & 120 deletions vizro-core/examples/_dev/app.py
Original file line number Diff line number Diff line change
@@ -1,137 +1,74 @@
"""Rough example used by developers."""

from typing import Literal
"""To try out the PR."""

import pandas as pd
import vizro.models as vm
import vizro.plotly.express as px
from vizro import Vizro
from vizro.models._components.form._text_area import TextArea
from vizro.models._components.form._user_input import UserInput

iris = px.data.iris()

from vizro.tables import dash_ag_grid

class CustomInput(UserInput):
"""Custom Input that allows passing `className` as an argument."""

type: Literal["other_input"] = "other_input"
class_name: str = "form-control"

def build(self):
"""Build the component."""
input_build_obj = super().build()
input_build_obj[self.id].className = self.class_name
return input_build_obj
# DATA
data = {
"this_is_a_really_long_column_name_0": [
"sdfjalskdfnaksnfa;sldknfalksdnfl;kasdnfl;kasndflkasdf",
"sdfjalskdfnaksnfa;sldknfalksdnfl;kasdnfl;kasndflkasdf",
"sdfjalskdfnaksnfa;sldknfalksdnfl;kasdnfl;kasndflkasdf",
],
"short_col_name": [4, 5, 6],
"this_is_a_really_long_column_name_2": [
"sdfjalskdfnaksnfa;sldknfalksdnfl;kasdnfl;kasndflkasdf",
"sdfjalskdfnaksnfa;sldknfalksdnfl;kasdnfl;kasndflkasdf",
"sdfjalskdfnaksnfa;sldknfalksdnfl;kasdnfl;kasndflkasdf",
],
"short": [10, 11, 12],
"this_is_a_really_long_column_name_4": [
"sdfjalskdfnaksnfa;sldknfalksdnfl;kasdnfl;kasndflkasdf",
"sdfjalskdfnaksnfa;sldknfalksdnfl;kasdnfl;kasndflkasdf",
"sdfjalskdfnaksnfa;sldknfalksdnfl;kasdnfl;kasndflkasdf",
],
"this_is_a_really_long_column_name_6": [
"sdfjalskdfnaksnfa;sldknfalksdnfl;kasdnfl;kasndflkasdf",
"sdfjalskdfnaksnfa;sldknfalksdnfl;kasdnfl;kasndflkasdf",
"sdfjalskdfnaksnfa;sldknfalksdnfl;kasdnfl;kasndflkasdf",
],
"short4": [10, 11, 12],
"this_is_a_really_long_column_name_7": [13, 14, 15],
}

df = pd.DataFrame(data)

# Only added to container.components directly for dev example
vm.Page.add_type("controls", UserInput)
vm.Page.add_type("controls", TextArea)
vm.Container.add_type("components", vm.Dropdown)
vm.Container.add_type("components", vm.Checklist)
vm.Container.add_type("components", vm.RadioItems)
vm.Container.add_type("components", vm.Slider)
vm.Container.add_type("components", vm.RangeSlider)
vm.Container.add_type("components", TextArea)
vm.Container.add_type("components", UserInput)
vm.Container.add_type("components", CustomInput)
# df = px.data.gapminder()

selectors = vm.Page(
title="Selectors - Controls",
page = vm.Page(
title="Example of a Dash AG Grid",
components=[
vm.Graph(
id="scatter_relation",
figure=px.scatter(data_frame=px.data.gapminder(), x="gdpPercap", y="lifeExp", size="pop"),
),
vm.Card(
text="""
# This is an <h1> tag
## This is an <h2> tag
###### This is an <h6> tag
\n
>
> Block quotes are used to highlight text.
>
\n
* Item 1
* Item 2
\n
*This text will be italic*
_This will also be italic_
**This text will be bold**
_You **can** combine them_
""",
vm.AgGrid(
title="Dash AG Grid",
figure=dash_ag_grid(
id="grid1",
data_frame=px.data.gapminder(),
defaultColDef={"flex": 1, "minWidth": 200},
persistence=True,
persisted_props=["filterModel", "columnSize"], # ,persistence_type = "local" #columnSize="autoSize"#
),
),
],
controls=[
vm.Filter(
column="continent",
selector=vm.Dropdown(title="Dropdown Label"),
),
vm.Filter(
column="year",
selector=vm.RangeSlider(title="Range Slider Label", step=1, marks=None),
),
vm.Filter(
column="year",
selector=vm.Slider(title="Slider Label"),
),
vm.Filter(
column="year",
selector=vm.RangeSlider(title="Range Slider Label", step=10),
),
vm.Filter(
column="year",
selector=vm.Slider(title="Slider Label", step=10),
),
vm.Filter(
column="continent",
selector=vm.Checklist(title="Checklist Label"),
),
vm.Filter(
column="continent",
selector=vm.RadioItems(title="Radio Items Label"),
),
UserInput(title="Input - Text (single-line)", placeholder="Enter text here"),
TextArea(title="Input - Text (multi-line)", placeholder="Enter multi-line text here"),
],
# controls=[vm.Filter(column="this_is_a_really_long_column_name_0")],
)

form_components = vm.Page(
title="Selectors - Components",
page2 = vm.Page(
title="Example of a Dash AG Grid 2",
components=[
vm.Container(
id="container-id",
title="Form",
components=[
UserInput(title="Input - Text (single-line)", placeholder="Enter text here"),
CustomInput(
title="Input - Text (single-line)",
placeholder="Enter text here",
class_name="form-control is-valid",
),
CustomInput(
title="Input - Text (single-line)",
placeholder="Enter text here",
class_name="form-control is-invalid",
),
TextArea(title="Input - Text (multi-line)", placeholder="Enter multi-line text here"),
vm.Dropdown(title="Dropdown - Single", options=["Option 1", "Option 2", "Option 3"], multi=False),
vm.Dropdown(title="Dropdown - Multi", options=["Option 1", "Option 2", "Option 3"], multi=True),
vm.Checklist(title="Checklist", options=["Option 1", "Option 2", "Option 3"]),
vm.RadioItems(title="Radio Items", options=["Option 1", "Option 2", "Option 3"]),
vm.Slider(title="Slider without marks", min=0, max=10),
vm.Slider(title="Slider with marks", min=0, max=10, step=1),
vm.RangeSlider(title="Range Slider without marks", min=0, max=10),
vm.RangeSlider(title="Range Slider with marks", min=0, max=10, step=1),
vm.Button(),
],
vm.AgGrid(
title="Dash AG Grid 2",
figure=dash_ag_grid(
id="grid2",
data_frame=px.data.gapminder(),
columnSize="autoSize", # persistence=True, persisted_props=["filterModel","columnSize"],
# persistence_type = "local"
),
),
],
# controls=[vm.Filter(column="continent")],
)
dashboard = vm.Dashboard(pages=[page, page2])


dashboard = vm.Dashboard(pages=[selectors, form_components])

if __name__ == "__main__":
Vizro().build(dashboard).run()
Vizro().build(dashboard).run()
4 changes: 3 additions & 1 deletion vizro-core/src/vizro/models/_components/ag_grid.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,10 @@ def build(self):
# The pagination setting (and potentially others) of the initially built AgGrid (in the build method
# here) must have the same setting as the object that is built by the on-page-load mechanism using
# with the user settings and rendered finally. Otherwise the grid is not rendered correctly.
# Additionally, we cannot remove the DF from the ag grid object before returning it (to save sending
# data over the network), because it breaks filter persistence settings on page change.
# Hence be careful when editing the line below.
html.Div(self.__call__(data_frame=pd.DataFrame()), id=self.id, className="table-container"),
html.Div(self.__call__(), id=self.id, className="table-container"),
maxschulz-COL marked this conversation as resolved.
Show resolved Hide resolved
],
id=f"{self.id}_outer",
color="grey",
Expand Down
5 changes: 4 additions & 1 deletion vizro-core/src/vizro/models/_components/table.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,10 @@ def build(self):
html.Div(
[
html.H3(self.title, className="table-title") if self.title else None,
html.Div(self.__call__(data_frame=pd.DataFrame()), id=self.id),
# Please see vm.AgGrid build method as to why we are returning the call with the full data here
# Most of the comments may not apply to the data table, but in order to be consistent, we are
# handling the build method in the exact same way here
html.Div(self.__call__(), id=self.id),
maxschulz-COL marked this conversation as resolved.
Show resolved Hide resolved
],
className="table-container",
id=f"{self.id}_outer",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
"""Unit tests for vizro.models.AgGrid."""

import pandas as pd
import pytest
from asserts import assert_component_equal
from dash import dcc, html
Expand Down Expand Up @@ -117,15 +116,15 @@ def test_pre_build_actions_underlying_ag_grid_id(self, ag_grid_with_id, filter_i


class TestBuildAgGrid:
def test_ag_grid_build_mandatory_only(self, standard_ag_grid):
def test_ag_grid_build_mandatory_only(self, standard_ag_grid, gapminder):
ag_grid = vm.AgGrid(id="text_ag_grid", figure=standard_ag_grid)
ag_grid.pre_build()
ag_grid = ag_grid.build()
expected_ag_grid = dcc.Loading(
[
None,
html.Div(
dash_ag_grid(data_frame=pd.DataFrame(), id="__input_text_ag_grid")(),
dash_ag_grid(data_frame=gapminder, id="__input_text_ag_grid")(),
id="text_ag_grid",
className="table-container",
),
Expand All @@ -137,7 +136,7 @@ def test_ag_grid_build_mandatory_only(self, standard_ag_grid):

assert_component_equal(ag_grid, expected_ag_grid)

def test_ag_grid_build_with_underlying_id(self, ag_grid_with_id_and_conf, filter_interaction_action):
def test_ag_grid_build_with_underlying_id(self, ag_grid_with_id_and_conf, filter_interaction_action, gapminder):
ag_grid = vm.AgGrid(id="text_ag_grid", figure=ag_grid_with_id_and_conf, actions=[filter_interaction_action])
ag_grid.pre_build()
ag_grid = ag_grid.build()
Expand All @@ -147,7 +146,7 @@ def test_ag_grid_build_with_underlying_id(self, ag_grid_with_id_and_conf, filter
None,
html.Div(
dash_ag_grid(
data_frame=pd.DataFrame(), id="underlying_ag_grid_id", dashGridOptions={"pagination": True}
data_frame=gapminder, id="underlying_ag_grid_id", dashGridOptions={"pagination": True}
)(),
id="text_ag_grid",
className="table-container",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
"""Unit tests for vizro.models.Table."""

import pandas as pd
import pytest
from asserts import assert_component_equal
from dash import dcc, html
Expand Down Expand Up @@ -118,15 +117,15 @@ def test_pre_build_actions_underlying_table_id(self, dash_data_table_with_id, fi


class TestBuildTable:
def test_table_build_mandatory_only(self, standard_dash_table):
def test_table_build_mandatory_only(self, standard_dash_table, gapminder):
table = vm.Table(id="text_table", figure=standard_dash_table)
table.pre_build()
table = table.build()
expected_table = dcc.Loading(
html.Div(
[
None,
html.Div(dash_data_table(id="__input_text_table", data_frame=pd.DataFrame())(), id="text_table"),
html.Div(dash_data_table(id="__input_text_table", data_frame=gapminder)(), id="text_table"),
],
className="table-container",
id="text_table_outer",
Expand All @@ -137,7 +136,7 @@ def test_table_build_mandatory_only(self, standard_dash_table):

assert_component_equal(table, expected_table)

def test_table_build_with_underlying_id(self, dash_data_table_with_id, filter_interaction_action):
def test_table_build_with_underlying_id(self, dash_data_table_with_id, filter_interaction_action, gapminder):
table = vm.Table(id="text_table", figure=dash_data_table_with_id, actions=[filter_interaction_action])
table.pre_build()
table = table.build()
Expand All @@ -146,7 +145,7 @@ def test_table_build_with_underlying_id(self, dash_data_table_with_id, filter_in
html.Div(
[
None,
html.Div(dash_data_table(id="underlying_table_id", data_frame=pd.DataFrame())(), id="text_table"),
html.Div(dash_data_table(id="underlying_table_id", data_frame=gapminder)(), id="text_table"),
],
className="table-container",
id="text_table_outer",
Expand Down