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

Scopes: Add ScopesBridge object #990

Open
wants to merge 11 commits into
base: main
Choose a base branch
from

Conversation

bfmatei
Copy link
Contributor

@bfmatei bfmatei commented Dec 4, 2024

Continuing the discussion from here: grafana/grafana#97176

So what this PR brings: allow SceneObjects to consume React Contexts.

📦 Published PR as canary version: 5.29.1--canary.990.12238644149.0

✨ Test out this PR locally via:

npm install @grafana/[email protected]
npm install @grafana/[email protected]
# or 
yarn add @grafana/[email protected]
yarn add @grafana/[email protected]

Copy link
Member

@torkelo torkelo left a comment

Choose a reason for hiding this comment

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

I think this is really cool, but until we have more examples / stronger need for this for many contexts I would recommend a more simple specific implementation for the ScopeContext specifically (maybe a base class that can handle some generic stuff).

Like a ScopeContextConsumer scene object that you can add to your scene (we would add it to DashboardScene), maybe we add it as an optional state prop to EmbeddeddScene or SceneApp (DashboardSceneRenderer would have render the ScopeContextConsumer component to make the context => scene state active).

Adding this to all scene objects, and to ComponentWrapper feels a bit too drastic until we know how much this will be used

@torkelo
Copy link
Member

torkelo commented Dec 4, 2024

But I do think something like ScopesContextConsumer or ScopesSceneBridge (whatever we call it), could be something we add to scenes lib (and it depends on the context in runtime). And then scene app plugins can use it

Copy link
Member

@dprokop dprokop left a comment

Choose a reason for hiding this comment

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

Agree with Torkel overall, this is a neat addition, but maybe would be worth talking it trough more widely if there's really a library need for this. It introduces quite a bit of complexity, and I'm not sure if we should solve this problem in classic scenes, but rather in react-scenes.

Comment on lines 46 to 52
function SceneComponentWrapperWithoutMemo<T extends SceneObject>({ model, ...otherProps }: SceneComponentProps<T>) {
return [
<ContextsConsumer key="contexts" model={model} />,
<ComponentRenderer key="component" model={model} {...otherProps} />,
];
}

Copy link
Member

Choose a reason for hiding this comment

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

Took me a bit to udnerstand this 🤔

@bfmatei
Copy link
Contributor Author

bfmatei commented Dec 5, 2024

@torkelo @dprokop

I refactored this to only use React Context for Scopes (added a bridge between scopes and scenes).

A couple of notes:

  • SceneApp seems the best place to place the bridge as it's top level, meaning that all nested scene objects can get it
  • SceneAppPage have a useScopes flag that control wether a page should or should not show the scopes selector
  • the bridge also handles URL sync as it's way better than controlling it via the service (I can change this tho')
  • added usage for SceneQueryRunner as well as adhoc variables and groupby variables. No more double queries and no more data/filters enriching needed
  • the context is defined here for testing purposes as it's easier than to link runtime to scopes and then scopes to grafana while doing development
  • the useScopes hook has to spread the context as simply returning the context won't take effect for use-cases like
useEffect(() => {
  console.log(context);
}, [context]);
  • the context has to be a service as it's way easier to offer interoperability between scopes dashboards, scopes selector and the scopes "facade"
  • we need to do something with Prettier. Apparently there are a lot of files which are not formatted correctly 😢

Copy link
Member

@torkelo torkelo left a comment

Choose a reason for hiding this comment

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

I think this looking really good

I think the isScopesLoading code added to AdHocFilters and GroupByVarable feel a bit on the "too complex" / detail that it should not have to care so deeply about (ie subscribe to state etc).

Wonder if we can skip that for now, and if it becomes a problem find a less invasive solution (like a loading spinner on the whole scene until scopes have initialized)

packages/scenes/src/core/SceneScopesBridge.ts Outdated Show resolved Hide resolved
@@ -140,6 +143,7 @@ export class SceneQueryRunner extends SceneObjectBase<QueryRunnerState> implemen
private _onActivate() {
if (this.isQueryModeAuto()) {
const timeRange = sceneGraph.getTimeRange(this);
const scopesBridge = sceneGraph.getScopesBridge(this);
Copy link
Member

Choose a reason for hiding this comment

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

Long term I think it would be cool to generalize this concept with a special variable type that all query runners and variables depend on by default (so will block initial query execution), and the variable can then modify the query.

I tried to start a poc around it, a QueryEnhancerVariable but did not get very far.

But I think this implementation is also ok, just a shame it adds more complexity to this already complex class :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I have something in mind regarding this. I'll start a PoC in the next weeks 🤔 .

Copy link
Contributor Author

@bfmatei bfmatei left a comment

Choose a reason for hiding this comment

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

I'll just continue doing testing for this and see how it goes. I also need to fix the code in core and test that out as well.

packages/scenes-app/src/components/SomeReactContext.tsx Outdated Show resolved Hide resolved
@@ -140,6 +143,7 @@ export class SceneQueryRunner extends SceneObjectBase<QueryRunnerState> implemen
private _onActivate() {
if (this.isQueryModeAuto()) {
const timeRange = sceneGraph.getTimeRange(this);
const scopesBridge = sceneGraph.getScopesBridge(this);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I have something in mind regarding this. I'll start a PoC in the next weeks 🤔 .

packages/scenes/src/core/SceneScopesBridge.ts Outdated Show resolved Hide resolved
@@ -69,6 +71,9 @@ export interface SceneAppPageState extends SceneObjectState {
getFallbackPage?: () => SceneAppPageLike;

layout?: PageLayoutType;

// Whether to use scopes for this page
useScopes?: boolean;
Copy link
Member

Choose a reason for hiding this comment

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

do we really need this as a page level prop?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm thinking that some pages might not want scopes to be shown for various reasons 🤔

Copy link
Member

@dprokop dprokop left a comment

Choose a reason for hiding this comment

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

@bfmatei - this looks good now! Excellent job on bringing this to scenes. I've left just a few nits to consider.

packages/scenes/src/core/SceneScopesBridge.ts Outdated Show resolved Hide resolved
packages/scenes/src/components/SceneApp/SceneAppPage.tsx Outdated Show resolved Hide resolved
packages/scenes/src/core/SceneScopesBridge.ts Outdated Show resolved Hide resolved
}

this.runWithTimeRange(timeRange);
this.runWithTimeRangeAndScopes(timeRange, scopesBridge);
Copy link
Member

Choose a reason for hiding this comment

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

Let's add tests for making sure the SQR works as expected w/ scopes.

@bfmatei bfmatei force-pushed the bogdan/react-contexts-bindings-poc branch from 6265009 to c3a4b47 Compare December 9, 2024 14:40
@bfmatei bfmatei added patch Increment the patch version when merged release Create a release when this pr is merged labels Dec 9, 2024
@bfmatei bfmatei changed the title ReactContexts: PoC Scopes: Add ScopesBridge object Dec 9, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
patch Increment the patch version when merged release Create a release when this pr is merged
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants