Skip to content

Commit

Permalink
Refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
bfmatei committed Dec 5, 2024
1 parent 148f937 commit 82a70e3
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 21 deletions.
47 changes: 40 additions & 7 deletions packages/scenes/src/core/SceneScopesBridge.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,48 @@
import { isEqual } from 'lodash';
import { useEffect } from 'react';
import { BehaviorSubject, filter, map, Observable, pairwise, Unsubscribable } from 'rxjs';

import { Scope } from '@grafana/data';

import { SceneObjectBase } from './SceneObjectBase';
import { SceneComponentProps, SceneObjectState } from './types';
import { SceneComponentProps, SceneObjectState, SceneObjectUrlValues, SceneObjectWithUrlSync } from './types';
import { ScopesContextValue, useScopes } from './ScopesContext';
import { SceneObjectUrlSyncConfig } from '../services/SceneObjectUrlSyncConfig';

export interface SceneScopesBridgeState extends SceneObjectState {}

export class SceneScopesBridge extends SceneObjectBase<SceneScopesBridgeState> {
export class SceneScopesBridge extends SceneObjectBase<SceneScopesBridgeState> implements SceneObjectWithUrlSync {
static Component = SceneScopesBridgeRenderer;

protected _urlSync = new SceneObjectUrlSyncConfig(this, { keys: ['scopes'] });

protected _renderBeforeActivation = true;

private _contextSubject = new BehaviorSubject<ScopesContextValue | undefined>(undefined);

private _pendingScopes: string[] | null = null;

public constructor(state: SceneScopesBridgeState) {
super(state);
}

public getUrlState(): SceneObjectUrlValues {
return {
scopes: this._pendingScopes ?? (this.context?.state.value ?? []).map((scope) => scope.metadata.name),
};
}

public updateFromUrl(values: SceneObjectUrlValues) {
let scopes = values['scopes'] ?? [];
scopes = (Array.isArray(scopes) ? scopes : [scopes]).map(String);

if (!this.context) {
this._pendingScopes = scopes;
return;
}

this.context?.changeScopes(scopes);
}

public getValue(): Scope[] {
return this.context?.state.value ?? [];
}
Expand Down Expand Up @@ -78,8 +100,21 @@ export class SceneScopesBridge extends SceneObjectBase<SceneScopesBridgeState> {
}

public updateContext(newContext: ScopesContextValue | undefined) {
if (this.context !== newContext) {
if (this._pendingScopes && newContext) {
setTimeout(() => {
newContext?.changeScopes(this._pendingScopes!);
this._pendingScopes = null;
});
}

if (this.context !== newContext || this.context?.state !== newContext?.state) {
const shouldUpdate = this.context?.state.value !== newContext?.state.value;

this._contextSubject.next(newContext);

if (shouldUpdate) {
setTimeout(() => this.forceRender());
}
}
}

Expand All @@ -95,9 +130,7 @@ export class SceneScopesBridge extends SceneObjectBase<SceneScopesBridgeState> {
function SceneScopesBridgeRenderer({ model }: SceneComponentProps<SceneScopesBridge>) {
const context = useScopes();

useEffect(() => {
model.updateContext(context);
}, [context, model]);
model.updateContext(context);

return null;
}
27 changes: 13 additions & 14 deletions packages/scenes/src/core/ScopesContext.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { createContext, useContext } from 'react';
import { useObservable } from 'react-use';
import { Observable, Subscription } from 'rxjs';
import { Observable } from 'rxjs';

import { Scope } from '@grafana/data';

Expand All @@ -9,21 +9,14 @@ export interface ScopesContextValue {
isEnabled: boolean;
isLoading: boolean;
isReadOnly: boolean;
pendingScopes: string[] | null;
value: Scope[];
};
stateObservable: Observable<ScopesContextValue['state']>;
setNewScopes: (scopeNames: string[] | null) => void;
setCurrentScopes: (scopes: Scope[]) => void;
enterLoadingMode: () => void;
exitLoadingMode: () => void;
changeScopes: (scopeNames: string[]) => void;
enterReadOnly: () => void;
exitReadOnly: () => void;
enable: () => void;
disable: () => void;
subscribeToState: (
cb: (newState: ScopesContextValue['state'], prevState: ScopesContextValue['state']) => void
) => Subscription;
}

export const ScopesContext = createContext<ScopesContextValue | undefined>(undefined);
Expand All @@ -33,9 +26,15 @@ export function useScopes() {

useObservable(context?.stateObservable ?? new Observable(), context?.state);

if (!context) {
return undefined;
}

return context;
return context
? {
state: context.state,
stateObservable: context.stateObservable,
changeScopes: context.changeScopes,
enterReadOnly: context.enterReadOnly,
exitReadOnly: context.exitReadOnly,
enable: context.enable,
disable: context.disable,
}
: undefined;
}

0 comments on commit 82a70e3

Please sign in to comment.