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

[Tidy] Proof of concept replacing ctd for filter and parameter #880

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

antonymilne
Copy link
Contributor

@antonymilne antonymilne commented Nov 15, 2024

Description

@petar-qb raising this PR just to see if you think it's a good idea as a change. I won't actually implement it until you've done your PR so you don't have to resolve any more conflicts.

I'm finally continuing work on #363 and this seems like a small refactor that will tidy things up some more before the conversion to classes, which will hopefully be the next PR I raise on this topic 🤞

So far this PR is just a proof of concept to show what the change would look like. I haven't fully rolled it out or updated tests yet but the simple demo app works exactly the same as before.

Basically we passed filters and parameters through inputs in the callbacks before but didn't actually use them anywhere and instead looked inside ctx.args_grouping to extract all the values and and component ids. The only actual properties used in the CallbackTriggerDict are id and value. We can instead pass through named states in the form {<id>: State(...)} to get the id passed in automatically so we don't need ctx.args_grouping for that. I don't think we'll ever need it for anything else. Here's what's in it to remind you:

class CallbackTriggerDict(TypedDict):
    """Represent dash.ctx.args_grouping item. Shortened as 'ctd' in the code.

    Args:
        id: The component ID. If it's a pattern matching ID, it will be a dict.
        property: The component property used in the callback.
        value: The value of the component property at the time the callback was fired.
        str_id: For pattern matching IDs, it's the stringified dict ID without white spaces.
        triggered: A boolean indicating whether this input triggered the callback.

    """

    id: ModelID
    property: Literal["clickData", "value", "n_clicks", "active_cell", "derived_viewport_data"]
    value: Optional[Any]
    str_id: str
    triggered: bool

The change here would achieve be half of what you suggest in this comment:

        # TODO-AV2-OQ: Consider the following inputs ctx form:
        #  ```
        #  return {
        #      target_1: {'filters': ..., 'parameters': ..., 'filter_interaction': ..., 'theme_selector': ...},
        #      target_2: {'filters': ..., 'parameters': ..., 'filter_interaction': ..., 'theme_selector': ...},
        #  }
        #  ```
        #  Pros:
        #  1. We don't need anymore to send all filter/parameters/filter_interaction inputs to the server
        #  2. Potentially we don't need to dig through the ctx in the _actions_utils.py which decreases the complexity

The other half is also captured by my more recent comment:

    # TODO: the structure here would be nicer if we could get just the ctds for a single target at one time,
    #  so you could do apply_filters on a target a pass only the ctds relevant for that target.
    #  Consider restructuring ctds to a more convenient form to make this possible.

Screenshot

Notice

  • I acknowledge and agree that, by checking this box and clicking "Submit Pull Request":

    • I submit this contribution under the Apache 2.0 license and represent that I am entitled to do so on behalf of myself, my employer, or relevant third parties, as applicable.
    • I certify that (a) this contribution is my original creation and / or (b) to the extent it is not my original creation, I am authorized to submit this contribution on behalf of the original creator(s) or their licensees.
    • I certify that the use of this contribution as authorized by the Apache 2.0 license does not violate the intellectual property rights of anyone else.
    • I have not referenced individuals, products or companies in any commits, directly or indirectly.
    • I have not added data or restricted code in any commits, directly or indirectly.

Copy link
Contributor

github-actions bot commented Nov 15, 2024

View the example dashboards of the current commit live on PyCafe ☕ 🚀

Updated on: 2024-11-15 15:26:40 UTC
Commit: 94a90cd

Link: vizro-core/examples/dev/

Link: vizro-core/examples/scratch_dev

Link: vizro-core/examples/visual-vocabulary/

Link: vizro-ai/examples/dashboard_ui/

@petar-qb
Copy link
Contributor

I like the initiative! There's a huge room for improvement regarding the ctds. We have to find the best possible format for sending these from the client to the server.

In your code version, states are sent like:

dict(component_id_1=State(componenent_id, ...), component_id_2=...).

It's similar to the current filter_interaction format. However, for the filter_interaction, we decided to sent it like this

list({
        "clickData": State(component_id=self.id, component_property="clickData"),
        "modelID": State(component_id=self.id, component_property="id"),  # required, to determine triggered model
    }, 
    {...},
)

The current filter_interaction way enables to propagate multiple different properties from of the same component to the server. So, we should preserve this flexibility I think.

N.B.
There are two tickets we should keep in mind while thinking about the ctds changes:

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.

2 participants