@grafana/scenes 6.22.1 → 6.23.0--canary.1156.15877258579.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/core/types.js.map +1 -1
- package/dist/esm/services/UniqueUrlKeyMapper.js +18 -2
- package/dist/esm/services/UniqueUrlKeyMapper.js.map +1 -1
- package/dist/esm/services/UrlSyncContextProvider.js +9 -2
- package/dist/esm/services/UrlSyncContextProvider.js.map +1 -1
- package/dist/esm/services/UrlSyncManager.js +16 -5
- package/dist/esm/services/UrlSyncManager.js.map +1 -1
- package/dist/esm/services/utils.js +4 -4
- package/dist/esm/services/utils.js.map +1 -1
- package/dist/index.d.ts +18 -3
- package/dist/index.js +47 -13
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"types.js","sources":["../../../src/core/types.ts"],"sourcesContent":["import React from 'react';\nimport { MonoTypeOperatorFunction, Observable, Unsubscribable } from 'rxjs';\n\nimport {\n BusEvent,\n BusEventHandler,\n BusEventType,\n DataFrame,\n DataQueryRequest,\n DataSourceGetTagKeysOptions,\n DataSourceGetTagValuesOptions,\n DataTransformContext,\n PanelData,\n TimeRange,\n} from '@grafana/data';\nimport { DataQuery, DataTopic, TimeZone } from '@grafana/schema';\n\nimport { SceneVariableDependencyConfigLike, SceneVariables } from '../variables/types';\nimport { SceneObjectRef } from './SceneObjectRef';\nimport { VizPanel } from '../components/VizPanel/VizPanel';\nimport { WeekStart } from '@grafana/ui';\n\nexport interface SceneObjectState {\n key?: string;\n $timeRange?: SceneTimeRangeLike;\n $data?: SceneDataProvider;\n $variables?: SceneVariables;\n /**\n * @experimental\n * Can be used to add extra behaviors to a scene object.\n * These are activated when the their parent scene object is activated.\n */\n $behaviors?: Array<SceneObject | SceneStatelessBehavior>;\n}\n\nexport interface SceneLayoutChildOptions {\n width?: number | string;\n height?: number | string;\n xSizing?: 'fill' | 'content';\n ySizing?: 'fill' | 'content';\n x?: number;\n y?: number;\n minWidth?: number | string;\n minHeight?: number | string;\n isDraggable?: boolean;\n isResizable?: boolean;\n}\n\nexport interface SceneComponentProps<T> {\n model: T;\n}\n\nexport type SceneComponent<TModel> = (props: SceneComponentProps<TModel>) => React.ReactElement | null;\n\nexport interface SceneDataState extends SceneObjectState {\n data?: PanelData;\n}\n\nexport interface SceneObject<TState extends SceneObjectState = SceneObjectState> {\n /** The current state */\n readonly state: TState;\n\n /** True when there is a React component mounted for this Object */\n readonly isActive: boolean;\n\n /** Controls if activation blocks rendering */\n readonly renderBeforeActivation: boolean;\n\n /** SceneObject parent */\n readonly parent?: SceneObject;\n\n /** This abtractions declares what variables the scene object depends on and how to handle when they change value. **/\n readonly variableDependency?: SceneVariableDependencyConfigLike;\n\n /** This abstraction declares URL sync dependencies of a scene object. **/\n readonly urlSync?: SceneObjectUrlSyncHandler;\n\n /** Subscribe to state changes */\n subscribeToState(handler: SceneStateChangedHandler<TState>): Unsubscribable;\n\n /** Subscribe to a scene event */\n subscribeToEvent<T extends BusEvent>(typeFilter: BusEventType<T>, handler: BusEventHandler<T>): Unsubscribable;\n\n /** Publish an event and optionally bubble it up the scene */\n publishEvent(event: BusEvent, bubble?: boolean): void;\n\n /** Utility hook that wraps useObservable. Used by React components to subscribes to state changes */\n useState(): TState;\n\n /** How to modify state */\n setState(state: Partial<TState>): void;\n\n /**\n * Called when the Component is mounted. This will also activate any $data, $variables or $timeRange scene object on this level.\n * Don't override this in your custom SceneObjects, instead use addActivationHandler from the constructor.\n **/\n activate(): CancelActivationHandler;\n\n /** Get the scene root */\n getRoot(): SceneObject;\n\n /** Returns a deep clone this object and all its children */\n clone(state?: Partial<TState>): this;\n\n /** A React component to use for rendering the object */\n Component(props: SceneComponentProps<SceneObject<TState>>): React.ReactElement | null;\n\n /** Force a re-render, should only be needed when variable values change */\n forceRender(): void;\n\n /** Returns a SceneObjectRef that will resolve to this object */\n getRef(): SceneObjectRef<this>;\n\n /**\n * Allows external code to register code that is executed on activate and deactivate. This allow you\n * to wire up scene objects that need to respond to state changes in other objects from the outside.\n **/\n addActivationHandler(handler: SceneActivationHandler): void;\n\n /**\n * Loop through state and call callback for each direct child scene object.\n * Checks 1 level deep properties and arrays. So a scene object hidden in a nested plain object will not be detected.\n */\n forEachChild(callback: (child: SceneObject) => void): void;\n\n /**\n * Useful for edge cases when you want to move a scene object to another parent.\n */\n clearParent(): void;\n}\n\nexport type SceneActivationHandler = () => SceneDeactivationHandler | void;\nexport type SceneDeactivationHandler = () => void;\n\n/**\n * Function returned by activate() that when called will deactivate the object if it's the last activator\n **/\nexport type CancelActivationHandler = () => void;\n\nexport interface SceneLayoutState extends SceneObjectState {\n children: SceneObject[];\n}\n\nexport interface SceneLayout<T extends SceneLayoutState = SceneLayoutState> extends SceneObject<T> {\n isDraggable(): boolean;\n getDragClass?(): string;\n getDragClassCancel?(): string;\n getDragHooks?(): { onDragStart?: (e: React.PointerEvent, panel: VizPanel) => void };\n}\n\nexport interface SceneTimeRangeState extends SceneObjectState {\n from: string;\n to: string;\n fiscalYearStartMonth?: number;\n value: TimeRange;\n timeZone?: TimeZone;\n /** weekStart will change the global date locale so having multiple different weekStart values is not supported */\n weekStart?: WeekStart;\n /**\n * @internal\n * To enable feature parity with the old time range picker, not sure if it will be kept.\n * Override the now time by entering a time delay. Use this option to accommodate known delays in data aggregation to avoid null values.\n * */\n UNSAFE_nowDelay?: string;\n\n refreshOnActivate?: {\n /**\n * When set, the time range will invalidate relative ranges after the specified interval has elapsed\n */\n afterMs?: number;\n /**\n * When set, the time range will invalidate relative ranges after the specified percentage of the current interval has elapsed.\n * If both invalidate values are set, the smaller value will be used for the given interval.\n */\n percent?: number;\n };\n}\n\nexport interface SceneTimeRangeLike extends SceneObject<SceneTimeRangeState> {\n onTimeZoneChange(timeZone: TimeZone): void;\n onTimeRangeChange(timeRange: TimeRange): void;\n onRefresh(): void;\n getTimeZone(): TimeZone;\n}\n\nexport function isSceneObject(obj: any): obj is SceneObject {\n return obj.useState !== undefined;\n}\n\nexport interface SceneObjectWithUrlSync extends SceneObject {\n getUrlState(): SceneObjectUrlValues;\n updateFromUrl(values: SceneObjectUrlValues): void;\n}\n\nexport interface SceneObjectUrlSyncHandler {\n getKeys(): string[];\n getUrlState(): SceneObjectUrlValues;\n updateFromUrl(values: SceneObjectUrlValues): void;\n shouldCreateHistoryStep?(values: SceneObjectUrlValues): boolean;\n performBrowserHistoryAction?(callback: () => void): void;\n}\n\nexport interface DataRequestEnricher {\n // Return partial data query request that will be merged with the original request provided by SceneQueryRunner\n enrichDataRequest(source: SceneObject): Partial<DataQueryRequest> | null;\n}\n\nexport interface FiltersRequestEnricher {\n // Return partial getTagKeys or getTagValues query request that will be merged with the original request provided by ad hoc or group by variable\n enrichFiltersRequest(\n source: SceneObject\n ): Partial<DataSourceGetTagKeysOptions | DataSourceGetTagValuesOptions> | null;\n}\n\nexport function isDataRequestEnricher(obj: any): obj is DataRequestEnricher {\n return 'enrichDataRequest' in obj;\n}\n\nexport function isFiltersRequestEnricher(obj: any): obj is FiltersRequestEnricher {\n return 'enrichFiltersRequest' in obj;\n}\n\nexport type SceneObjectUrlValue = string | string[] | undefined | null;\nexport type SceneObjectUrlValues = Record<string, SceneObjectUrlValue>;\n\nexport type CustomTransformOperator = (context: DataTransformContext) => MonoTypeOperatorFunction<DataFrame[]>;\nexport type CustomTransformerDefinition =\n | { operator: CustomTransformOperator; topic: DataTopic }\n | CustomTransformOperator;\nexport type SceneStateChangedHandler<TState> = (newState: TState, prevState: TState) => void;\n\nexport type DeepPartial<T> = {\n [K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K];\n};\n\nexport interface SceneDataProviderResult {\n data: PanelData;\n origin: SceneDataProvider;\n}\n\nexport interface SceneDataProvider<T extends SceneObjectState = SceneDataState> extends SceneObject<T> {\n setContainerWidth?: (width: number) => void;\n isDataReadyToDisplay?: () => boolean;\n cancelQuery?: () => void;\n getResultsStream(): Observable<SceneDataProviderResult>;\n}\n\nexport interface SceneDataLayerProviderState extends SceneDataState {\n name: string;\n description?: string;\n isEnabled?: boolean;\n isHidden?: boolean;\n}\n\nexport interface SceneDataLayerProvider extends SceneDataProvider<SceneDataLayerProviderState> {\n isDataLayer: true;\n}\n\nexport function isDataLayer(obj: SceneObject): obj is SceneDataLayerProvider {\n return 'isDataLayer' in obj;\n}\n\nexport interface DataLayerFilter {\n panelId: number;\n}\n\nexport interface SceneStatelessBehavior<T extends SceneObject = any> {\n (sceneObject: T): CancelActivationHandler | void;\n}\n\nexport type ControlsLayout = 'horizontal' | 'vertical';\n\nexport interface UseStateHookOptions {\n /**\n * For some edge cases other scene objects want to subscribe to scene object state for objects\n * that are not active, or whose main React Component can be un-mounted. Set this to true\n * to keep the scene object active even if the React component is unmounted.\n *\n * Normally you would not need this but this can be useful in some edge cases.\n *\n * @experimental\n */\n shouldActivateOrKeepAlive?: boolean;\n}\n\nexport interface SceneDataQuery extends DataQuery {\n [key: string]: any;\n\n // Opt this query out of time window comparison\n timeRangeCompare?: boolean;\n}\n\nexport interface SceneUrlSyncOptions {\n /**\n * This will update the url to contain all scene url state\n * when the scene is initialized. Important for browser history \"back\" actions.\n */\n updateUrlOnInit?: boolean;\n /**\n * This is only supported by some objects if they implement\n * shouldCreateHistoryStep where they can control what changes\n * url changes should add a new browser history entry.\n */\n createBrowserHistorySteps?: boolean;\n}\n"],"names":[],"mappings":"AAyLO,SAAS,cAAc,GAA8B,EAAA;AAC1D,EAAA,OAAO,IAAI,QAAa,KAAA,MAAA;AAC1B;AA2BO,SAAS,sBAAsB,GAAsC,EAAA;AAC1E,EAAA,OAAO,mBAAuB,IAAA,GAAA;AAChC;AAEO,SAAS,yBAAyB,GAAyC,EAAA;AAChF,EAAA,OAAO,sBAA0B,IAAA,GAAA;AACnC;AAsCO,SAAS,YAAY,GAAiD,EAAA;AAC3E,EAAA,OAAO,aAAiB,IAAA,GAAA;AAC1B;;;;"}
|
1
|
+
{"version":3,"file":"types.js","sources":["../../../src/core/types.ts"],"sourcesContent":["import React from 'react';\nimport { MonoTypeOperatorFunction, Observable, Unsubscribable } from 'rxjs';\n\nimport {\n BusEvent,\n BusEventHandler,\n BusEventType,\n DataFrame,\n DataQueryRequest,\n DataSourceGetTagKeysOptions,\n DataSourceGetTagValuesOptions,\n DataTransformContext,\n PanelData,\n TimeRange,\n} from '@grafana/data';\nimport { DataQuery, DataTopic, TimeZone } from '@grafana/schema';\n\nimport { SceneVariableDependencyConfigLike, SceneVariables } from '../variables/types';\nimport { SceneObjectRef } from './SceneObjectRef';\nimport { VizPanel } from '../components/VizPanel/VizPanel';\nimport { WeekStart } from '@grafana/ui';\n\nexport interface SceneObjectState {\n key?: string;\n $timeRange?: SceneTimeRangeLike;\n $data?: SceneDataProvider;\n $variables?: SceneVariables;\n /**\n * @experimental\n * Can be used to add extra behaviors to a scene object.\n * These are activated when the their parent scene object is activated.\n */\n $behaviors?: Array<SceneObject | SceneStatelessBehavior>;\n}\n\nexport interface SceneLayoutChildOptions {\n width?: number | string;\n height?: number | string;\n xSizing?: 'fill' | 'content';\n ySizing?: 'fill' | 'content';\n x?: number;\n y?: number;\n minWidth?: number | string;\n minHeight?: number | string;\n isDraggable?: boolean;\n isResizable?: boolean;\n}\n\nexport interface SceneComponentProps<T> {\n model: T;\n}\n\nexport type SceneComponent<TModel> = (props: SceneComponentProps<TModel>) => React.ReactElement | null;\n\nexport interface SceneDataState extends SceneObjectState {\n data?: PanelData;\n}\n\nexport interface SceneObject<TState extends SceneObjectState = SceneObjectState> {\n /** The current state */\n readonly state: TState;\n\n /** True when there is a React component mounted for this Object */\n readonly isActive: boolean;\n\n /** Controls if activation blocks rendering */\n readonly renderBeforeActivation: boolean;\n\n /** SceneObject parent */\n readonly parent?: SceneObject;\n\n /** This abtractions declares what variables the scene object depends on and how to handle when they change value. **/\n readonly variableDependency?: SceneVariableDependencyConfigLike;\n\n /** This abstraction declares URL sync dependencies of a scene object. **/\n readonly urlSync?: SceneObjectUrlSyncHandler;\n\n /** Subscribe to state changes */\n subscribeToState(handler: SceneStateChangedHandler<TState>): Unsubscribable;\n\n /** Subscribe to a scene event */\n subscribeToEvent<T extends BusEvent>(typeFilter: BusEventType<T>, handler: BusEventHandler<T>): Unsubscribable;\n\n /** Publish an event and optionally bubble it up the scene */\n publishEvent(event: BusEvent, bubble?: boolean): void;\n\n /** Utility hook that wraps useObservable. Used by React components to subscribes to state changes */\n useState(): TState;\n\n /** How to modify state */\n setState(state: Partial<TState>): void;\n\n /**\n * Called when the Component is mounted. This will also activate any $data, $variables or $timeRange scene object on this level.\n * Don't override this in your custom SceneObjects, instead use addActivationHandler from the constructor.\n **/\n activate(): CancelActivationHandler;\n\n /** Get the scene root */\n getRoot(): SceneObject;\n\n /** Returns a deep clone this object and all its children */\n clone(state?: Partial<TState>): this;\n\n /** A React component to use for rendering the object */\n Component(props: SceneComponentProps<SceneObject<TState>>): React.ReactElement | null;\n\n /** Force a re-render, should only be needed when variable values change */\n forceRender(): void;\n\n /** Returns a SceneObjectRef that will resolve to this object */\n getRef(): SceneObjectRef<this>;\n\n /**\n * Allows external code to register code that is executed on activate and deactivate. This allow you\n * to wire up scene objects that need to respond to state changes in other objects from the outside.\n **/\n addActivationHandler(handler: SceneActivationHandler): void;\n\n /**\n * Loop through state and call callback for each direct child scene object.\n * Checks 1 level deep properties and arrays. So a scene object hidden in a nested plain object will not be detected.\n */\n forEachChild(callback: (child: SceneObject) => void): void;\n\n /**\n * Useful for edge cases when you want to move a scene object to another parent.\n */\n clearParent(): void;\n}\n\nexport type SceneActivationHandler = () => SceneDeactivationHandler | void;\nexport type SceneDeactivationHandler = () => void;\n\n/**\n * Function returned by activate() that when called will deactivate the object if it's the last activator\n **/\nexport type CancelActivationHandler = () => void;\n\nexport interface SceneLayoutState extends SceneObjectState {\n children: SceneObject[];\n}\n\nexport interface SceneLayout<T extends SceneLayoutState = SceneLayoutState> extends SceneObject<T> {\n isDraggable(): boolean;\n getDragClass?(): string;\n getDragClassCancel?(): string;\n getDragHooks?(): { onDragStart?: (e: React.PointerEvent, panel: VizPanel) => void };\n}\n\nexport interface SceneTimeRangeState extends SceneObjectState {\n from: string;\n to: string;\n fiscalYearStartMonth?: number;\n value: TimeRange;\n timeZone?: TimeZone;\n /** weekStart will change the global date locale so having multiple different weekStart values is not supported */\n weekStart?: WeekStart;\n /**\n * @internal\n * To enable feature parity with the old time range picker, not sure if it will be kept.\n * Override the now time by entering a time delay. Use this option to accommodate known delays in data aggregation to avoid null values.\n * */\n UNSAFE_nowDelay?: string;\n\n refreshOnActivate?: {\n /**\n * When set, the time range will invalidate relative ranges after the specified interval has elapsed\n */\n afterMs?: number;\n /**\n * When set, the time range will invalidate relative ranges after the specified percentage of the current interval has elapsed.\n * If both invalidate values are set, the smaller value will be used for the given interval.\n */\n percent?: number;\n };\n}\n\nexport interface SceneTimeRangeLike extends SceneObject<SceneTimeRangeState> {\n onTimeZoneChange(timeZone: TimeZone): void;\n onTimeRangeChange(timeRange: TimeRange): void;\n onRefresh(): void;\n getTimeZone(): TimeZone;\n}\n\nexport function isSceneObject(obj: any): obj is SceneObject {\n return obj.useState !== undefined;\n}\n\nexport interface SceneObjectWithUrlSync extends SceneObject {\n getUrlState(): SceneObjectUrlValues;\n updateFromUrl(values: SceneObjectUrlValues): void;\n}\n\nexport interface SceneObjectUrlSyncHandler {\n getKeys(): string[];\n getUrlState(): SceneObjectUrlValues;\n updateFromUrl(values: SceneObjectUrlValues): void;\n shouldCreateHistoryStep?(values: SceneObjectUrlValues): boolean;\n performBrowserHistoryAction?(callback: () => void): void;\n}\n\nexport interface DataRequestEnricher {\n // Return partial data query request that will be merged with the original request provided by SceneQueryRunner\n enrichDataRequest(source: SceneObject): Partial<DataQueryRequest> | null;\n}\n\nexport interface FiltersRequestEnricher {\n // Return partial getTagKeys or getTagValues query request that will be merged with the original request provided by ad hoc or group by variable\n enrichFiltersRequest(\n source: SceneObject\n ): Partial<DataSourceGetTagKeysOptions | DataSourceGetTagValuesOptions> | null;\n}\n\nexport function isDataRequestEnricher(obj: any): obj is DataRequestEnricher {\n return 'enrichDataRequest' in obj;\n}\n\nexport function isFiltersRequestEnricher(obj: any): obj is FiltersRequestEnricher {\n return 'enrichFiltersRequest' in obj;\n}\n\nexport type SceneObjectUrlValue = string | string[] | undefined | null;\nexport type SceneObjectUrlValues = Record<string, SceneObjectUrlValue>;\n\nexport type CustomTransformOperator = (context: DataTransformContext) => MonoTypeOperatorFunction<DataFrame[]>;\nexport type CustomTransformerDefinition =\n | { operator: CustomTransformOperator; topic: DataTopic }\n | CustomTransformOperator;\nexport type SceneStateChangedHandler<TState> = (newState: TState, prevState: TState) => void;\n\nexport type DeepPartial<T> = {\n [K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K];\n};\n\nexport interface SceneDataProviderResult {\n data: PanelData;\n origin: SceneDataProvider;\n}\n\nexport interface SceneDataProvider<T extends SceneObjectState = SceneDataState> extends SceneObject<T> {\n setContainerWidth?: (width: number) => void;\n isDataReadyToDisplay?: () => boolean;\n cancelQuery?: () => void;\n getResultsStream(): Observable<SceneDataProviderResult>;\n}\n\nexport interface SceneDataLayerProviderState extends SceneDataState {\n name: string;\n description?: string;\n isEnabled?: boolean;\n isHidden?: boolean;\n}\n\nexport interface SceneDataLayerProvider extends SceneDataProvider<SceneDataLayerProviderState> {\n isDataLayer: true;\n}\n\nexport function isDataLayer(obj: SceneObject): obj is SceneDataLayerProvider {\n return 'isDataLayer' in obj;\n}\n\nexport interface DataLayerFilter {\n panelId: number;\n}\n\nexport interface SceneStatelessBehavior<T extends SceneObject = any> {\n (sceneObject: T): CancelActivationHandler | void;\n}\n\nexport type ControlsLayout = 'horizontal' | 'vertical';\n\nexport interface UseStateHookOptions {\n /**\n * For some edge cases other scene objects want to subscribe to scene object state for objects\n * that are not active, or whose main React Component can be un-mounted. Set this to true\n * to keep the scene object active even if the React component is unmounted.\n *\n * Normally you would not need this but this can be useful in some edge cases.\n *\n * @experimental\n */\n shouldActivateOrKeepAlive?: boolean;\n}\n\nexport interface SceneDataQuery extends DataQuery {\n [key: string]: any;\n\n // Opt this query out of time window comparison\n timeRangeCompare?: boolean;\n}\n\nexport interface SceneUrlSyncOptions {\n /**\n * This will update the url to contain all scene url state\n * when the scene is initialized. Important for browser history \"back\" actions.\n */\n updateUrlOnInit?: boolean;\n /**\n * This is only supported by some objects if they implement\n * shouldCreateHistoryStep where they can control what changes\n * url changes should add a new browser history entry.\n */\n createBrowserHistorySteps?: boolean;\n /**\n * This will automatically prefix url search parameters when syncing.\n * Can be used to prevent collisions when multiple Scene apps are embedded in the page.\n */\n namespace?: string;\n /**\n * When `namespace` is provided, this prevents some url search parameters to be automatically prefixed.\n * Defaults to the timerange parameters ([\"from\", \"to\", \"timezone\"])\n */\n excludeFromNamespace?: string[];\n}\n"],"names":[],"mappings":"AAyLO,SAAS,cAAc,GAA8B,EAAA;AAC1D,EAAA,OAAO,IAAI,QAAa,KAAA,MAAA;AAC1B;AA2BO,SAAS,sBAAsB,GAAsC,EAAA;AAC1E,EAAA,OAAO,mBAAuB,IAAA,GAAA;AAChC;AAEO,SAAS,yBAAyB,GAAyC,EAAA;AAChF,EAAA,OAAO,sBAA0B,IAAA,GAAA;AACnC;AAsCO,SAAS,YAAY,GAAiD,EAAA;AAC3E,EAAA,OAAO,aAAiB,IAAA,GAAA;AAC1B;;;;"}
|
@@ -1,10 +1,26 @@
|
|
1
1
|
import { sceneGraph } from '../core/sceneGraph/index.js';
|
2
2
|
|
3
|
+
const DEFAULT_NAMESPACE = "";
|
4
|
+
const DEFAULT_EXCLUDE_FROM_NAMESPACE = ["from", "to", "timezone"];
|
3
5
|
class UniqueUrlKeyMapper {
|
4
|
-
constructor() {
|
6
|
+
constructor(options) {
|
5
7
|
this.index = /* @__PURE__ */ new Map();
|
8
|
+
this.options = {
|
9
|
+
namespace: (options == null ? void 0 : options.namespace) || DEFAULT_NAMESPACE,
|
10
|
+
excludeFromNamespace: (options == null ? void 0 : options.excludeFromNamespace) || DEFAULT_EXCLUDE_FROM_NAMESPACE
|
11
|
+
};
|
6
12
|
}
|
7
|
-
|
13
|
+
getOptions() {
|
14
|
+
return this.options;
|
15
|
+
}
|
16
|
+
getNamespacedKey(keyWithoutNamespace) {
|
17
|
+
if (this.options.namespace && !this.options.excludeFromNamespace.includes(keyWithoutNamespace)) {
|
18
|
+
return `${this.options.namespace}-${keyWithoutNamespace}`;
|
19
|
+
}
|
20
|
+
return keyWithoutNamespace;
|
21
|
+
}
|
22
|
+
getUniqueKey(keyWithoutNamespace, obj) {
|
23
|
+
const key = this.getNamespacedKey(keyWithoutNamespace);
|
8
24
|
const objectsWithKey = this.index.get(key);
|
9
25
|
if (!objectsWithKey) {
|
10
26
|
this.index.set(key, [obj]);
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"UniqueUrlKeyMapper.js","sources":["../../../src/services/UniqueUrlKeyMapper.ts"],"sourcesContent":["import { sceneGraph } from '../core/sceneGraph';\nimport { SceneObject } from '../core/types';\n\nexport interface SceneObjectWithDepth {\n sceneObject: SceneObject;\n depth: number;\n}\n\nexport class UniqueUrlKeyMapper {\n private index = new Map<string, SceneObject[]>();\n\n public getUniqueKey(
|
1
|
+
{"version":3,"file":"UniqueUrlKeyMapper.js","sources":["../../../src/services/UniqueUrlKeyMapper.ts"],"sourcesContent":["import { sceneGraph } from '../core/sceneGraph';\nimport { SceneObject } from '../core/types';\n\nexport interface SceneObjectWithDepth {\n sceneObject: SceneObject;\n depth: number;\n}\n\nexport interface UniqueUrlKeyMapperOptions {\n namespace?: string;\n excludeFromNamespace?: string[];\n}\n\nconst DEFAULT_NAMESPACE = '';\nconst DEFAULT_EXCLUDE_FROM_NAMESPACE = ['from', 'to', 'timezone'];\n\nexport class UniqueUrlKeyMapper {\n private index = new Map<string, SceneObject[]>();\n private options: Required<UniqueUrlKeyMapperOptions>;\n\n public constructor(options?: UniqueUrlKeyMapperOptions) {\n this.options = {\n namespace: options?.namespace || DEFAULT_NAMESPACE,\n excludeFromNamespace: options?.excludeFromNamespace || DEFAULT_EXCLUDE_FROM_NAMESPACE,\n };\n }\n\n public getOptions() {\n return this.options;\n }\n\n private getNamespacedKey(keyWithoutNamespace: string) {\n if (this.options.namespace && !this.options.excludeFromNamespace.includes(keyWithoutNamespace)) {\n return `${this.options.namespace}-${keyWithoutNamespace}`;\n }\n return keyWithoutNamespace;\n }\n\n public getUniqueKey(keyWithoutNamespace: string, obj: SceneObject) {\n const key = this.getNamespacedKey(keyWithoutNamespace);\n const objectsWithKey = this.index.get(key);\n\n if (!objectsWithKey) {\n this.index.set(key, [obj]);\n return key;\n }\n\n let address = objectsWithKey.findIndex((o) => o === obj);\n if (address === -1) {\n filterOutOrphanedObjects(objectsWithKey);\n objectsWithKey.push(obj);\n\n address = objectsWithKey.length - 1;\n }\n\n if (address > 0) {\n return `${key}-${address + 1}`;\n }\n\n return key;\n }\n\n public clear() {\n this.index.clear();\n }\n}\n\nfunction filterOutOrphanedObjects(sceneObjects: SceneObject[]) {\n for (const obj of sceneObjects) {\n if (isOrphanOrInActive(obj)) {\n const index = sceneObjects.indexOf(obj);\n sceneObjects.splice(index, 1);\n }\n }\n}\n\nfunction isOrphanOrInActive(obj: SceneObject) {\n const root = obj.getRoot();\n\n // If we cannot find it from the root it's an orphan\n if (!sceneGraph.findObject(root, (child) => child === obj)) {\n return true;\n }\n\n return false;\n}\n"],"names":[],"mappings":";;AAaA,MAAM,iBAAoB,GAAA,EAAA;AAC1B,MAAM,8BAAiC,GAAA,CAAC,MAAQ,EAAA,IAAA,EAAM,UAAU,CAAA;AAEzD,MAAM,kBAAmB,CAAA;AAAA,EAIvB,YAAY,OAAqC,EAAA;AAHxD,IAAQ,IAAA,CAAA,KAAA,uBAAY,GAA2B,EAAA;AAI7C,IAAA,IAAA,CAAK,OAAU,GAAA;AAAA,MACb,SAAA,EAAA,CAAW,mCAAS,SAAa,KAAA,iBAAA;AAAA,MACjC,oBAAA,EAAA,CAAsB,mCAAS,oBAAwB,KAAA;AAAA,KACzD;AAAA;AACF,EAEO,UAAa,GAAA;AAClB,IAAA,OAAO,IAAK,CAAA,OAAA;AAAA;AACd,EAEQ,iBAAiB,mBAA6B,EAAA;AACpD,IAAI,IAAA,IAAA,CAAK,QAAQ,SAAa,IAAA,CAAC,KAAK,OAAQ,CAAA,oBAAA,CAAqB,QAAS,CAAA,mBAAmB,CAAG,EAAA;AAC9F,MAAA,OAAO,CAAG,EAAA,IAAA,CAAK,OAAQ,CAAA,SAAS,IAAI,mBAAmB,CAAA,CAAA;AAAA;AAEzD,IAAO,OAAA,mBAAA;AAAA;AACT,EAEO,YAAA,CAAa,qBAA6B,GAAkB,EAAA;AACjE,IAAM,MAAA,GAAA,GAAM,IAAK,CAAA,gBAAA,CAAiB,mBAAmB,CAAA;AACrD,IAAA,MAAM,cAAiB,GAAA,IAAA,CAAK,KAAM,CAAA,GAAA,CAAI,GAAG,CAAA;AAEzC,IAAA,IAAI,CAAC,cAAgB,EAAA;AACnB,MAAA,IAAA,CAAK,KAAM,CAAA,GAAA,CAAI,GAAK,EAAA,CAAC,GAAG,CAAC,CAAA;AACzB,MAAO,OAAA,GAAA;AAAA;AAGT,IAAA,IAAI,UAAU,cAAe,CAAA,SAAA,CAAU,CAAC,CAAA,KAAM,MAAM,GAAG,CAAA;AACvD,IAAA,IAAI,YAAY,EAAI,EAAA;AAClB,MAAA,wBAAA,CAAyB,cAAc,CAAA;AACvC,MAAA,cAAA,CAAe,KAAK,GAAG,CAAA;AAEvB,MAAA,OAAA,GAAU,eAAe,MAAS,GAAA,CAAA;AAAA;AAGpC,IAAA,IAAI,UAAU,CAAG,EAAA;AACf,MAAA,OAAO,CAAG,EAAA,GAAG,CAAI,CAAA,EAAA,OAAA,GAAU,CAAC,CAAA,CAAA;AAAA;AAG9B,IAAO,OAAA,GAAA;AAAA;AACT,EAEO,KAAQ,GAAA;AACb,IAAA,IAAA,CAAK,MAAM,KAAM,EAAA;AAAA;AAErB;AAEA,SAAS,yBAAyB,YAA6B,EAAA;AAC7D,EAAA,KAAA,MAAW,OAAO,YAAc,EAAA;AAC9B,IAAI,IAAA,kBAAA,CAAmB,GAAG,CAAG,EAAA;AAC3B,MAAM,MAAA,KAAA,GAAQ,YAAa,CAAA,OAAA,CAAQ,GAAG,CAAA;AACtC,MAAa,YAAA,CAAA,MAAA,CAAO,OAAO,CAAC,CAAA;AAAA;AAC9B;AAEJ;AAEA,SAAS,mBAAmB,GAAkB,EAAA;AAC5C,EAAM,MAAA,IAAA,GAAO,IAAI,OAAQ,EAAA;AAGzB,EAAI,IAAA,CAAC,WAAW,UAAW,CAAA,IAAA,EAAM,CAAC,KAAU,KAAA,KAAA,KAAU,GAAG,CAAG,EAAA;AAC1D,IAAO,OAAA,IAAA;AAAA;AAGT,EAAO,OAAA,KAAA;AACT;;;;"}
|
@@ -4,9 +4,16 @@ function UrlSyncContextProvider({
|
|
4
4
|
children,
|
5
5
|
scene,
|
6
6
|
updateUrlOnInit,
|
7
|
-
createBrowserHistorySteps
|
7
|
+
createBrowserHistorySteps,
|
8
|
+
namespace,
|
9
|
+
excludeFromNamespace
|
8
10
|
}) {
|
9
|
-
const isInitialized = useUrlSync(scene, {
|
11
|
+
const isInitialized = useUrlSync(scene, {
|
12
|
+
updateUrlOnInit,
|
13
|
+
createBrowserHistorySteps,
|
14
|
+
namespace,
|
15
|
+
excludeFromNamespace
|
16
|
+
});
|
10
17
|
if (!isInitialized) {
|
11
18
|
return null;
|
12
19
|
}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"UrlSyncContextProvider.js","sources":["../../../src/services/UrlSyncContextProvider.ts"],"sourcesContent":["import { SceneObject, SceneUrlSyncOptions } from '../core/types';\nimport { useUrlSync } from './useUrlSync';\n\nexport interface UrlSyncContextProviderProps extends SceneUrlSyncOptions {\n scene: SceneObject;\n children: React.ReactNode;\n}\n\n/**\n * Right now this is actually not defining a context, but think it might in the future (with UrlSyncManager as the context value)\n */\n\nexport function UrlSyncContextProvider({\n children,\n scene,\n updateUrlOnInit,\n createBrowserHistorySteps,\n}: UrlSyncContextProviderProps) {\n const isInitialized = useUrlSync(scene, {
|
1
|
+
{"version":3,"file":"UrlSyncContextProvider.js","sources":["../../../src/services/UrlSyncContextProvider.ts"],"sourcesContent":["import { SceneObject, SceneUrlSyncOptions } from '../core/types';\nimport { useUrlSync } from './useUrlSync';\n\nexport interface UrlSyncContextProviderProps extends SceneUrlSyncOptions {\n scene: SceneObject;\n children: React.ReactNode;\n}\n\n/**\n * Right now this is actually not defining a context, but think it might in the future (with UrlSyncManager as the context value)\n */\n\nexport function UrlSyncContextProvider({\n children,\n scene,\n updateUrlOnInit,\n createBrowserHistorySteps,\n namespace,\n excludeFromNamespace,\n}: UrlSyncContextProviderProps) {\n const isInitialized = useUrlSync(scene, {\n updateUrlOnInit,\n createBrowserHistorySteps,\n namespace,\n excludeFromNamespace,\n });\n\n if (!isInitialized) {\n return null;\n }\n\n return children;\n}\n"],"names":[],"mappings":";;AAYO,SAAS,sBAAuB,CAAA;AAAA,EACrC,QAAA;AAAA,EACA,KAAA;AAAA,EACA,eAAA;AAAA,EACA,yBAAA;AAAA,EACA,SAAA;AAAA,EACA;AACF,CAAgC,EAAA;AAC9B,EAAM,MAAA,aAAA,GAAgB,WAAW,KAAO,EAAA;AAAA,IACtC,eAAA;AAAA,IACA,yBAAA;AAAA,IACA,SAAA;AAAA,IACA;AAAA,GACD,CAAA;AAED,EAAA,IAAI,CAAC,aAAe,EAAA;AAClB,IAAO,OAAA,IAAA;AAAA;AAGT,EAAO,OAAA,QAAA;AACT;;;;"}
|
@@ -20,10 +20,13 @@ class NewSceneObjectAddedEvent extends BusEventWithPayload {
|
|
20
20
|
NewSceneObjectAddedEvent.type = "new-scene-object-added";
|
21
21
|
class UrlSyncManager {
|
22
22
|
constructor(_options = {}, locationService$1 = locationService) {
|
23
|
-
this._urlKeyMapper = new UniqueUrlKeyMapper();
|
24
23
|
this._options = _options;
|
25
24
|
this._locationService = locationService$1;
|
26
25
|
this._paramsCache = new UrlParamsCache(locationService$1);
|
26
|
+
this._urlKeyMapper = new UniqueUrlKeyMapper({
|
27
|
+
namespace: _options.namespace,
|
28
|
+
excludeFromNamespace: _options.excludeFromNamespace
|
29
|
+
});
|
27
30
|
}
|
28
31
|
/**
|
29
32
|
* Updates the current scene state to match URL state.
|
@@ -51,7 +54,7 @@ class UrlSyncManager {
|
|
51
54
|
this._lastLocation = this._locationService.getLocation();
|
52
55
|
this.handleNewObject(this._sceneRoot);
|
53
56
|
if (this._options.updateUrlOnInit) {
|
54
|
-
const urlState = getUrlState(root);
|
57
|
+
const urlState = getUrlState(root, this._urlKeyMapper.getOptions());
|
55
58
|
if (isUrlStateDifferent(urlState, this._paramsCache.getParams())) {
|
56
59
|
this._locationService.partial(urlState, true);
|
57
60
|
}
|
@@ -113,7 +116,7 @@ class UrlSyncManager {
|
|
113
116
|
}
|
114
117
|
}
|
115
118
|
getUrlState(root) {
|
116
|
-
return getUrlState(root);
|
119
|
+
return getUrlState(root, this._urlKeyMapper.getOptions());
|
117
120
|
}
|
118
121
|
}
|
119
122
|
class UrlParamsCache {
|
@@ -147,11 +150,19 @@ function useUrlSyncManager(options, locationService) {
|
|
147
150
|
() => new UrlSyncManager(
|
148
151
|
{
|
149
152
|
updateUrlOnInit: options.updateUrlOnInit,
|
150
|
-
createBrowserHistorySteps: options.createBrowserHistorySteps
|
153
|
+
createBrowserHistorySteps: options.createBrowserHistorySteps,
|
154
|
+
namespace: options.namespace,
|
155
|
+
excludeFromNamespace: options.excludeFromNamespace
|
151
156
|
},
|
152
157
|
locationService
|
153
158
|
),
|
154
|
-
[
|
159
|
+
[
|
160
|
+
options.updateUrlOnInit,
|
161
|
+
options.createBrowserHistorySteps,
|
162
|
+
options.namespace,
|
163
|
+
options.excludeFromNamespace,
|
164
|
+
locationService
|
165
|
+
]
|
155
166
|
);
|
156
167
|
}
|
157
168
|
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"UrlSyncManager.js","sources":["../../../src/services/UrlSyncManager.ts"],"sourcesContent":["import { Location } from 'history';\n\nimport { LocationService, locationService as locationServiceRuntime } from '@grafana/runtime';\n\nimport { SceneObjectStateChangedEvent } from '../core/events';\nimport { SceneObject, SceneObjectUrlValues, SceneUrlSyncOptions } from '../core/types';\nimport { writeSceneLog } from '../utils/writeSceneLog';\nimport { Subscription } from 'rxjs';\nimport { UniqueUrlKeyMapper } from './UniqueUrlKeyMapper';\nimport { getUrlState, isUrlValueEqual, syncStateFromUrl } from './utils';\nimport { BusEventWithPayload } from '@grafana/data';\nimport { useMemo } from 'react';\n\nexport interface UrlSyncManagerLike {\n initSync(root: SceneObject): void;\n cleanUp(root: SceneObject): void;\n handleNewLocation(location: Location): void;\n handleNewObject(sceneObj: SceneObject): void;\n}\n\n/**\n * Notify the url sync manager of a new object that has been added to the scene\n * that needs to init state from URL.\n */\nexport class NewSceneObjectAddedEvent extends BusEventWithPayload<SceneObject> {\n public static readonly type = 'new-scene-object-added';\n}\n\nexport class UrlSyncManager implements UrlSyncManagerLike {\n private _urlKeyMapper = new UniqueUrlKeyMapper();\n private _sceneRoot?: SceneObject;\n private _subs: Subscription | undefined;\n private _lastLocation: Location | undefined;\n private _locationService: LocationService;\n private _paramsCache: UrlParamsCache;\n private _options: SceneUrlSyncOptions;\n\n public constructor(_options: SceneUrlSyncOptions = {}, locationService: LocationService = locationServiceRuntime) {\n this._options = _options;\n this._locationService = locationService;\n this._paramsCache = new UrlParamsCache(locationService);\n }\n\n /**\n * Updates the current scene state to match URL state.\n */\n public initSync(root: SceneObject) {\n if (this._subs) {\n writeSceneLog('UrlSyncManager', 'Unregister previous scene state subscription', this._sceneRoot?.state.key);\n this._subs.unsubscribe();\n }\n\n writeSceneLog('UrlSyncManager', 'init', root.state.key);\n\n this._sceneRoot = root;\n this._subs = new Subscription();\n\n this._subs.add(\n root.subscribeToEvent(SceneObjectStateChangedEvent, (evt) => {\n this.handleSceneObjectStateChanged(evt.payload.changedObject);\n })\n );\n\n this._subs.add(\n root.subscribeToEvent(NewSceneObjectAddedEvent, (evt) => {\n this.handleNewObject(evt.payload);\n })\n );\n\n this._urlKeyMapper.clear();\n this._lastLocation = this._locationService.getLocation();\n\n // Sync current url with state\n this.handleNewObject(this._sceneRoot);\n\n if (this._options.updateUrlOnInit) {\n // Get current url state and update url to match\n const urlState = getUrlState(root);\n\n if (isUrlStateDifferent(urlState, this._paramsCache.getParams())) {\n this._locationService.partial(urlState, true);\n }\n }\n }\n\n public cleanUp(root: SceneObject) {\n // Ignore this if we have a new or different root\n if (this._sceneRoot !== root) {\n return;\n }\n\n writeSceneLog('UrlSyncManager', 'Clean up');\n\n if (this._subs) {\n this._subs.unsubscribe();\n this._subs = undefined;\n\n writeSceneLog(\n 'UrlSyncManager',\n 'Root deactived, unsub to state',\n 'same key',\n this._sceneRoot.state.key === root.state.key\n );\n }\n\n this._sceneRoot = undefined;\n this._lastLocation = undefined;\n }\n\n public handleNewLocation(location: Location) {\n if (!this._sceneRoot || this._lastLocation === location) {\n return;\n }\n\n writeSceneLog('UrlSyncManager', 'handleNewLocation');\n\n this._lastLocation = location;\n\n // Sync scene state tree from url\n syncStateFromUrl(this._sceneRoot!, this._paramsCache.getParams(), this._urlKeyMapper);\n }\n\n public handleNewObject(sceneObj: SceneObject) {\n if (!this._sceneRoot) {\n return;\n }\n\n syncStateFromUrl(sceneObj, this._paramsCache.getParams(), this._urlKeyMapper);\n }\n\n private handleSceneObjectStateChanged(changedObject: SceneObject) {\n if (!changedObject.urlSync) {\n return;\n }\n\n const newUrlState = changedObject.urlSync.getUrlState();\n\n const searchParams = this._locationService.getSearch();\n const mappedUpdated: SceneObjectUrlValues = {};\n\n for (const [key, newUrlValue] of Object.entries(newUrlState)) {\n const uniqueKey = this._urlKeyMapper.getUniqueKey(key, changedObject);\n const currentUrlValue = searchParams.getAll(uniqueKey);\n\n if (!isUrlValueEqual(currentUrlValue, newUrlValue)) {\n mappedUpdated[uniqueKey] = newUrlValue;\n }\n }\n\n if (Object.keys(mappedUpdated).length > 0) {\n const shouldCreateHistoryEntry = changedObject.urlSync.shouldCreateHistoryStep?.(newUrlState);\n const shouldReplace = shouldCreateHistoryEntry !== true;\n\n writeSceneLog('UrlSyncManager', 'onStateChange updating URL');\n this._locationService.partial(mappedUpdated, shouldReplace);\n\n /// Mark the location already handled\n this._lastLocation = this._locationService.getLocation();\n }\n }\n\n public getUrlState(root: SceneObject): SceneObjectUrlValues {\n return getUrlState(root);\n }\n}\n\nclass UrlParamsCache {\n #cache: URLSearchParams | undefined;\n #location: Location | undefined;\n\n public constructor(private locationService: LocationService) {}\n\n public getParams(): URLSearchParams {\n const location = this.locationService.getLocation();\n\n if (this.#location === location) {\n return this.#cache!;\n }\n\n this.#location = location;\n this.#cache = new URLSearchParams(location.search);\n\n return this.#cache;\n }\n}\n\nfunction isUrlStateDifferent(sceneUrlState: SceneObjectUrlValues, currentParams: URLSearchParams) {\n for (let key in sceneUrlState) {\n if (!isUrlValueEqual(currentParams.getAll(key), sceneUrlState[key])) {\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * Creates a new memoized instance of the UrlSyncManager based on options\n */\nexport function useUrlSyncManager(options: SceneUrlSyncOptions, locationService: LocationService): UrlSyncManagerLike {\n return useMemo(\n () =>\n new UrlSyncManager(\n {\n updateUrlOnInit: options.updateUrlOnInit,\n createBrowserHistorySteps: options.createBrowserHistorySteps,\n },\n locationService\n ),\n [options.updateUrlOnInit, options.createBrowserHistorySteps, locationService]\n );\n}\n"],"names":["locationService","locationServiceRuntime"],"mappings":"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"}
|
1
|
+
{"version":3,"file":"UrlSyncManager.js","sources":["../../../src/services/UrlSyncManager.ts"],"sourcesContent":["import { Location } from 'history';\n\nimport { LocationService, locationService as locationServiceRuntime } from '@grafana/runtime';\n\nimport { SceneObjectStateChangedEvent } from '../core/events';\nimport { SceneObject, SceneObjectUrlValues, SceneUrlSyncOptions } from '../core/types';\nimport { writeSceneLog } from '../utils/writeSceneLog';\nimport { Subscription } from 'rxjs';\nimport { UniqueUrlKeyMapper } from './UniqueUrlKeyMapper';\nimport { getUrlState, isUrlValueEqual, syncStateFromUrl } from './utils';\nimport { BusEventWithPayload } from '@grafana/data';\nimport { useMemo } from 'react';\n\nexport interface UrlSyncManagerLike {\n initSync(root: SceneObject): void;\n cleanUp(root: SceneObject): void;\n handleNewLocation(location: Location): void;\n handleNewObject(sceneObj: SceneObject): void;\n}\n\n/**\n * Notify the url sync manager of a new object that has been added to the scene\n * that needs to init state from URL.\n */\nexport class NewSceneObjectAddedEvent extends BusEventWithPayload<SceneObject> {\n public static readonly type = 'new-scene-object-added';\n}\n\nexport class UrlSyncManager implements UrlSyncManagerLike {\n private _urlKeyMapper: UniqueUrlKeyMapper;\n private _sceneRoot?: SceneObject;\n private _subs: Subscription | undefined;\n private _lastLocation: Location | undefined;\n private _locationService: LocationService;\n private _paramsCache: UrlParamsCache;\n private _options: SceneUrlSyncOptions;\n\n public constructor(_options: SceneUrlSyncOptions = {}, locationService: LocationService = locationServiceRuntime) {\n this._options = _options;\n this._locationService = locationService;\n this._paramsCache = new UrlParamsCache(locationService);\n\n this._urlKeyMapper = new UniqueUrlKeyMapper({\n namespace: _options.namespace,\n excludeFromNamespace: _options.excludeFromNamespace,\n });\n }\n\n /**\n * Updates the current scene state to match URL state.\n */\n public initSync(root: SceneObject) {\n if (this._subs) {\n writeSceneLog('UrlSyncManager', 'Unregister previous scene state subscription', this._sceneRoot?.state.key);\n this._subs.unsubscribe();\n }\n\n writeSceneLog('UrlSyncManager', 'init', root.state.key);\n\n this._sceneRoot = root;\n this._subs = new Subscription();\n\n this._subs.add(\n root.subscribeToEvent(SceneObjectStateChangedEvent, (evt) => {\n this.handleSceneObjectStateChanged(evt.payload.changedObject);\n })\n );\n\n this._subs.add(\n root.subscribeToEvent(NewSceneObjectAddedEvent, (evt) => {\n this.handleNewObject(evt.payload);\n })\n );\n\n this._urlKeyMapper.clear();\n this._lastLocation = this._locationService.getLocation();\n\n // Sync current url with state\n this.handleNewObject(this._sceneRoot);\n\n if (this._options.updateUrlOnInit) {\n // Get current url state and update url to match\n const urlState = getUrlState(root, this._urlKeyMapper.getOptions());\n\n if (isUrlStateDifferent(urlState, this._paramsCache.getParams())) {\n this._locationService.partial(urlState, true);\n }\n }\n }\n\n public cleanUp(root: SceneObject) {\n // Ignore this if we have a new or different root\n if (this._sceneRoot !== root) {\n return;\n }\n\n writeSceneLog('UrlSyncManager', 'Clean up');\n\n if (this._subs) {\n this._subs.unsubscribe();\n this._subs = undefined;\n\n writeSceneLog(\n 'UrlSyncManager',\n 'Root deactived, unsub to state',\n 'same key',\n this._sceneRoot.state.key === root.state.key\n );\n }\n\n this._sceneRoot = undefined;\n this._lastLocation = undefined;\n }\n\n public handleNewLocation(location: Location) {\n if (!this._sceneRoot || this._lastLocation === location) {\n return;\n }\n\n writeSceneLog('UrlSyncManager', 'handleNewLocation');\n\n this._lastLocation = location;\n\n // Sync scene state tree from url\n syncStateFromUrl(this._sceneRoot!, this._paramsCache.getParams(), this._urlKeyMapper);\n }\n\n public handleNewObject(sceneObj: SceneObject) {\n if (!this._sceneRoot) {\n return;\n }\n\n syncStateFromUrl(sceneObj, this._paramsCache.getParams(), this._urlKeyMapper);\n }\n\n private handleSceneObjectStateChanged(changedObject: SceneObject) {\n if (!changedObject.urlSync) {\n return;\n }\n\n const newUrlState = changedObject.urlSync.getUrlState();\n\n const searchParams = this._locationService.getSearch();\n const mappedUpdated: SceneObjectUrlValues = {};\n\n for (const [key, newUrlValue] of Object.entries(newUrlState)) {\n const uniqueKey = this._urlKeyMapper.getUniqueKey(key, changedObject);\n const currentUrlValue = searchParams.getAll(uniqueKey);\n\n if (!isUrlValueEqual(currentUrlValue, newUrlValue)) {\n mappedUpdated[uniqueKey] = newUrlValue;\n }\n }\n\n if (Object.keys(mappedUpdated).length > 0) {\n const shouldCreateHistoryEntry = changedObject.urlSync.shouldCreateHistoryStep?.(newUrlState);\n const shouldReplace = shouldCreateHistoryEntry !== true;\n\n writeSceneLog('UrlSyncManager', 'onStateChange updating URL');\n this._locationService.partial(mappedUpdated, shouldReplace);\n\n /// Mark the location already handled\n this._lastLocation = this._locationService.getLocation();\n }\n }\n\n public getUrlState(root: SceneObject): SceneObjectUrlValues {\n return getUrlState(root, this._urlKeyMapper.getOptions());\n }\n}\n\nclass UrlParamsCache {\n #cache: URLSearchParams | undefined;\n #location: Location | undefined;\n\n public constructor(private locationService: LocationService) {}\n\n public getParams(): URLSearchParams {\n const location = this.locationService.getLocation();\n\n if (this.#location === location) {\n return this.#cache!;\n }\n\n this.#location = location;\n this.#cache = new URLSearchParams(location.search);\n\n return this.#cache;\n }\n}\n\nfunction isUrlStateDifferent(sceneUrlState: SceneObjectUrlValues, currentParams: URLSearchParams) {\n for (let key in sceneUrlState) {\n if (!isUrlValueEqual(currentParams.getAll(key), sceneUrlState[key])) {\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * Creates a new memoized instance of the UrlSyncManager based on options\n */\nexport function useUrlSyncManager(options: SceneUrlSyncOptions, locationService: LocationService): UrlSyncManagerLike {\n return useMemo(\n () =>\n new UrlSyncManager(\n {\n updateUrlOnInit: options.updateUrlOnInit,\n createBrowserHistorySteps: options.createBrowserHistorySteps,\n namespace: options.namespace,\n excludeFromNamespace: options.excludeFromNamespace,\n },\n locationService\n ),\n [\n options.updateUrlOnInit,\n options.createBrowserHistorySteps,\n options.namespace,\n options.excludeFromNamespace,\n locationService,\n ]\n );\n}\n"],"names":["locationService","locationServiceRuntime"],"mappings":"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"}
|
@@ -1,8 +1,8 @@
|
|
1
1
|
import { isEqual } from 'lodash';
|
2
2
|
import { UniqueUrlKeyMapper } from './UniqueUrlKeyMapper.js';
|
3
3
|
|
4
|
-
function getUrlState(root) {
|
5
|
-
const urlKeyMapper = new UniqueUrlKeyMapper();
|
4
|
+
function getUrlState(root, uniqueUrlKeyMapperOptions) {
|
5
|
+
const urlKeyMapper = new UniqueUrlKeyMapper(uniqueUrlKeyMapperOptions);
|
6
6
|
const result = {};
|
7
7
|
const visitNode = (obj) => {
|
8
8
|
if (obj.urlSync) {
|
@@ -19,8 +19,8 @@ function getUrlState(root) {
|
|
19
19
|
visitNode(root);
|
20
20
|
return result;
|
21
21
|
}
|
22
|
-
function syncStateFromSearchParams(root, urlParams) {
|
23
|
-
const urlKeyMapper = new UniqueUrlKeyMapper();
|
22
|
+
function syncStateFromSearchParams(root, urlParams, uniqueUrlKeyMapperOptions) {
|
23
|
+
const urlKeyMapper = new UniqueUrlKeyMapper(uniqueUrlKeyMapperOptions);
|
24
24
|
syncStateFromUrl(root, urlParams, urlKeyMapper);
|
25
25
|
}
|
26
26
|
function syncStateFromUrl(root, urlParams, urlKeyMapper, onlyChildren) {
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"utils.js","sources":["../../../src/services/utils.ts"],"sourcesContent":["import { isEqual } from 'lodash';\n\nimport { SceneObject, SceneObjectUrlValue, SceneObjectUrlValues } from '../core/types';\nimport { UniqueUrlKeyMapper } from './UniqueUrlKeyMapper';\n\n/**\n * @param root\n * @returns the full scene url state as a object with keys and values\n */\nexport function getUrlState(root: SceneObject): SceneObjectUrlValues {\n const urlKeyMapper = new UniqueUrlKeyMapper();\n const result: SceneObjectUrlValues = {};\n\n const visitNode = (obj: SceneObject) => {\n if (obj.urlSync) {\n const newUrlState = obj.urlSync.getUrlState();\n\n for (const [key, value] of Object.entries(newUrlState)) {\n if (value != null) {\n const uniqueKey = urlKeyMapper.getUniqueKey(key, obj);\n result[uniqueKey] = value;\n }\n }\n }\n\n obj.forEachChild(visitNode);\n };\n\n visitNode(root);\n return result;\n}\n\n/**\n * Exported util function to sync state from an initial url state.\n * Useful for initializing an embedded scenes with a url state string.\n */\nexport function syncStateFromSearchParams(root: SceneObject
|
1
|
+
{"version":3,"file":"utils.js","sources":["../../../src/services/utils.ts"],"sourcesContent":["import { isEqual } from 'lodash';\n\nimport { SceneObject, SceneObjectUrlValue, SceneObjectUrlValues } from '../core/types';\nimport { UniqueUrlKeyMapper, UniqueUrlKeyMapperOptions } from './UniqueUrlKeyMapper';\n\n/**\n * @param root\n * @returns the full scene url state as a object with keys and values\n */\nexport function getUrlState(\n root: SceneObject,\n uniqueUrlKeyMapperOptions?: UniqueUrlKeyMapperOptions\n): SceneObjectUrlValues {\n const urlKeyMapper = new UniqueUrlKeyMapper(uniqueUrlKeyMapperOptions);\n const result: SceneObjectUrlValues = {};\n\n const visitNode = (obj: SceneObject) => {\n if (obj.urlSync) {\n const newUrlState = obj.urlSync.getUrlState();\n\n for (const [key, value] of Object.entries(newUrlState)) {\n if (value != null) {\n const uniqueKey = urlKeyMapper.getUniqueKey(key, obj);\n result[uniqueKey] = value;\n }\n }\n }\n\n obj.forEachChild(visitNode);\n };\n\n visitNode(root);\n return result;\n}\n\n/**\n * Exported util function to sync state from an initial url state.\n * Useful for initializing an embedded scenes with a url state string.\n */\nexport function syncStateFromSearchParams(\n root: SceneObject,\n urlParams: URLSearchParams,\n uniqueUrlKeyMapperOptions?: UniqueUrlKeyMapperOptions\n) {\n const urlKeyMapper = new UniqueUrlKeyMapper(uniqueUrlKeyMapperOptions);\n syncStateFromUrl(root, urlParams, urlKeyMapper);\n}\n\nexport function syncStateFromUrl(\n root: SceneObject,\n urlParams: URLSearchParams,\n urlKeyMapper: UniqueUrlKeyMapper,\n onlyChildren?: boolean\n) {\n if (!onlyChildren) {\n syncUrlStateToObject(root, urlParams, urlKeyMapper);\n }\n\n // These two forEachChild loops might look strange but it's to make sure we walk through the scene graph one level at a time as url key conflicts depend depth in the scene tree\n root.forEachChild((child) => {\n syncUrlStateToObject(child, urlParams, urlKeyMapper);\n });\n\n root.forEachChild((child) => syncStateFromUrl(child, urlParams, urlKeyMapper, true));\n}\n\nfunction syncUrlStateToObject(sceneObject: SceneObject, urlParams: URLSearchParams, urlKeyMapper: UniqueUrlKeyMapper) {\n if (sceneObject.urlSync) {\n const urlState: SceneObjectUrlValues = {};\n const currentState = sceneObject.urlSync.getUrlState();\n\n for (const key of sceneObject.urlSync.getKeys()) {\n const uniqueKey = urlKeyMapper.getUniqueKey(key, sceneObject);\n const newValue = urlParams.getAll(uniqueKey);\n const currentValue = currentState[key];\n\n if (isUrlValueEqual(newValue, currentValue)) {\n continue;\n }\n\n if (newValue.length > 0) {\n if (Array.isArray(currentValue)) {\n urlState[key] = newValue;\n } else {\n urlState[key] = newValue[0];\n }\n } else {\n // mark this key as having no url state\n urlState[key] = null;\n }\n }\n\n if (Object.keys(urlState).length > 0) {\n sceneObject.urlSync.updateFromUrl(urlState);\n }\n }\n}\n\nexport function isUrlValueEqual(currentUrlValue: string[], newUrlValue: SceneObjectUrlValue): boolean {\n if (currentUrlValue.length === 0 && newUrlValue == null) {\n return true;\n }\n\n if (!Array.isArray(newUrlValue) && currentUrlValue?.length === 1) {\n return newUrlValue === currentUrlValue[0];\n }\n\n if (newUrlValue?.length === 0 && currentUrlValue === null) {\n return true;\n }\n\n // We have two arrays, lets compare them\n return isEqual(currentUrlValue, newUrlValue);\n}\n"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
@@ -638,6 +638,16 @@ interface SceneUrlSyncOptions {
|
|
638
638
|
* url changes should add a new browser history entry.
|
639
639
|
*/
|
640
640
|
createBrowserHistorySteps?: boolean;
|
641
|
+
/**
|
642
|
+
* This will automatically prefix url search parameters when syncing.
|
643
|
+
* Can be used to prevent collisions when multiple Scene apps are embedded in the page.
|
644
|
+
*/
|
645
|
+
namespace?: string;
|
646
|
+
/**
|
647
|
+
* When `namespace` is provided, this prevents some url search parameters to be automatically prefixed.
|
648
|
+
* Defaults to the timerange parameters (["from", "to", "timezone"])
|
649
|
+
*/
|
650
|
+
excludeFromNamespace?: string[];
|
641
651
|
}
|
642
652
|
|
643
653
|
interface EmbeddedSceneState extends SceneObjectState {
|
@@ -773,16 +783,21 @@ interface RuntimeDataSourceOptions {
|
|
773
783
|
*/
|
774
784
|
declare function registerRuntimeDataSource({ dataSource }: RuntimeDataSourceOptions): void;
|
775
785
|
|
786
|
+
interface UniqueUrlKeyMapperOptions {
|
787
|
+
namespace?: string;
|
788
|
+
excludeFromNamespace?: string[];
|
789
|
+
}
|
790
|
+
|
776
791
|
/**
|
777
792
|
* @param root
|
778
793
|
* @returns the full scene url state as a object with keys and values
|
779
794
|
*/
|
780
|
-
declare function getUrlState(root: SceneObject): SceneObjectUrlValues;
|
795
|
+
declare function getUrlState(root: SceneObject, uniqueUrlKeyMapperOptions?: UniqueUrlKeyMapperOptions): SceneObjectUrlValues;
|
781
796
|
/**
|
782
797
|
* Exported util function to sync state from an initial url state.
|
783
798
|
* Useful for initializing an embedded scenes with a url state string.
|
784
799
|
*/
|
785
|
-
declare function syncStateFromSearchParams(root: SceneObject, urlParams: URLSearchParams): void;
|
800
|
+
declare function syncStateFromSearchParams(root: SceneObject, urlParams: URLSearchParams, uniqueUrlKeyMapperOptions?: UniqueUrlKeyMapperOptions): void;
|
786
801
|
|
787
802
|
interface FormatRegistryItem extends RegistryItem {
|
788
803
|
formatter(value: VariableValue, args: string[], variable: FormatVariable): string;
|
@@ -2052,7 +2067,7 @@ interface UrlSyncContextProviderProps extends SceneUrlSyncOptions {
|
|
2052
2067
|
/**
|
2053
2068
|
* Right now this is actually not defining a context, but think it might in the future (with UrlSyncManager as the context value)
|
2054
2069
|
*/
|
2055
|
-
declare function UrlSyncContextProvider({ children, scene, updateUrlOnInit, createBrowserHistorySteps, }: UrlSyncContextProviderProps): React$1.ReactNode;
|
2070
|
+
declare function UrlSyncContextProvider({ children, scene, updateUrlOnInit, createBrowserHistorySteps, namespace, excludeFromNamespace, }: UrlSyncContextProviderProps): React$1.ReactNode;
|
2056
2071
|
|
2057
2072
|
interface ExploreButtonOptions {
|
2058
2073
|
onClick?: () => void;
|
package/dist/index.js
CHANGED
@@ -7578,11 +7578,27 @@ const sceneGraph = {
|
|
7578
7578
|
getScopes
|
7579
7579
|
};
|
7580
7580
|
|
7581
|
+
const DEFAULT_NAMESPACE = "";
|
7582
|
+
const DEFAULT_EXCLUDE_FROM_NAMESPACE = ["from", "to", "timezone"];
|
7581
7583
|
class UniqueUrlKeyMapper {
|
7582
|
-
constructor() {
|
7584
|
+
constructor(options) {
|
7583
7585
|
this.index = /* @__PURE__ */ new Map();
|
7586
|
+
this.options = {
|
7587
|
+
namespace: (options == null ? void 0 : options.namespace) || DEFAULT_NAMESPACE,
|
7588
|
+
excludeFromNamespace: (options == null ? void 0 : options.excludeFromNamespace) || DEFAULT_EXCLUDE_FROM_NAMESPACE
|
7589
|
+
};
|
7590
|
+
}
|
7591
|
+
getOptions() {
|
7592
|
+
return this.options;
|
7593
|
+
}
|
7594
|
+
getNamespacedKey(keyWithoutNamespace) {
|
7595
|
+
if (this.options.namespace && !this.options.excludeFromNamespace.includes(keyWithoutNamespace)) {
|
7596
|
+
return `${this.options.namespace}-${keyWithoutNamespace}`;
|
7597
|
+
}
|
7598
|
+
return keyWithoutNamespace;
|
7584
7599
|
}
|
7585
|
-
getUniqueKey(
|
7600
|
+
getUniqueKey(keyWithoutNamespace, obj) {
|
7601
|
+
const key = this.getNamespacedKey(keyWithoutNamespace);
|
7586
7602
|
const objectsWithKey = this.index.get(key);
|
7587
7603
|
if (!objectsWithKey) {
|
7588
7604
|
this.index.set(key, [obj]);
|
@@ -7619,8 +7635,8 @@ function isOrphanOrInActive(obj) {
|
|
7619
7635
|
return false;
|
7620
7636
|
}
|
7621
7637
|
|
7622
|
-
function getUrlState(root) {
|
7623
|
-
const urlKeyMapper = new UniqueUrlKeyMapper();
|
7638
|
+
function getUrlState(root, uniqueUrlKeyMapperOptions) {
|
7639
|
+
const urlKeyMapper = new UniqueUrlKeyMapper(uniqueUrlKeyMapperOptions);
|
7624
7640
|
const result = {};
|
7625
7641
|
const visitNode = (obj) => {
|
7626
7642
|
if (obj.urlSync) {
|
@@ -7637,8 +7653,8 @@ function getUrlState(root) {
|
|
7637
7653
|
visitNode(root);
|
7638
7654
|
return result;
|
7639
7655
|
}
|
7640
|
-
function syncStateFromSearchParams(root, urlParams) {
|
7641
|
-
const urlKeyMapper = new UniqueUrlKeyMapper();
|
7656
|
+
function syncStateFromSearchParams(root, urlParams, uniqueUrlKeyMapperOptions) {
|
7657
|
+
const urlKeyMapper = new UniqueUrlKeyMapper(uniqueUrlKeyMapperOptions);
|
7642
7658
|
syncStateFromUrl(root, urlParams, urlKeyMapper);
|
7643
7659
|
}
|
7644
7660
|
function syncStateFromUrl(root, urlParams, urlKeyMapper, onlyChildren) {
|
@@ -10500,10 +10516,13 @@ class NewSceneObjectAddedEvent extends data.BusEventWithPayload {
|
|
10500
10516
|
NewSceneObjectAddedEvent.type = "new-scene-object-added";
|
10501
10517
|
class UrlSyncManager {
|
10502
10518
|
constructor(_options = {}, locationService = runtime.locationService) {
|
10503
|
-
this._urlKeyMapper = new UniqueUrlKeyMapper();
|
10504
10519
|
this._options = _options;
|
10505
10520
|
this._locationService = locationService;
|
10506
10521
|
this._paramsCache = new UrlParamsCache(locationService);
|
10522
|
+
this._urlKeyMapper = new UniqueUrlKeyMapper({
|
10523
|
+
namespace: _options.namespace,
|
10524
|
+
excludeFromNamespace: _options.excludeFromNamespace
|
10525
|
+
});
|
10507
10526
|
}
|
10508
10527
|
/**
|
10509
10528
|
* Updates the current scene state to match URL state.
|
@@ -10531,7 +10550,7 @@ class UrlSyncManager {
|
|
10531
10550
|
this._lastLocation = this._locationService.getLocation();
|
10532
10551
|
this.handleNewObject(this._sceneRoot);
|
10533
10552
|
if (this._options.updateUrlOnInit) {
|
10534
|
-
const urlState = getUrlState(root);
|
10553
|
+
const urlState = getUrlState(root, this._urlKeyMapper.getOptions());
|
10535
10554
|
if (isUrlStateDifferent(urlState, this._paramsCache.getParams())) {
|
10536
10555
|
this._locationService.partial(urlState, true);
|
10537
10556
|
}
|
@@ -10593,7 +10612,7 @@ class UrlSyncManager {
|
|
10593
10612
|
}
|
10594
10613
|
}
|
10595
10614
|
getUrlState(root) {
|
10596
|
-
return getUrlState(root);
|
10615
|
+
return getUrlState(root, this._urlKeyMapper.getOptions());
|
10597
10616
|
}
|
10598
10617
|
}
|
10599
10618
|
class UrlParamsCache {
|
@@ -10627,11 +10646,19 @@ function useUrlSyncManager(options, locationService) {
|
|
10627
10646
|
() => new UrlSyncManager(
|
10628
10647
|
{
|
10629
10648
|
updateUrlOnInit: options.updateUrlOnInit,
|
10630
|
-
createBrowserHistorySteps: options.createBrowserHistorySteps
|
10649
|
+
createBrowserHistorySteps: options.createBrowserHistorySteps,
|
10650
|
+
namespace: options.namespace,
|
10651
|
+
excludeFromNamespace: options.excludeFromNamespace
|
10631
10652
|
},
|
10632
10653
|
locationService
|
10633
10654
|
),
|
10634
|
-
[
|
10655
|
+
[
|
10656
|
+
options.updateUrlOnInit,
|
10657
|
+
options.createBrowserHistorySteps,
|
10658
|
+
options.namespace,
|
10659
|
+
options.excludeFromNamespace,
|
10660
|
+
locationService
|
10661
|
+
]
|
10635
10662
|
);
|
10636
10663
|
}
|
10637
10664
|
|
@@ -10660,9 +10687,16 @@ function UrlSyncContextProvider({
|
|
10660
10687
|
children,
|
10661
10688
|
scene,
|
10662
10689
|
updateUrlOnInit,
|
10663
|
-
createBrowserHistorySteps
|
10690
|
+
createBrowserHistorySteps,
|
10691
|
+
namespace,
|
10692
|
+
excludeFromNamespace
|
10664
10693
|
}) {
|
10665
|
-
const isInitialized = useUrlSync(scene, {
|
10694
|
+
const isInitialized = useUrlSync(scene, {
|
10695
|
+
updateUrlOnInit,
|
10696
|
+
createBrowserHistorySteps,
|
10697
|
+
namespace,
|
10698
|
+
excludeFromNamespace
|
10699
|
+
});
|
10666
10700
|
if (!isInitialized) {
|
10667
10701
|
return null;
|
10668
10702
|
}
|