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

refactor: Updated spectrum imports to use dh components #424

Merged
merged 4 commits into from
Apr 24, 2024

Conversation

bmingles
Copy link
Contributor

@bmingles bmingles commented Apr 18, 2024

Imports for Spectrum components that are available in @deephaven/components have been updated.

Components that are not yet re-exported by @deephaven/components:

We also will want to rename some things such that DH components aren't mapped to SPECTRUM_ELEMENT_TYPE_PREFIX #425

#366

@bmingles bmingles requested a review from mofojed April 18, 2024 20:18
mofojed
mofojed previously approved these changes Apr 19, 2024
Copy link
Member

@mofojed mofojed left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, but should we just wait until deephaven/web-client-ui#1919 and rest of the components are exported and do it all at once?

@bmingles
Copy link
Contributor Author

bmingles commented Apr 19, 2024

Looks good, but should we just wait until deephaven/web-client-ui#1919 and rest of the components are exported and do it all at once?

I merged 1919 so we could do a release and include it. It only addresses Icon. Will still have to address ButtonGroup and CheckBox later

@bmingles
Copy link
Contributor Author

@mofojed I updated DHC version and included Icon in the exports from DHC

Copy link
Member

@mofojed mofojed left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where's the PR for exporting ButtonGroup and Checkbox ? Any reason to not do this all in one shot?

@bmingles
Copy link
Contributor Author

Where's the PR for exporting ButtonGroup and Checkbox ? Any reason to not do this all in one shot?

Since we already export components with these names from @deephaven/components not sure how we want to handle the Spectrum ones. My assumption was eventually ours will be wrappers on Spectrum and maybe adhere closer to Spectrum apis.

The python apis are already assuming checkbox and button_group are Spectrum api based and not our custom ones, so this will require more than just re-mapping an export

plugins/ui/src/deephaven/ui/components/spectrum/button_group.py and checkbox in plugins/ui/src/deephaven/ui/components/spectrum/basic.py

I created #433 to follow up

@bmingles bmingles merged commit db97c9a into deephaven:main Apr 24, 2024
16 checks passed
bmingles added a commit to deephaven/web-client-ui that referenced this pull request Apr 24, 2024
NOTE: This PR depends on
deephaven/deephaven-plugins#424 in order for
element type checks to work for `Item`, `Text`, `Section`, etc.

- Refactored non-jsapi Picker to support JSX children with minimal
wrapping instead of having to normalize items (#1890 should do the same
for ListView, and we should be able to delete some of the normalization
code)
- Updated scroll position logic to be able to traverse JSX elements
- Disable initial scrolling when children contain descriptions or
sections

**Testing**
This illustrates different configurations and shows how initial scroll
behavior differs for Pickers with plain items, descriptions, or
sections:

