From 7930e6bdb382e1c6246fd6fbe3850af739fb2b6f Mon Sep 17 00:00:00 2001 From: huong-li-nguyen Date: Tue, 26 Mar 2024 10:39:28 +0100 Subject: [PATCH 1/6] Fix misalignment of floating filter --- vizro-core/examples/_dev/app.py | 184 ++------------------- vizro-core/src/vizro/static/css/aggrid.css | 12 +- 2 files changed, 29 insertions(+), 167 deletions(-) diff --git a/vizro-core/examples/_dev/app.py b/vizro-core/examples/_dev/app.py index ce40c6a99..3e4ad5dfc 100644 --- a/vizro-core/examples/_dev/app.py +++ b/vizro-core/examples/_dev/app.py @@ -1,181 +1,33 @@ """Example to show dashboard configuration.""" -import datetime -import random -from typing import List, Literal, Optional, Union - -import pandas as pd import vizro.models as vm import vizro.plotly.express as px -from dash import dcc, html from vizro import Vizro -from vizro.models.types import MultiValueType, OptionsType, SingleValueType - -try: - from pydantic.v1 import Field, PrivateAttr -except ImportError: - from pydantic import Field, PrivateAttr -from vizro.models import Action -from vizro.models._action._actions_chain import _action_validator_factory -from vizro.models._base import VizroBaseModel, _log_call - -vm.Page.add_type("components", vm.DatePicker) - -date_data_frame = pd.DataFrame( - { - "value": [random.randint(0, 5) for _ in range(31)], - "time": [datetime.datetime(2024, 1, 1) + datetime.timedelta(days=i) for i in range(31)], - "type": [random.choice(["A", "B", "C"]) for _ in range(31)], - } -) +from vizro.tables import dash_ag_grid -numerical_selectors = [ - vm.RangeSlider(id="numerical_range_slider"), - vm.Slider(id="numerical_slider"), - vm.Dropdown(id="numerical_dropdown"), - vm.RadioItems(id="numerical_radio_items"), - vm.Checklist(id="numerical_checklist"), - # vm.DatePicker(id="numerical_date_picker") # -> doesn't work properly with numerical column_type - # because it's impossible to compare "number" with "date" -] - -temporal_selectors = [ - # vm.RangeSlider(id="temporal_range_slider"), # -> dcc.RangeSlider doesn't work with temporal data - # vm.Slider(id="temporal_slider"), # -> dcc.Slider doesn't work with temporal data - vm.Dropdown(id="temporal_dropdown"), - vm.RadioItems(id="temporal_radio_items"), - vm.Checklist(id="temporal_checklist"), - vm.DatePicker(id="temporal_date_picker"), -] - -categorical_selectors = [ - # vm.RangeSlider(id="categorical_range_slider"), # -> dcc.RangeSlider doesn't work with categorical data - # vm.Slider(id="categorical_slider"), # -> dcc.Slider doesn't work with categorical data - vm.Dropdown(id="categorical_dropdown"), - vm.RadioItems(id="categorical_radio_items"), - vm.Checklist(id="categorical_checklist"), - # vm.DatePicker(id="categorical_date_picker") # -> dmc.DatePicker doesn't work with categorical data -] +df = px.data.gapminder(datetimes=True) page = vm.Page( - title="My first page", - components=[ - vm.Graph(figure=px.line(date_data_frame, x="time", y="value")), - vm.DatePicker(min="2024-01-01", max="2026-01-01", range=False), - ], - controls=[ - # *[vm.Filter(column="value", selector=selector) for selector in numerical_selectors], - # *[vm.Filter(column="time", selector=selector) for selector in temporal_selectors], - # *[vm.Filter(column="type", selector=selector) for selector in categorical_selectors], - vm.Filter(column="type"), - vm.Filter(column="value"), - vm.Filter(column="time"), - ], -) - -df_stocks_long = pd.melt( - px.data.stocks(datetimes=True), - id_vars="date", - value_vars=["GOOG", "AAPL", "AMZN", "FB", "NFLX", "MSFT"], - var_name="stocks", - value_name="value", -) - -df_stocks_long["value"] = df_stocks_long["value"].round(3) - -page_2 = vm.Page( - title="My second page", + title="Enhanced AG Grid", components=[ - vm.Graph(figure=px.line(df_stocks_long, x="date", y="value", color="stocks")), - ], - controls=[ - vm.Filter(column="stocks"), - vm.Filter(column="value"), - vm.Filter(column="date"), - ], -) - - -# CUSTOM SELECTORS - - -class NewDropdown(VizroBaseModel): - """Categorical single/multi-selector `Dropdown` to be provided to `Filter`.""" - - type: Literal["new-dropdown"] = "new-dropdown" - options: Optional[OptionsType] = Field(None, description="Possible options the user can select from") - value: Optional[Union[SingleValueType, MultiValueType]] = Field( - None, description="Options that are selected by default" - ) - multi: bool = Field(True, description="Whether to allow selection of multiple values") - actions: List[Action] = [] # noqa: RUF012 - title: Optional[str] = Field(None, description="Title to be displayed") - - # Component properties for actions and interactions - _input_property: str = PrivateAttr("value") - - set_actions = _action_validator_factory("value") - - @_log_call - def build(self): - """Custom build method.""" - return html.Div( - [ - html.P(self.title) if self.title else None, - dcc.Dropdown( - id=self.id, - options=self.options, - value=self.value or self.options[0], - multi=self.multi, - persistence=True, - clearable=False, - ), - ], - className="input-container", - ) - - -class RangeSliderNonCross(vm.RangeSlider): - """Custom numeric multi-selector `RangeSliderNonCross` to be provided to `Filter`.""" - - type: Literal["range_slider_non_cross"] = "range_slider_non_cross" - - def build(self): - """Custom build method.""" - range_slider_build_obj = super().build() - range_slider_build_obj[self.id].allowCross = False - return range_slider_build_obj - - -# Important: Add new components to expected type - here the selector of the parent components -vm.Filter.add_type("selector", NewDropdown) -vm.Parameter.add_type("selector", NewDropdown) - - -# Important: Add new components to expected type - here the selector of the parent components -vm.Filter.add_type("selector", RangeSliderNonCross) -vm.Parameter.add_type("selector", RangeSliderNonCross) - - -page_3 = vm.Page( - title="Custom filer selectors", - components=[ - vm.Graph(figure=px.line(date_data_frame, x="time", y="value")), - ], - controls=[ - vm.Filter(column="type", selector=NewDropdown(options=["A", "B", "C"])), - vm.Filter(column="value", selector=NewDropdown(options=[1, 2, 3, 4, 5])), - vm.Filter( - column="time", - selector=NewDropdown( - options=[datetime.datetime(2024, 1, 1) + datetime.timedelta(days=i) for i in range(31)] - ), + vm.AgGrid( + title="Dash AG Grid", + figure=dash_ag_grid( + data_frame=df, + columnDefs=[ + {"field" : "country", 'floatingFilter': True}, + {"field" : "continent", 'floatingFilter': True}, + {"field" : "year"}, + {"field" : "lifeExp", "cellDataType": "numeric"}, + {"field" : "pop", "cellDataType": "numeric"}, + {"field" : "gdpPercap", "cellDataType": "euro"},] + + ) ), - vm.Filter(column="value", selector=RangeSliderNonCross(id="new_range_slider")), ], + controls=[vm.Filter(column="continent")], ) - -dashboard = vm.Dashboard(pages=[page, page_2, page_3]) +dashboard = vm.Dashboard(pages=[page]) if __name__ == "__main__": Vizro().build(dashboard).run() diff --git a/vizro-core/src/vizro/static/css/aggrid.css b/vizro-core/src/vizro/static/css/aggrid.css index 3647eb673..3c340ae9b 100644 --- a/vizro-core/src/vizro/static/css/aggrid.css +++ b/vizro-core/src/vizro/static/css/aggrid.css @@ -30,13 +30,13 @@ align-items: flex-start; border-bottom: 1px solid var(--border-subtle-alpha-02); display: flex; - padding: var(--spacing-03) 0 0 0; } #page-container .ag-header-cell { align-items: center; display: flex; padding: 0 var(--spacing-03); + height: 40px; } #page-container .ag-header-cell-text { @@ -137,3 +137,13 @@ .ag-theme-quartz-dark.ag-theme-vizro .ag-header-cell-menu-button { --ag-quartz-icon-hover-color: transparent; } + + +/* Floating Filter */ +#page-container .ag-floating-filter-input input[class^=ag-][type=text] { + padding-left: 0; +} + +#page-container .ag-floating-filter-input { + outline: none; +} From 937343c73376e713fa8a193e4c33546e2440a332 Mon Sep 17 00:00:00 2001 From: huong-li-nguyen Date: Tue, 26 Mar 2024 10:58:35 +0100 Subject: [PATCH 2/6] Fix jumping and unnecessary border --- vizro-core/src/vizro/static/css/aggrid.css | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/vizro-core/src/vizro/static/css/aggrid.css b/vizro-core/src/vizro/static/css/aggrid.css index 3c340ae9b..32d2bea58 100644 --- a/vizro-core/src/vizro/static/css/aggrid.css +++ b/vizro-core/src/vizro/static/css/aggrid.css @@ -23,6 +23,7 @@ --ag-header-column-resize-handle-width: 1px; --ag-header-column-resize-handle-color: var(--border-subtle-alpha-02); --ag-range-selection-border-color: transparent; + --ag-input-focus-border-color: transparent; } /* Header ------- */ @@ -140,10 +141,15 @@ /* Floating Filter */ +#page-container .ag-floating-filter-input { + height: 40px; + color: var(--text-primary); +} + #page-container .ag-floating-filter-input input[class^=ag-][type=text] { padding-left: 0; } -#page-container .ag-floating-filter-input { - outline: none; +#page-container .ag-cell-focus, .ag-cell { + border: none; } From 67ab0333f83ca3c029853471b9c2fc9156568895 Mon Sep 17 00:00:00 2001 From: huong-li-nguyen Date: Tue, 26 Mar 2024 11:09:37 +0100 Subject: [PATCH 3/6] Remove hover color --- vizro-core/src/vizro/static/css/aggrid.css | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/vizro-core/src/vizro/static/css/aggrid.css b/vizro-core/src/vizro/static/css/aggrid.css index 32d2bea58..0247b016c 100644 --- a/vizro-core/src/vizro/static/css/aggrid.css +++ b/vizro-core/src/vizro/static/css/aggrid.css @@ -135,7 +135,9 @@ } .ag-theme-quartz.ag-theme-vizro .ag-header-cell-menu-button, -.ag-theme-quartz-dark.ag-theme-vizro .ag-header-cell-menu-button { +.ag-theme-quartz-dark.ag-theme-vizro .ag-header-cell-menu-button, +.ag-theme-quartz.ag-theme-vizro .ag-floating-filter-button-button, +.ag-theme-quartz-dark.ag-theme-vizro .ag-floating-filter-button-button { --ag-quartz-icon-hover-color: transparent; } From ca7a747920b0719023b721baeda2057a9df8609b Mon Sep 17 00:00:00 2001 From: huong-li-nguyen Date: Tue, 26 Mar 2024 11:14:42 +0100 Subject: [PATCH 4/6] Lint --- ..._huong_li_nguyen_add_css_floatingfilter.md | 48 +++++++++++++++++++ vizro-core/examples/_dev/app.py | 16 +++---- vizro-core/src/vizro/static/css/aggrid.css | 15 +++--- 3 files changed, 63 insertions(+), 16 deletions(-) create mode 100644 vizro-core/changelog.d/20240326_111333_huong_li_nguyen_add_css_floatingfilter.md diff --git a/vizro-core/changelog.d/20240326_111333_huong_li_nguyen_add_css_floatingfilter.md b/vizro-core/changelog.d/20240326_111333_huong_li_nguyen_add_css_floatingfilter.md new file mode 100644 index 000000000..f1f65e73c --- /dev/null +++ b/vizro-core/changelog.d/20240326_111333_huong_li_nguyen_add_css_floatingfilter.md @@ -0,0 +1,48 @@ + + + + + + + + + diff --git a/vizro-core/examples/_dev/app.py b/vizro-core/examples/_dev/app.py index 3e4ad5dfc..0d852afdc 100644 --- a/vizro-core/examples/_dev/app.py +++ b/vizro-core/examples/_dev/app.py @@ -15,14 +15,14 @@ figure=dash_ag_grid( data_frame=df, columnDefs=[ - {"field" : "country", 'floatingFilter': True}, - {"field" : "continent", 'floatingFilter': True}, - {"field" : "year"}, - {"field" : "lifeExp", "cellDataType": "numeric"}, - {"field" : "pop", "cellDataType": "numeric"}, - {"field" : "gdpPercap", "cellDataType": "euro"},] - - ) + {"field": "country", "floatingFilter": True}, + {"field": "continent", "floatingFilter": True}, + {"field": "year"}, + {"field": "lifeExp", "cellDataType": "numeric"}, + {"field": "pop", "cellDataType": "numeric"}, + {"field": "gdpPercap", "cellDataType": "euro"}, + ], + ), ), ], controls=[vm.Filter(column="continent")], diff --git a/vizro-core/src/vizro/static/css/aggrid.css b/vizro-core/src/vizro/static/css/aggrid.css index 0247b016c..3bec7dcc0 100644 --- a/vizro-core/src/vizro/static/css/aggrid.css +++ b/vizro-core/src/vizro/static/css/aggrid.css @@ -36,8 +36,8 @@ #page-container .ag-header-cell { align-items: center; display: flex; - padding: 0 var(--spacing-03); height: 40px; + padding: 0 var(--spacing-03); } #page-container .ag-header-cell-text { @@ -58,6 +58,10 @@ padding: 0 var(--spacing-03); } +#page-container .ag-cell-focus { + border: none; +} + #page-container .ag-cell-focus:not(.ag-cell-range-selected):focus-within { background: var(--state-overlays-selected); } @@ -141,17 +145,12 @@ --ag-quartz-icon-hover-color: transparent; } - /* Floating Filter */ #page-container .ag-floating-filter-input { - height: 40px; color: var(--text-primary); + height: 40px; } -#page-container .ag-floating-filter-input input[class^=ag-][type=text] { +#page-container .ag-floating-filter-input input[class^="ag-"][type="text"] { padding-left: 0; } - -#page-container .ag-cell-focus, .ag-cell { - border: none; -} From 250d66cff366934a7f171c2b69878ffee9797b5a Mon Sep 17 00:00:00 2001 From: huong-li-nguyen Date: Tue, 26 Mar 2024 11:59:46 +0100 Subject: [PATCH 5/6] Tidy --- vizro-core/examples/_dev/app.py | 6 +++--- vizro-core/src/vizro/tables/_dash_ag_grid.py | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/vizro-core/examples/_dev/app.py b/vizro-core/examples/_dev/app.py index 0d852afdc..11f21e685 100644 --- a/vizro-core/examples/_dev/app.py +++ b/vizro-core/examples/_dev/app.py @@ -5,7 +5,7 @@ from vizro import Vizro from vizro.tables import dash_ag_grid -df = px.data.gapminder(datetimes=True) +df = px.data.gapminder() page = vm.Page( title="Enhanced AG Grid", @@ -15,8 +15,8 @@ figure=dash_ag_grid( data_frame=df, columnDefs=[ - {"field": "country", "floatingFilter": True}, - {"field": "continent", "floatingFilter": True}, + {"field": "country", "floatingFilter": True, "suppressHeaderMenuButton": True}, + {"field": "continent", "floatingFilter": True, "suppressHeaderMenuButton": True}, {"field": "year"}, {"field": "lifeExp", "cellDataType": "numeric"}, {"field": "pop", "cellDataType": "numeric"}, diff --git a/vizro-core/src/vizro/tables/_dash_ag_grid.py b/vizro-core/src/vizro/tables/_dash_ag_grid.py index 762fe8f6c..b81de5de9 100644 --- a/vizro-core/src/vizro/tables/_dash_ag_grid.py +++ b/vizro-core/src/vizro/tables/_dash_ag_grid.py @@ -60,7 +60,6 @@ def dash_ag_grid(data_frame: pd.DataFrame, **kwargs) -> dag.AgGrid: ) ).to_dict("records"), "defaultColDef": { - # "editable": True, #do not set, as this may confuse some users "resizable": True, "sortable": True, "filter": True, From 9c7b233e18fbe53758847a921e8ae0d82bd065ce Mon Sep 17 00:00:00 2001 From: huong-li-nguyen Date: Tue, 26 Mar 2024 13:41:27 +0100 Subject: [PATCH 6/6] Update 20240326_111333_huong_li_nguyen_add_css_floatingfilter.md --- ...20240326_111333_huong_li_nguyen_add_css_floatingfilter.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/vizro-core/changelog.d/20240326_111333_huong_li_nguyen_add_css_floatingfilter.md b/vizro-core/changelog.d/20240326_111333_huong_li_nguyen_add_css_floatingfilter.md index f1f65e73c..99f2e607a 100644 --- a/vizro-core/changelog.d/20240326_111333_huong_li_nguyen_add_css_floatingfilter.md +++ b/vizro-core/changelog.d/20240326_111333_huong_li_nguyen_add_css_floatingfilter.md @@ -34,12 +34,11 @@ Uncomment the section that is right (remove the HTML comment wrapper). - 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)) --> -