Skip to content

Commit

Permalink
[feat] Utilize new fullscreen Toolbar for st.{map|pydeck_chart} (stre…
Browse files Browse the repository at this point in the history
…amlit#9501)

## Describe your changes

- Utilizes the new fullscreen Toolbar from dataframes for `st.map` and
`st.pydeck_chart`

Dark mode:
<img width="735" alt="Screenshot 2024-09-18 at 3 10 52 PM"
src="https://github.com/user-attachments/assets/b5b5fe07-e6b6-4867-ba74-098a148ea51e">

Light mode:
<img width="739" alt="Screenshot 2024-09-18 at 3 11 03 PM"
src="https://github.com/user-attachments/assets/b54a0c3f-33cb-4a8d-92e1-fc3a96793bfb">

When in fullscreen:
<img width="1507" alt="Screenshot 2024-09-18 at 3 14 56 PM"
src="https://github.com/user-attachments/assets/629aa07e-c07f-41c6-94fd-381065d78ac3">


## GitHub Issue Link (if applicable)

## Testing Plan

- Explanation of why no additional tests are needed
- Unit Tests (JS and/or Python)
- E2E Tests ✅ Added tests + reusable helper function
- Any manual testing needed? ✅ Manually tested

---

**Contribution License Agreement**

By submitting this pull request you agree that all contributions to this
project are made under the Apache 2.0 license.
  • Loading branch information
sfc-gh-bnisco authored Sep 19, 2024
1 parent 810d50b commit 7913ce5
Show file tree
Hide file tree
Showing 14 changed files with 138 additions and 30 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
67 changes: 67 additions & 0 deletions e2e_playwright/shared/toolbar_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# Copyright (c) Streamlit Inc. (2018-2022) Snowflake Inc. (2022-2024)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from __future__ import annotations

from typing import TYPE_CHECKING

from playwright.sync_api import Page, expect

if TYPE_CHECKING:
from e2e_playwright.conftest import ImageCompareFunction


def assert_fullscreen_toolbar_button_interactions(
app: Page,
assert_snapshot: ImageCompareFunction,
widget_test_id: str,
filename_prefix: str = "",
nth: int = 0,
pixel_threshold: float = 0.05,
):
"""
Shared test function to assert that clicking on fullscreen toolbar button
expands the map into fullscreen.
"""

widget_element = app.get_by_test_id(widget_test_id).nth(nth)
widget_toolbar = widget_element.get_by_test_id("stElementToolbar")
fullscreen_wrapper = app.get_by_test_id("stFullScreenFrame").nth(nth)

fullscreen_toolbar_button = widget_toolbar.get_by_test_id(
"stElementToolbarButton"
).last

# Activate toolbar:
widget_element.hover()
# Check that it is visible
expect(widget_toolbar).to_have_css("opacity", "1")

# Click on expand to fullscreen button:
fullscreen_toolbar_button.click()

# Check that it is visible
assert_snapshot(
fullscreen_wrapper,
name=f"{filename_prefix if filename_prefix != "" else widget_test_id}-fullscreen_expanded",
pixel_threshold=pixel_threshold,
)

# Click again on fullscreen button to close fullscreen mode:
fullscreen_toolbar_button.click()
assert_snapshot(
fullscreen_wrapper,
name=f"{filename_prefix if filename_prefix != "" else widget_test_id}-fullscreen_collapsed",
pixel_threshold=pixel_threshold,
)
35 changes: 8 additions & 27 deletions e2e_playwright/st_dataframe_interactions_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
from e2e_playwright.conftest import IframedPage, ImageCompareFunction, wait_for_app_run
from e2e_playwright.shared.app_utils import expect_prefixed_markdown, get_element_by_key
from e2e_playwright.shared.dataframe_utils import click_on_cell, get_open_cell_overlay
from e2e_playwright.shared.toolbar_utils import (
assert_fullscreen_toolbar_button_interactions,
)

# This test suite covers all interactions of dataframe & data_editor

Expand Down Expand Up @@ -202,33 +205,11 @@ def test_clicking_on_fullscreen_toolbar_button(
):
"""Test that clicking on fullscreen toolbar button expands the dataframe into fullscreen."""

dataframe_element = app.get_by_test_id("stDataFrame").nth(0)
dataframe_toolbar = dataframe_element.get_by_test_id("stElementToolbar")
fullscreen_wrapper = app.get_by_test_id("stFullScreenFrame").nth(0)

fullscreen_toolbar_button = dataframe_toolbar.get_by_test_id(
"stElementToolbarButton"
).last

# Activate toolbar:
dataframe_element.hover()
# Check that it is visible
expect(dataframe_toolbar).to_have_css("opacity", "1")

# Click on expand to fullscreen button:
fullscreen_toolbar_button.click()

# Check that it is visible
assert_snapshot(
fullscreen_wrapper,
name="st_dataframe-fullscreen_expanded",
)

# Click again on fullscreen button to close fullscreen mode:
fullscreen_toolbar_button.click()
assert_snapshot(
fullscreen_wrapper,
name="st_dataframe-fullscreen_collapsed",
assert_fullscreen_toolbar_button_interactions(
app,
assert_snapshot=assert_snapshot,
widget_test_id="stDataFrame",
filename_prefix="st_dataframe",
)


Expand Down
23 changes: 23 additions & 0 deletions e2e_playwright/st_map_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@

from e2e_playwright.conftest import ImageCompareFunction, wait_for_app_run
from e2e_playwright.shared.app_utils import check_top_level_class
from e2e_playwright.shared.toolbar_utils import (
assert_fullscreen_toolbar_button_interactions,
)


# Firefox seems to be failing but can't reproduce locally and video produces an empty page for firefox
Expand Down Expand Up @@ -69,3 +72,23 @@ def test_st_map_has_consistent_visuals(
def test_check_top_level_class(app: Page):
"""Check that the top level class is correctly set."""
check_top_level_class(app, "stDeckGlJsonChart")


# Firefox seems to be failing but can't reproduce locally and video produces an empty page for firefox
@pytest.mark.skip_browser("firefox")
def test_st_map_clicking_on_fullscreen_toolbar_button(
app: Page, assert_snapshot: ImageCompareFunction
):
"""Test that clicking on fullscreen toolbar button expands the map into fullscreen."""

# wait for mapbox to load
wait_for_app_run(app, 15000)

assert_fullscreen_toolbar_button_interactions(
app,
assert_snapshot=assert_snapshot,
widget_test_id="stDeckGlJsonChart",
filename_prefix="st_map",
# The pydeck tests are a lot flakier than need be so increase the pixel threshold
pixel_threshold=1.0,
)
25 changes: 24 additions & 1 deletion e2e_playwright/st_pydeck_chart_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,11 @@
import pytest
from playwright.sync_api import Page, expect

from e2e_playwright.conftest import ImageCompareFunction
from e2e_playwright.conftest import ImageCompareFunction, wait_for_app_run
from e2e_playwright.shared.app_utils import check_top_level_class
from e2e_playwright.shared.toolbar_utils import (
assert_fullscreen_toolbar_button_interactions,
)


# Firefox seems to be failing but can't reproduce locally and video produces an empty page for firefox
Expand Down Expand Up @@ -84,3 +87,23 @@ def test_check_top_level_class(app: Page):
expect(pydeck_charts.first).to_be_attached(timeout=15000)

check_top_level_class(app, "stDeckGlJsonChart")


# Firefox seems to be failing but can't reproduce locally and video produces an empty page for firefox
@pytest.mark.skip_browser("firefox")
def test_st_pydeck_clicking_on_fullscreen_toolbar_button(
app: Page, assert_snapshot: ImageCompareFunction
):
"""Test that clicking on fullscreen toolbar button expands the map into fullscreen."""

# wait for mapbox to load
wait_for_app_run(app, 15000)

assert_fullscreen_toolbar_button_interactions(
app,
assert_snapshot=assert_snapshot,
widget_test_id="stDeckGlJsonChart",
filename_prefix="st_pydeck_chart",
# The pydeck tests are a lot flakier than need be so increase the pixel threshold
pixel_threshold=1.0,
)
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import {
EmotionTheme,
hasLightBackgroundColor,
} from "@streamlit/lib/src/theme"
import Toolbar from "@streamlit/lib/src/components/shared/Toolbar"
import { withFullScreenWrapper } from "@streamlit/lib/src/components/shared/FullScreenWrapper"

import withMapboxToken from "./withMapboxToken"
Expand All @@ -46,10 +47,13 @@ const EMPTY_LAYERS: LayersList = []

export const DeckGlJsonChart: FC<PropsWithHeight> = props => {
const {
collapse,
disableFullscreenMode,
element,
expand,
height: propsHeight,
isFullScreen,
width: propsWidth,
height: propsHeight,
} = props
const theme: EmotionTheme = useTheme()

Expand Down Expand Up @@ -78,6 +82,13 @@ export const DeckGlJsonChart: FC<PropsWithHeight> = props => {
width={width}
height={height}
>
<Toolbar
isFullScreen={isFullScreen}
disableFullscreenMode={disableFullscreenMode}
onExpand={expand}
onCollapse={collapse}
target={StyledDeckGlChart}
/>
<DeckGL
viewState={viewState}
onViewStateChange={onViewStateChange}
Expand Down Expand Up @@ -112,5 +123,5 @@ export const DeckGlJsonChart: FC<PropsWithHeight> = props => {
}

export default withMapboxToken("st.pydeck_chart")(
withFullScreenWrapper(DeckGlJsonChart)
withFullScreenWrapper(DeckGlJsonChart, true)
)
3 changes: 3 additions & 0 deletions frontend/lib/src/components/elements/DeckGlJsonChart/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ export interface DeckGLProps {

export interface PropsWithHeight extends DeckGLProps {
height?: number
expand?: () => void
collapse?: () => void
disableFullscreenMode?: boolean
}

export interface DeckObject {
Expand Down

0 comments on commit 7913ce5

Please sign in to comment.