```python
import deephaven.ui as ui
from math import floor
import datetime

# Ticking table with initial row count of 200 that adds a row every second
initial_row_count=1000
items_table = time_table("PT1S", start_time=datetime.datetime.now() - datetime.timedelta(seconds=initial_row_count)).update([
    "Id=new Integer(i)",
    "Display=new String(`Display `+i)",
])

@ui.component
def pickers():
    value, set_value = ui.use_state('2SSS')

    def handle_change(v):
        print(v)
        set_value(v)

    on_change = ui.use_callback(handle_change, [])

    # Picker with text options
    text = ui.picker(
        label="Text",
        children=[
            'Text 1',
            'Text 2',
            'Text 3'
        ]
    )

    # Picker with boolean options
    boolean = ui.picker(
        label="Boolean",
        children=[
            True,
            False
        ]
    )

    # Picker with numeric options
    numeric = ui.picker(
        label="Numeric",
        children=[
            10,
            20,
            30
        ]
    )

    ################ Icons #######################################

    # Icons
    icons = ui.picker(
        label = "Icons",
        children = [
            item_with_icon('Add', 'vsAdd'),
            item_with_icon('Remove', 'vsRemove'),
        ]
    )

    # Icons (default selection)
    icons_default_selection = ui.picker(
        label = "Icons (default selection)",
        default_selected_key="3GGG",
        children = list(map(
            lambda args : item(args[1]) if args[0] % 7 > 0 else item_with_icon(args[1], 'vsAccount'), 
            enumerate(generate_item_texts(0, 500))))
    )

     # Icons (controlled)
    icons_controlled = ui.picker(
        label = "Icons (controlled)",
        selected_key=value,
        on_change=on_change,
        children = list(map(
            lambda args : item(args[1]) if args[0] % 7 > 0 else item_with_icon(args[1], 'vsAccount'), 
            enumerate(generate_item_texts(0, 500))))
    )

    ################ Descriptions #######################################

    # Descriptions (default selection)
    descriptions = ui.picker(
        label = "Descriptions",
        children = list(map(lambda txt : item(txt, True), generate_item_texts(0, 500)))
    )

    # Descriptions (default selection)
    descriptions_default_selection = ui.picker(
        label = "Descriptions (default selection)",
        default_selected_key="3GGG",
        children = list(map(lambda txt : item(txt, True), generate_item_texts(0, 500)))
    )

    # Descriptions (controlled)
    descriptions_controlled = ui.picker(
        label = "Descriptions (controlled)",
        selected_key=value,
        on_change=on_change,
        children = list(map(lambda txt : item(txt, True), generate_item_texts(0, 500)))
    )

    ################ Sections #######################################

    # Sections
    sections = ui.picker(
        label = "Sections (default selection)",
        children = [
            section(x, i * 10, i * 10 + 9) for i, x in enumerate(generate_item_texts(0, 19))
        ]
    )

    # Sections (default selection)
    sections_default_selection = ui.picker(
        label = "Sections (default selection)",
        default_selected_key = "3GGG",
        children = [
            section(x, i * 10, i * 10 + 9) for i, x in enumerate(generate_item_texts(0, 19))
        ]
    )

    # Sections (controlled)
    sections_controlled = ui.picker(
        label = "Sections (controlled)",
        selected_key=value,
        on_change=on_change,
        children = [
            section(x, i * 10, i * 10 + 9) for i, x in enumerate(generate_item_texts(0, 19))
        ]
    )

    ################ Tables #######################################

    table_value, set_table_value = ui.use_state('Display 824')

    # Uncontrolled table with default selection
    table = ui.picker(
        items_table,
        key_column="Display",
        label_column="Display",
        label="Table",
    )

    # Uncontrolled table with default selection
    table_default_selection = ui.picker(
        items_table,
        key_column="Display",
        label_column="Display",
        label="Table (default selection)",
        default_selected_key="Display 86",
    )

    # Controlled table
    table_controlled = ui.picker(
        items_table,
        key_column="Display",
        label_column="Display",
        label="Table (controlled)",
        on_selection_change=set_table_value,
        selected_key=table_value,
    )

    return ui.flex(
        direction="column",
        UNSAFE_style={"overflow":"scroll"},
        children = [
            ui.heading("Basic", margin=0),
            ui.flex(
                direction='row',
                children=[
                    text,
                    boolean,
                    numeric,
                ]
            ),
            ui.heading("Icons", margin=0),
            ui.flex(
                direction='row',
                children=[
                    icons,
                    icons_default_selection,
                    icons_controlled,
                ]
            ),
            ui.heading("Descriptions", margin=0),
            ui.flex(
                direction='row',
                children=[
                    descriptions,
                    descriptions_default_selection,
                    descriptions_controlled,
                ]
            ),
            ui.heading("Sections", margin=0),
            ui.flex(
                direction='row',
                children=[
                    sections,
                    sections_default_selection,
                    sections_controlled,
                ]
            ),
            ui.heading("Table", margin=0),
            ui.flex(
                direction='row',
                children=[
                    table,
                    table_default_selection,
                    table_controlled,
                ]
            )
        ],
    )

pick = pickers()

################ Helpers #######################################

# Generate a list of unique item text for a start / stop range
def generate_item_texts(start, stop):
    characters = list("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
    size = len(characters)
    return [str(floor((i + start) / size)) + (characters[x % size] * 3) for i, x in enumerate(range(start, stop))]

@ui.component
def item(txt, include_description=False):
    return ui.item(
        ui.text(txt, key="label"),
        ui.text("Description " + txt, key="description", slot="description"),
        # key=txt,
        text_value=txt
    ) if include_description else ui.item(txt, text_value=txt)

@ui.component
def item_with_icon(txt, icon):
    return ui.item(
        text_value=txt,
        children=[
            ui.icon(icon),
            txt,
        ]
    )

@ui.component
def section(txt, start, end):
    return ui.section(
        title = "Section " + txt,
        children = list(map(lambda txt : item(txt), generate_item_texts(start, end)))
    )
```

resolves #1935
@bmingles bmingles linked an issue Apr 29, 2024 that may be closed by this pull request
@bmingles bmingles deleted the 366-use-dh-components branch May 3, 2024 16:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Cleanup component mappings and utils ui.list_view - basic items + table support
2 participants