@grafana/scenes 0.0.28 → 0.0.29
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/CHANGELOG.md +144 -7
- package/dist/esm/components/EmbeddedScene.js +3 -11
- package/dist/esm/components/EmbeddedScene.js.map +1 -1
- package/dist/esm/core/SceneTimeRange.js +3 -0
- package/dist/esm/core/SceneTimeRange.js.map +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/services/UrlSyncManager.js +9 -18
- package/dist/esm/services/UrlSyncManager.js.map +1 -1
- package/dist/esm/variables/interpolation/ScopedVarsVariable.js.map +1 -1
- package/dist/esm/variables/interpolation/sceneInterpolator.js +15 -8
- package/dist/esm/variables/interpolation/sceneInterpolator.js.map +1 -1
- package/dist/esm/variables/lookupVariable.js.map +1 -1
- package/dist/esm/variables/macros/AllVariablesMacro.js +50 -0
- package/dist/esm/variables/macros/AllVariablesMacro.js.map +1 -0
- package/dist/esm/variables/macros/UrlTimeRangeMacro.js +32 -0
- package/dist/esm/variables/macros/UrlTimeRangeMacro.js.map +1 -0
- package/dist/esm/variables/macros/index.js +11 -0
- package/dist/esm/variables/macros/index.js.map +1 -0
- package/dist/esm/variables/macros/types.js +11 -0
- package/dist/esm/variables/macros/types.js.map +1 -0
- package/dist/esm/variables/types.js +4 -1
- package/dist/esm/variables/types.js.map +1 -1
- package/dist/esm/variables/variants/ConstantVariable.js +7 -2
- package/dist/esm/variables/variants/ConstantVariable.js.map +1 -1
- package/dist/esm/variables/variants/MultiValueVariable.js +21 -11
- package/dist/esm/variables/variants/MultiValueVariable.js.map +1 -1
- package/dist/index.d.ts +10 -12
- package/dist/index.js +154 -61
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,13 +1,150 @@
|
|
|
1
|
-
# v0.0.
|
|
1
|
+
# v0.0.29 (Mon Mar 27 2023)
|
|
2
2
|
|
|
3
3
|
#### 🐛 Bug Fix
|
|
4
4
|
|
|
5
|
-
-
|
|
6
|
-
-
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
5
|
+
- release test [#106](https://github.com/grafana/scenes/pull/106) ([@torkelo](https://github.com/torkelo))
|
|
6
|
+
- Fix type import [#104](https://github.com/grafana/scenes/pull/104) ([@torkelo](https://github.com/torkelo))
|
|
7
|
+
- my bad ([@torkelo](https://github.com/torkelo))
|
|
8
|
+
- Fix type import ([@torkelo](https://github.com/torkelo))
|
|
9
|
+
- Macros: Share SkipFormattingValue value between AllUrlVariablesMacro and UrlTimeRangeMacro [#101](https://github.com/grafana/scenes/pull/101) ([@torkelo](https://github.com/torkelo))
|
|
10
|
+
- Share skip formatting ([@torkelo](https://github.com/torkelo))
|
|
11
|
+
- Scene: Support for new types of "macro" variables starting with __all_variables [#98](https://github.com/grafana/scenes/pull/98) ([@domasx2](https://github.com/domasx2) [@torkelo](https://github.com/torkelo))
|
|
12
|
+
- Removed some old code ([@torkelo](https://github.com/torkelo))
|
|
13
|
+
- Updates ([@torkelo](https://github.com/torkelo))
|
|
14
|
+
- More refactoring ([@torkelo](https://github.com/torkelo))
|
|
15
|
+
- Refactoring and added time range macro ([@torkelo](https://github.com/torkelo))
|
|
16
|
+
- Refactoring ([@torkelo](https://github.com/torkelo))
|
|
17
|
+
- fix ([@torkelo](https://github.com/torkelo))
|
|
18
|
+
- Fixed ts issues ([@torkelo](https://github.com/torkelo))
|
|
19
|
+
- Merge branch 'main' of github.com:grafana/scenes into scene-url-variables ([@torkelo](https://github.com/torkelo))
|
|
20
|
+
- ScenesApp: Change to workspace dependency [#99](https://github.com/grafana/scenes/pull/99) ([@torkelo](https://github.com/torkelo))
|
|
21
|
+
- UrlSyncManager: Improvements and fixes [#96](https://github.com/grafana/scenes/pull/96) ([@torkelo](https://github.com/torkelo))
|
|
22
|
+
- remove unused arg ([@torkelo](https://github.com/torkelo))
|
|
23
|
+
- Add skipUrlSync support ([@torkelo](https://github.com/torkelo))
|
|
24
|
+
- Variables: Add support for macro variables like __all_variables ([@torkelo](https://github.com/torkelo))
|
|
25
|
+
- Merge branch 'scene-interpolate-all-variables' into domas-interpolate-all-variables ([@torkelo](https://github.com/torkelo))
|
|
26
|
+
- Simplify logic ([@torkelo](https://github.com/torkelo))
|
|
27
|
+
- minor fix ([@torkelo](https://github.com/torkelo))
|
|
28
|
+
- Made tests a bit clear on what scenario they where testing ([@torkelo](https://github.com/torkelo))
|
|
29
|
+
- remove unnessary cleanup in EmbeddedScene ([@torkelo](https://github.com/torkelo))
|
|
30
|
+
- UrlSyncManager: Improvements and fixes ([@torkelo](https://github.com/torkelo))
|
|
31
|
+
- Update ([@torkelo](https://github.com/torkelo))
|
|
32
|
+
- Changelog: Clean up auto crap [#94](https://github.com/grafana/scenes/pull/94) ([@torkelo](https://github.com/torkelo))
|
|
33
|
+
- Fixing changelog ([@torkelo](https://github.com/torkelo))
|
|
34
|
+
- test ([@torkelo](https://github.com/torkelo))
|
|
35
|
+
- Yarn: Caching should work [#93](https://github.com/grafana/scenes/pull/93) ([@torkelo](https://github.com/torkelo))
|
|
36
|
+
- interpolate all variables ([@domasx2](https://github.com/domasx2))
|
|
10
37
|
|
|
11
|
-
#### Authors:
|
|
38
|
+
#### Authors: 2
|
|
12
39
|
|
|
40
|
+
- Domas ([@domasx2](https://github.com/domasx2))
|
|
13
41
|
- Torkel Ödegaard ([@torkelo](https://github.com/torkelo))
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
# v0.0.28 (Tue Mar 21 2023)
|
|
46
|
+
|
|
47
|
+
- Removal of isEditing from SceneComponentProps (also $editor from SceneObjectState, and sceneGraph.getSceneEditor)
|
|
48
|
+
- DataSourceVariable state change, query property is now named pluginId
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
# 0.21 (2023-03-17)
|
|
53
|
+
|
|
54
|
+
**SceneObject subscribeToState parameter change**
|
|
55
|
+
|
|
56
|
+
Signature change. Now the parameter to this function expects a simple function that takes two args (newState, prevState).
|
|
57
|
+
|
|
58
|
+
Before:
|
|
59
|
+
|
|
60
|
+
```ts
|
|
61
|
+
this._subs.add(
|
|
62
|
+
sourceData.subscribeToState({
|
|
63
|
+
next: (state) => this.transform(state.data),
|
|
64
|
+
})
|
|
65
|
+
);
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Becomes:
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
this._subs.add(sourceData.subscribeToState((state) => this.transform(state.data)));
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
**addActivationHandler**
|
|
75
|
+
|
|
76
|
+
SceneObject now has a new function called addActivationHandler that makes it much easier to add external behaviors to core scene componenents. The
|
|
77
|
+
activation handler (callback) can return a deactivation handler. This works very similar to useEffect.
|
|
78
|
+
|
|
79
|
+
For custom components that used to override activate and then call super.activate() we now recommend that you instead use addActivationHandler from
|
|
80
|
+
the constructor. See https://github.com/grafana/scenes/pull/77 for some examples.
|
|
81
|
+
|
|
82
|
+
**VizPanelMenu**
|
|
83
|
+
|
|
84
|
+
A new scene object to enable panel menu for `VizPanel`.
|
|
85
|
+
|
|
86
|
+
Example usage:
|
|
87
|
+
|
|
88
|
+
```ts
|
|
89
|
+
const menu = new VizPanelMenu({});
|
|
90
|
+
|
|
91
|
+
// Configure menu items
|
|
92
|
+
menu.addActivationHandler(() => {
|
|
93
|
+
menu.setItems(menuItems);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
// Attach menu to VizPanel
|
|
97
|
+
const panelWithMenu = new VizPanel({
|
|
98
|
+
title: 'Panel with menu',
|
|
99
|
+
menu,
|
|
100
|
+
// ... VizPanel configuration
|
|
101
|
+
});
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
To see more examples, please look at [`VizPanelMenu` demo](./packages/scenes-app/src/pages/Demos/scenes/panelMenu.ts).
|
|
105
|
+
|
|
106
|
+
**Scene App demos**
|
|
107
|
+
|
|
108
|
+
Scene App included with this repo now contains Demos page in which we will continue providing examples of particular @grafana/scenes usages. Run `./scripts/demo.sh` and navigate to [http://localhost:3001/a/grafana-scenes-app/demos](http://localhost:3001/a/grafana-scenes-app/demos) to see available demos.
|
|
109
|
+
|
|
110
|
+
# 0.20 (2023-03-15)
|
|
111
|
+
|
|
112
|
+
**AppScenePage**
|
|
113
|
+
|
|
114
|
+
The getScene for drilldowns now expect the parent property to be of type AppScenePageLike (interface).
|
|
115
|
+
|
|
116
|
+
# 0.19 (2023-03-15)
|
|
117
|
+
|
|
118
|
+
**SceneQueryRunner no longer has transformations**
|
|
119
|
+
|
|
120
|
+
Instead you have to use SceneDataTransformer and set its internal $data property to the SceneQueryRunner to get the same effect.
|
|
121
|
+
|
|
122
|
+
Example:
|
|
123
|
+
|
|
124
|
+
```tsx
|
|
125
|
+
$data: new SceneDataTransformer({
|
|
126
|
+
$data: new SceneQueryRunner({...}),
|
|
127
|
+
transformations: [
|
|
128
|
+
{
|
|
129
|
+
id: 'reduce',
|
|
130
|
+
options: {
|
|
131
|
+
reducers: ['mean'],
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
],
|
|
135
|
+
}),
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
SceneDataTransformer can still be used to transform parent scoped data, it will look for this if there is no $data property set.
|
|
139
|
+
|
|
140
|
+
The reasons for this change it to have more control over when only transformations should be re-processed (to not issue query again when only a dependency on the transforms changed).
|
|
141
|
+
It also removes some duplication between SceneQueryRunner and SceneDataTransformer. There is also a new interface SceneDataProvider.
|
|
142
|
+
|
|
143
|
+
```ts
|
|
144
|
+
export interface SceneDataProvider extends SceneObject<SceneDataState> {
|
|
145
|
+
setContainerWidth?: (width: number) => void;
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Change PR
|
|
150
|
+
https://github.com/grafana/scenes/pull/55
|
|
@@ -5,18 +5,10 @@ import { SceneObjectBase } from '../core/SceneObjectBase.js';
|
|
|
5
5
|
import { UrlSyncManager } from '../services/UrlSyncManager.js';
|
|
6
6
|
|
|
7
7
|
class EmbeddedScene extends SceneObjectBase {
|
|
8
|
-
constructor(state) {
|
|
9
|
-
super(state);
|
|
10
|
-
this.addActivationHandler(() => {
|
|
11
|
-
return () => {
|
|
12
|
-
if (this.urlSyncManager) {
|
|
13
|
-
this.urlSyncManager.cleanUp();
|
|
14
|
-
}
|
|
15
|
-
};
|
|
16
|
-
});
|
|
17
|
-
}
|
|
18
8
|
initUrlSync() {
|
|
19
|
-
this.urlSyncManager
|
|
9
|
+
if (!this.urlSyncManager) {
|
|
10
|
+
this.urlSyncManager = new UrlSyncManager(this);
|
|
11
|
+
}
|
|
20
12
|
this.urlSyncManager.initSync();
|
|
21
13
|
}
|
|
22
14
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EmbeddedScene.js","sources":["../../../src/components/EmbeddedScene.tsx"],"sourcesContent":["import { css } from '@emotion/css';\nimport { GrafanaTheme2 } from '@grafana/data';\nimport { useStyles2 } from '@grafana/ui';\nimport React from 'react';\n\nimport { SceneObjectBase } from '../core/SceneObjectBase';\nimport { SceneComponentProps, SceneObjectStatePlain, SceneObject } from '../core/types';\nimport { UrlSyncManager } from '../services/UrlSyncManager';\n\nexport interface EmbeddedSceneState extends SceneObjectStatePlain {\n /**\n * The main content of the scene (usually a SceneFlexLayout)\n */\n body: SceneObject;\n /**\n * Top row of variable selectors, filters, time pickers and custom actions.\n */\n controls?: SceneObject[];\n}\n\nexport class EmbeddedScene extends SceneObjectBase<EmbeddedSceneState> {\n public static Component = EmbeddedSceneRenderer;\n\n private urlSyncManager?: UrlSyncManager;\n\n
|
|
1
|
+
{"version":3,"file":"EmbeddedScene.js","sources":["../../../src/components/EmbeddedScene.tsx"],"sourcesContent":["import { css } from '@emotion/css';\nimport { GrafanaTheme2 } from '@grafana/data';\nimport { useStyles2 } from '@grafana/ui';\nimport React from 'react';\n\nimport { SceneObjectBase } from '../core/SceneObjectBase';\nimport { SceneComponentProps, SceneObjectStatePlain, SceneObject } from '../core/types';\nimport { UrlSyncManager } from '../services/UrlSyncManager';\n\nexport interface EmbeddedSceneState extends SceneObjectStatePlain {\n /**\n * The main content of the scene (usually a SceneFlexLayout)\n */\n body: SceneObject;\n /**\n * Top row of variable selectors, filters, time pickers and custom actions.\n */\n controls?: SceneObject[];\n}\n\nexport class EmbeddedScene extends SceneObjectBase<EmbeddedSceneState> {\n public static Component = EmbeddedSceneRenderer;\n\n private urlSyncManager?: UrlSyncManager;\n\n /**\n * initUrlSync should be called before the scene is rendered to ensure that objects are in sync\n * before they get activated. This saves some unnecessary re-renders and makes sure variables\n * queries are issued as needed.\n */\n public initUrlSync() {\n if (!this.urlSyncManager) {\n this.urlSyncManager = new UrlSyncManager(this);\n }\n\n this.urlSyncManager.initSync();\n }\n}\n\nfunction EmbeddedSceneRenderer({ model }: SceneComponentProps<EmbeddedScene>) {\n const { body, controls } = model.useState();\n const styles = useStyles2(getStyles);\n\n return (\n <div className={styles.container}>\n {controls && (\n <div className={styles.controls}>\n {controls.map((control) => (\n <control.Component key={control.state.key} model={control} />\n ))}\n </div>\n )}\n <div className={styles.body}>\n <body.Component model={body} />\n </div>\n </div>\n );\n}\n\nfunction getStyles(theme: GrafanaTheme2) {\n return {\n container: css({\n flexGrow: 1,\n display: 'flex',\n gap: theme.spacing(2),\n minHeight: '100%',\n flexDirection: 'column',\n }),\n body: css({\n flexGrow: 1,\n display: 'flex',\n gap: '8px',\n }),\n controls: css({\n display: 'flex',\n gap: theme.spacing(1),\n alignItems: 'center',\n flexWrap: 'wrap',\n }),\n };\n}\n"],"names":[],"mappings":";;;;;;AAoBO,MAAM,sBAAsB,eAAoC,CAAA;AAAA,EAU9D,WAAc,GAAA;AACnB,IAAI,IAAA,CAAC,KAAK,cAAgB,EAAA;AACxB,MAAK,IAAA,CAAA,cAAA,GAAiB,IAAI,cAAA,CAAe,IAAI,CAAA,CAAA;AAAA,KAC/C;AAEA,IAAA,IAAA,CAAK,eAAe,QAAS,EAAA,CAAA;AAAA,GAC/B;AACF,CAAA;AAjBa,aAAA,CACG,SAAY,GAAA,qBAAA,CAAA;AAkB5B,SAAS,qBAAA,CAAsB,EAAE,KAAA,EAA6C,EAAA;AAC5E,EAAA,MAAM,EAAE,IAAA,EAAM,QAAS,EAAA,GAAI,MAAM,QAAS,EAAA,CAAA;AAC1C,EAAM,MAAA,MAAA,GAAS,WAAW,SAAS,CAAA,CAAA;AAEnC,EAAA,uBACG,KAAA,CAAA,aAAA,CAAA,KAAA,EAAA;AAAA,IAAI,WAAW,MAAO,CAAA,SAAA;AAAA,GAAA,EACpB,4BACE,KAAA,CAAA,aAAA,CAAA,KAAA,EAAA;AAAA,IAAI,WAAW,MAAO,CAAA,QAAA;AAAA,GAAA,EACpB,SAAS,GAAI,CAAA,CAAC,OACb,qBAAA,KAAA,CAAA,aAAA,CAAC,QAAQ,SAAR,EAAA;AAAA,IAAkB,GAAA,EAAK,QAAQ,KAAM,CAAA,GAAA;AAAA,IAAK,KAAO,EAAA,OAAA;AAAA,GAAS,CAC5D,CACH,CAAA,kBAED,KAAA,CAAA,aAAA,CAAA,KAAA,EAAA;AAAA,IAAI,WAAW,MAAO,CAAA,IAAA;AAAA,GACrB,kBAAA,KAAA,CAAA,aAAA,CAAC,KAAK,SAAL,EAAA;AAAA,IAAe,KAAO,EAAA,IAAA;AAAA,GAAM,CAC/B,CACF,CAAA,CAAA;AAEJ,CAAA;AAEA,SAAS,UAAU,KAAsB,EAAA;AACvC,EAAO,OAAA;AAAA,IACL,WAAW,GAAI,CAAA;AAAA,MACb,QAAU,EAAA,CAAA;AAAA,MACV,OAAS,EAAA,MAAA;AAAA,MACT,GAAA,EAAK,KAAM,CAAA,OAAA,CAAQ,CAAC,CAAA;AAAA,MACpB,SAAW,EAAA,MAAA;AAAA,MACX,aAAe,EAAA,QAAA;AAAA,KAChB,CAAA;AAAA,IACD,MAAM,GAAI,CAAA;AAAA,MACR,QAAU,EAAA,CAAA;AAAA,MACV,OAAS,EAAA,MAAA;AAAA,MACT,GAAK,EAAA,KAAA;AAAA,KACN,CAAA;AAAA,IACD,UAAU,GAAI,CAAA;AAAA,MACZ,OAAS,EAAA,MAAA;AAAA,MACT,GAAA,EAAK,KAAM,CAAA,OAAA,CAAQ,CAAC,CAAA;AAAA,MACpB,UAAY,EAAA,QAAA;AAAA,MACZ,QAAU,EAAA,MAAA;AAAA,KACX,CAAA;AAAA,GACH,CAAA;AACF;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SceneTimeRange.js","sources":["../../../src/core/SceneTimeRange.tsx"],"sourcesContent":["import { dateMath, getTimeZone, TimeRange, TimeZone, toUtc } from '@grafana/data';\n\nimport { SceneObjectUrlSyncConfig } from '../services/SceneObjectUrlSyncConfig';\n\nimport { SceneObjectBase } from './SceneObjectBase';\nimport { SceneTimeRangeLike, SceneTimeRangeState, SceneObjectUrlValues, SceneObjectUrlValue } from './types';\n\nexport class SceneTimeRange extends SceneObjectBase<SceneTimeRangeState> implements SceneTimeRangeLike {\n protected _urlSync = new SceneObjectUrlSyncConfig(this, { keys: ['from', 'to'] });\n\n public constructor(state: Partial<SceneTimeRangeState> = {}) {\n const from = state.from ?? 'now-6h';\n const to = state.to ?? 'now';\n const timeZone = state.timeZone ?? getTimeZone();\n const value = evaluateTimeRange(from, to, timeZone);\n super({ from, to, timeZone, value, ...state });\n }\n\n public onTimeRangeChange = (timeRange: TimeRange) => {\n const update: Partial<SceneTimeRangeState> = {};\n\n if (typeof timeRange.raw.from === 'string') {\n update.from = timeRange.raw.from;\n } else {\n update.from = timeRange.raw.from.toISOString();\n }\n\n if (typeof timeRange.raw.to === 'string') {\n update.to = timeRange.raw.to;\n } else {\n update.to = timeRange.raw.to.toISOString();\n }\n\n update.value = evaluateTimeRange(update.from, update.to, this.state.timeZone);\n this.setState(update);\n };\n\n public onRefresh = () => {\n this.setState({ value: evaluateTimeRange(this.state.from, this.state.to, this.state.timeZone) });\n };\n\n public getUrlState(state: SceneTimeRangeState) {\n return { from: state.from, to: state.to };\n }\n\n public updateFromUrl(values: SceneObjectUrlValues) {\n const update: Partial<SceneTimeRangeState> = {};\n
|
|
1
|
+
{"version":3,"file":"SceneTimeRange.js","sources":["../../../src/core/SceneTimeRange.tsx"],"sourcesContent":["import { dateMath, getTimeZone, TimeRange, TimeZone, toUtc } from '@grafana/data';\n\nimport { SceneObjectUrlSyncConfig } from '../services/SceneObjectUrlSyncConfig';\n\nimport { SceneObjectBase } from './SceneObjectBase';\nimport { SceneTimeRangeLike, SceneTimeRangeState, SceneObjectUrlValues, SceneObjectUrlValue } from './types';\n\nexport class SceneTimeRange extends SceneObjectBase<SceneTimeRangeState> implements SceneTimeRangeLike {\n protected _urlSync = new SceneObjectUrlSyncConfig(this, { keys: ['from', 'to'] });\n\n public constructor(state: Partial<SceneTimeRangeState> = {}) {\n const from = state.from ?? 'now-6h';\n const to = state.to ?? 'now';\n const timeZone = state.timeZone ?? getTimeZone();\n const value = evaluateTimeRange(from, to, timeZone);\n super({ from, to, timeZone, value, ...state });\n }\n\n public onTimeRangeChange = (timeRange: TimeRange) => {\n const update: Partial<SceneTimeRangeState> = {};\n\n if (typeof timeRange.raw.from === 'string') {\n update.from = timeRange.raw.from;\n } else {\n update.from = timeRange.raw.from.toISOString();\n }\n\n if (typeof timeRange.raw.to === 'string') {\n update.to = timeRange.raw.to;\n } else {\n update.to = timeRange.raw.to.toISOString();\n }\n\n update.value = evaluateTimeRange(update.from, update.to, this.state.timeZone);\n this.setState(update);\n };\n\n public onRefresh = () => {\n this.setState({ value: evaluateTimeRange(this.state.from, this.state.to, this.state.timeZone) });\n };\n\n public getUrlState(state: SceneTimeRangeState) {\n return { from: state.from, to: state.to };\n }\n\n public updateFromUrl(values: SceneObjectUrlValues) {\n // ignore if both are missing\n if (!values.to && !values.from) {\n return;\n }\n\n const update: Partial<SceneTimeRangeState> = {};\n const from = parseUrlParam(values.from);\n\n if (from) {\n update.from = from;\n }\n\n const to = parseUrlParam(values.to);\n if (to) {\n update.to = to;\n }\n\n update.value = evaluateTimeRange(update.from ?? this.state.from, update.to ?? this.state.to, this.state.timeZone);\n this.setState(update);\n }\n}\n\nfunction parseUrlParam(value: SceneObjectUrlValue): string | null {\n if (typeof value !== 'string') {\n return null;\n }\n\n if (value.indexOf('now') !== -1) {\n return value;\n }\n\n if (value.length === 8) {\n const utcValue = toUtc(value, 'YYYYMMDD');\n if (utcValue.isValid()) {\n return utcValue.toISOString();\n }\n } else if (value.length === 15) {\n const utcValue = toUtc(value, 'YYYYMMDDTHHmmss');\n if (utcValue.isValid()) {\n return utcValue.toISOString();\n }\n } else if (value.length === 24) {\n const utcValue = toUtc(value);\n return utcValue.toISOString();\n }\n\n const epoch = parseInt(value, 10);\n if (!isNaN(epoch)) {\n return toUtc(epoch).toISOString();\n }\n\n return null;\n}\n\nfunction evaluateTimeRange(from: string, to: string, timeZone: TimeZone, fiscalYearStartMonth?: number): TimeRange {\n return {\n from: dateMath.parse(from, false, timeZone, fiscalYearStartMonth)!,\n to: dateMath.parse(to, true, timeZone, fiscalYearStartMonth)!,\n raw: {\n from: from,\n to: to,\n },\n };\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;AAOO,MAAM,uBAAuB,eAAmE,CAAA;AAAA,EAG9F,WAAA,CAAY,KAAsC,GAAA,EAAI,EAAA;AAV/D,IAAA,IAAA,EAAA,EAAA,EAAA,EAAA,EAAA,CAAA;AAWI,IAAM,MAAA,IAAA,GAAA,CAAO,EAAM,GAAA,KAAA,CAAA,IAAA,KAAN,IAAc,GAAA,EAAA,GAAA,QAAA,CAAA;AAC3B,IAAM,MAAA,EAAA,GAAA,CAAK,EAAM,GAAA,KAAA,CAAA,EAAA,KAAN,IAAY,GAAA,EAAA,GAAA,KAAA,CAAA;AACvB,IAAA,MAAM,QAAW,GAAA,CAAA,EAAA,GAAA,KAAA,CAAM,QAAN,KAAA,IAAA,GAAA,EAAA,GAAkB,WAAY,EAAA,CAAA;AAC/C,IAAA,MAAM,KAAQ,GAAA,iBAAA,CAAkB,IAAM,EAAA,EAAA,EAAI,QAAQ,CAAA,CAAA;AAClD,IAAA,KAAA,CAAM,cAAE,CAAA,EAAA,IAAA,EAAM,EAAI,EAAA,QAAA,EAAU,SAAU,KAAO,CAAA,CAAA,CAAA;AAP/C,IAAU,IAAA,CAAA,QAAA,GAAW,IAAI,wBAAA,CAAyB,IAAM,EAAA,EAAE,MAAM,CAAC,MAAA,EAAQ,IAAI,CAAA,EAAG,CAAA,CAAA;AAUhF,IAAO,IAAA,CAAA,iBAAA,GAAoB,CAAC,SAAyB,KAAA;AACnD,MAAA,MAAM,SAAuC,EAAC,CAAA;AAE9C,MAAA,IAAI,OAAO,SAAA,CAAU,GAAI,CAAA,IAAA,KAAS,QAAU,EAAA;AAC1C,QAAO,MAAA,CAAA,IAAA,GAAO,UAAU,GAAI,CAAA,IAAA,CAAA;AAAA,OACvB,MAAA;AACL,QAAA,MAAA,CAAO,IAAO,GAAA,SAAA,CAAU,GAAI,CAAA,IAAA,CAAK,WAAY,EAAA,CAAA;AAAA,OAC/C;AAEA,MAAA,IAAI,OAAO,SAAA,CAAU,GAAI,CAAA,EAAA,KAAO,QAAU,EAAA;AACxC,QAAO,MAAA,CAAA,EAAA,GAAK,UAAU,GAAI,CAAA,EAAA,CAAA;AAAA,OACrB,MAAA;AACL,QAAA,MAAA,CAAO,EAAK,GAAA,SAAA,CAAU,GAAI,CAAA,EAAA,CAAG,WAAY,EAAA,CAAA;AAAA,OAC3C;AAEA,MAAO,MAAA,CAAA,KAAA,GAAQ,kBAAkB,MAAO,CAAA,IAAA,EAAM,OAAO,EAAI,EAAA,IAAA,CAAK,MAAM,QAAQ,CAAA,CAAA;AAC5E,MAAA,IAAA,CAAK,SAAS,MAAM,CAAA,CAAA;AAAA,KACtB,CAAA;AAEA,IAAA,IAAA,CAAO,YAAY,MAAM;AACvB,MAAA,IAAA,CAAK,QAAS,CAAA,EAAE,KAAO,EAAA,iBAAA,CAAkB,KAAK,KAAM,CAAA,IAAA,EAAM,IAAK,CAAA,KAAA,CAAM,EAAI,EAAA,IAAA,CAAK,KAAM,CAAA,QAAQ,GAAG,CAAA,CAAA;AAAA,KACjG,CAAA;AAAA,GAvBA;AAAA,EAyBO,YAAY,KAA4B,EAAA;AAC7C,IAAA,OAAO,EAAE,IAAM,EAAA,KAAA,CAAM,IAAM,EAAA,EAAA,EAAI,MAAM,EAAG,EAAA,CAAA;AAAA,GAC1C;AAAA,EAEO,cAAc,MAA8B,EAAA;AA7CrD,IAAA,IAAA,EAAA,EAAA,EAAA,CAAA;AA+CI,IAAA,IAAI,CAAC,MAAA,CAAO,EAAM,IAAA,CAAC,OAAO,IAAM,EAAA;AAC9B,MAAA,OAAA;AAAA,KACF;AAEA,IAAA,MAAM,SAAuC,EAAC,CAAA;AAC9C,IAAM,MAAA,IAAA,GAAO,aAAc,CAAA,MAAA,CAAO,IAAI,CAAA,CAAA;AAEtC,IAAA,IAAI,IAAM,EAAA;AACR,MAAA,MAAA,CAAO,IAAO,GAAA,IAAA,CAAA;AAAA,KAChB;AAEA,IAAM,MAAA,EAAA,GAAK,aAAc,CAAA,MAAA,CAAO,EAAE,CAAA,CAAA;AAClC,IAAA,IAAI,EAAI,EAAA;AACN,MAAA,MAAA,CAAO,EAAK,GAAA,EAAA,CAAA;AAAA,KACd;AAEA,IAAA,MAAA,CAAO,QAAQ,iBAAkB,CAAA,CAAA,EAAA,GAAA,MAAA,CAAO,IAAP,KAAA,IAAA,GAAA,EAAA,GAAe,KAAK,KAAM,CAAA,IAAA,EAAA,CAAM,EAAO,GAAA,MAAA,CAAA,EAAA,KAAP,YAAa,IAAK,CAAA,KAAA,CAAM,EAAI,EAAA,IAAA,CAAK,MAAM,QAAQ,CAAA,CAAA;AAChH,IAAA,IAAA,CAAK,SAAS,MAAM,CAAA,CAAA;AAAA,GACtB;AACF,CAAA;AAEA,SAAS,cAAc,KAA2C,EAAA;AAChE,EAAI,IAAA,OAAO,UAAU,QAAU,EAAA;AAC7B,IAAO,OAAA,IAAA,CAAA;AAAA,GACT;AAEA,EAAA,IAAI,KAAM,CAAA,OAAA,CAAQ,KAAK,CAAA,KAAM,CAAI,CAAA,EAAA;AAC/B,IAAO,OAAA,KAAA,CAAA;AAAA,GACT;AAEA,EAAI,IAAA,KAAA,CAAM,WAAW,CAAG,EAAA;AACtB,IAAM,MAAA,QAAA,GAAW,KAAM,CAAA,KAAA,EAAO,UAAU,CAAA,CAAA;AACxC,IAAI,IAAA,QAAA,CAAS,SAAW,EAAA;AACtB,MAAA,OAAO,SAAS,WAAY,EAAA,CAAA;AAAA,KAC9B;AAAA,GACF,MAAA,IAAW,KAAM,CAAA,MAAA,KAAW,EAAI,EAAA;AAC9B,IAAM,MAAA,QAAA,GAAW,KAAM,CAAA,KAAA,EAAO,iBAAiB,CAAA,CAAA;AAC/C,IAAI,IAAA,QAAA,CAAS,SAAW,EAAA;AACtB,MAAA,OAAO,SAAS,WAAY,EAAA,CAAA;AAAA,KAC9B;AAAA,GACF,MAAA,IAAW,KAAM,CAAA,MAAA,KAAW,EAAI,EAAA;AAC9B,IAAM,MAAA,QAAA,GAAW,MAAM,KAAK,CAAA,CAAA;AAC5B,IAAA,OAAO,SAAS,WAAY,EAAA,CAAA;AAAA,GAC9B;AAEA,EAAM,MAAA,KAAA,GAAQ,QAAS,CAAA,KAAA,EAAO,EAAE,CAAA,CAAA;AAChC,EAAI,IAAA,CAAC,KAAM,CAAA,KAAK,CAAG,EAAA;AACjB,IAAO,OAAA,KAAA,CAAM,KAAK,CAAA,CAAE,WAAY,EAAA,CAAA;AAAA,GAClC;AAEA,EAAO,OAAA,IAAA,CAAA;AACT,CAAA;AAEA,SAAS,iBAAkB,CAAA,IAAA,EAAc,EAAY,EAAA,QAAA,EAAoB,oBAA0C,EAAA;AACjH,EAAO,OAAA;AAAA,IACL,MAAM,QAAS,CAAA,KAAA,CAAM,IAAM,EAAA,KAAA,EAAO,UAAU,oBAAoB,CAAA;AAAA,IAChE,IAAI,QAAS,CAAA,KAAA,CAAM,EAAI,EAAA,IAAA,EAAM,UAAU,oBAAoB,CAAA;AAAA,IAC3D,GAAK,EAAA;AAAA,MACH,IAAA;AAAA,MACA,EAAA;AAAA,KACF;AAAA,GACF,CAAA;AACF;;;;"}
|
package/dist/esm/index.js
CHANGED
|
@@ -6,7 +6,7 @@ export { SceneDataNode } from './core/SceneDataNode.js';
|
|
|
6
6
|
export { SceneTimeRange } from './core/SceneTimeRange.js';
|
|
7
7
|
export { SceneQueryRunner } from './querying/SceneQueryRunner.js';
|
|
8
8
|
export { SceneDataTransformer } from './querying/SceneDataTransformer.js';
|
|
9
|
-
export { SceneVariableValueChangedEvent } from './variables/types.js';
|
|
9
|
+
export { SceneVariableValueChangedEvent, isCustomVariableValue } from './variables/types.js';
|
|
10
10
|
export { VariableDependencyConfig } from './variables/VariableDependencyConfig.js';
|
|
11
11
|
export { FormatRegistryID, formatRegistry } from './variables/interpolation/formatRegistry.js';
|
|
12
12
|
export { VariableValueSelectors } from './variables/components/VariableValueSelectors.js';
|
|
@@ -6,7 +6,6 @@ import { forEachSceneObjectInState } from '../core/utils.js';
|
|
|
6
6
|
class UrlSyncManager {
|
|
7
7
|
constructor(sceneRoot) {
|
|
8
8
|
this.sceneRoot = sceneRoot;
|
|
9
|
-
this.initialStates = /* @__PURE__ */ new Map();
|
|
10
9
|
this.urlKeyMapper = new UniqueUrlKeyMapper();
|
|
11
10
|
this.onLocationUpdate = (location) => {
|
|
12
11
|
const urlParams = new URLSearchParams(location.search);
|
|
@@ -17,7 +16,6 @@ class UrlSyncManager {
|
|
|
17
16
|
const changedObject = payload.changedObject;
|
|
18
17
|
if (changedObject.urlSync) {
|
|
19
18
|
const newUrlState = changedObject.urlSync.getUrlState(payload.newState);
|
|
20
|
-
const prevUrlState = changedObject.urlSync.getUrlState(payload.prevState);
|
|
21
19
|
const searchParams = locationService.getSearch();
|
|
22
20
|
const mappedUpdated = {};
|
|
23
21
|
this.urlKeyMapper.rebuldIndex(this.sceneRoot);
|
|
@@ -26,9 +24,6 @@ class UrlSyncManager {
|
|
|
26
24
|
const currentUrlValue = searchParams.getAll(uniqueKey);
|
|
27
25
|
if (!isUrlValueEqual(currentUrlValue, newUrlValue)) {
|
|
28
26
|
mappedUpdated[uniqueKey] = newUrlValue;
|
|
29
|
-
if (!this.initialStates.has(uniqueKey) && prevUrlState[key] !== void 0) {
|
|
30
|
-
this.initialStates.set(uniqueKey, prevUrlState[key]);
|
|
31
|
-
}
|
|
32
27
|
}
|
|
33
28
|
}
|
|
34
29
|
if (Object.keys(mappedUpdated).length > 0) {
|
|
@@ -36,18 +31,20 @@ class UrlSyncManager {
|
|
|
36
31
|
}
|
|
37
32
|
}
|
|
38
33
|
};
|
|
39
|
-
this.stateChangeSub = sceneRoot.subscribeToEvent(SceneObjectStateChangedEvent, this.onStateChanged);
|
|
40
|
-
this.locationListenerUnsub = locationService.getHistory().listen(this.onLocationUpdate);
|
|
41
34
|
}
|
|
42
35
|
initSync() {
|
|
36
|
+
this.sceneRoot.addActivationHandler(() => {
|
|
37
|
+
const stateChangeSub = this.sceneRoot.subscribeToEvent(SceneObjectStateChangedEvent, this.onStateChanged);
|
|
38
|
+
const locationListenerUnsub = locationService.getHistory().listen(this.onLocationUpdate);
|
|
39
|
+
return () => {
|
|
40
|
+
stateChangeSub.unsubscribe();
|
|
41
|
+
locationListenerUnsub();
|
|
42
|
+
};
|
|
43
|
+
});
|
|
43
44
|
const urlParams = locationService.getSearch();
|
|
44
45
|
this.urlKeyMapper.rebuldIndex(this.sceneRoot);
|
|
45
46
|
this.syncSceneStateFromUrl(this.sceneRoot, urlParams);
|
|
46
47
|
}
|
|
47
|
-
cleanUp() {
|
|
48
|
-
this.stateChangeSub.unsubscribe();
|
|
49
|
-
this.locationListenerUnsub();
|
|
50
|
-
}
|
|
51
48
|
syncSceneStateFromUrl(sceneObject, urlParams) {
|
|
52
49
|
if (sceneObject.urlSync) {
|
|
53
50
|
const urlState = {};
|
|
@@ -65,14 +62,8 @@ class UrlSyncManager {
|
|
|
65
62
|
} else {
|
|
66
63
|
urlState[key] = newValue[0];
|
|
67
64
|
}
|
|
68
|
-
if (!this.initialStates.has(uniqueKey) && currentValue !== void 0) {
|
|
69
|
-
this.initialStates.set(uniqueKey, currentValue);
|
|
70
|
-
}
|
|
71
65
|
} else {
|
|
72
|
-
|
|
73
|
-
if (initialValue !== void 0) {
|
|
74
|
-
urlState[key] = initialValue;
|
|
75
|
-
}
|
|
66
|
+
urlState[key] = null;
|
|
76
67
|
}
|
|
77
68
|
}
|
|
78
69
|
if (Object.keys(urlState).length > 0) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UrlSyncManager.js","sources":["../../../src/services/UrlSyncManager.ts"],"sourcesContent":["import { Location } from 'history';\nimport { isEqual } from 'lodash';\nimport { Unsubscribable } from 'rxjs';\n\nimport { locationService } from '@grafana/runtime';\n\nimport { SceneObjectStateChangedEvent } from '../core/events';\nimport { SceneObject, SceneObjectUrlValue, SceneObjectUrlValues } from '../core/types';\nimport { forEachSceneObjectInState } from '../core/utils';\n\nexport class UrlSyncManager {\n private locationListenerUnsub: () => void;\n private stateChangeSub: Unsubscribable;\n private initialStates: Map<string, SceneObjectUrlValue> = new Map();\n private urlKeyMapper = new UniqueUrlKeyMapper();\n\n public constructor(private sceneRoot: SceneObject) {\n this.stateChangeSub = sceneRoot.subscribeToEvent(SceneObjectStateChangedEvent, this.onStateChanged);\n this.locationListenerUnsub = locationService.getHistory().listen(this.onLocationUpdate);\n }\n\n /**\n * Updates the current scene state to match URL state.\n */\n public initSync() {\n const urlParams = locationService.getSearch();\n this.urlKeyMapper.rebuldIndex(this.sceneRoot);\n this.syncSceneStateFromUrl(this.sceneRoot, urlParams);\n }\n\n private onLocationUpdate = (location: Location) => {\n const urlParams = new URLSearchParams(location.search);\n // Rebuild key mapper index before starting sync\n this.urlKeyMapper.rebuldIndex(this.sceneRoot);\n // Sync scene state tree from url\n this.syncSceneStateFromUrl(this.sceneRoot, urlParams);\n };\n\n private onStateChanged = ({ payload }: SceneObjectStateChangedEvent) => {\n const changedObject = payload.changedObject;\n\n if (changedObject.urlSync) {\n const newUrlState = changedObject.urlSync.getUrlState(payload.newState);\n const prevUrlState = changedObject.urlSync.getUrlState(payload.prevState);\n\n const searchParams = locationService.getSearch();\n const mappedUpdated: SceneObjectUrlValues = {};\n\n this.urlKeyMapper.rebuldIndex(this.sceneRoot);\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 // Remember the initial state so we can go back to it\n if (!this.initialStates.has(uniqueKey) && prevUrlState[key] !== undefined) {\n this.initialStates.set(uniqueKey, prevUrlState[key]);\n }\n }\n }\n\n if (Object.keys(mappedUpdated).length > 0) {\n locationService.partial(mappedUpdated, true);\n }\n }\n };\n\n public cleanUp() {\n this.stateChangeSub.unsubscribe();\n this.locationListenerUnsub();\n }\n\n private syncSceneStateFromUrl(sceneObject: SceneObject, urlParams: URLSearchParams) {\n if (sceneObject.urlSync) {\n const urlState: SceneObjectUrlValues = {};\n const currentState = sceneObject.urlSync.getUrlState(sceneObject.state);\n\n for (const key of sceneObject.urlSync.getKeys()) {\n const uniqueKey = this.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\n // Remember the initial state so we can go back to it\n if (!this.initialStates.has(uniqueKey) && currentValue !== undefined) {\n this.initialStates.set(uniqueKey, currentValue);\n }\n } else {\n const initialValue = this.initialStates.get(uniqueKey);\n if (initialValue !== undefined) {\n urlState[key] = initialValue;\n }\n }\n }\n\n if (Object.keys(urlState).length > 0) {\n sceneObject.urlSync.updateFromUrl(urlState);\n }\n }\n\n forEachSceneObjectInState(sceneObject.state, (obj) => this.syncSceneStateFromUrl(obj, urlParams));\n }\n}\n\ninterface SceneObjectWithDepth {\n sceneObject: SceneObject;\n depth: number;\n}\nclass UniqueUrlKeyMapper {\n private index = new Map<string, SceneObjectWithDepth[]>();\n\n public getUniqueKey(key: string, obj: SceneObject) {\n const objectsWithKey = this.index.get(key);\n if (!objectsWithKey) {\n throw new Error(\"Cannot find any scene object that uses the key '\" + key + \"'\");\n }\n\n const address = objectsWithKey.findIndex((o) => o.sceneObject === obj);\n if (address > 0) {\n return `${key}-${address + 1}`;\n }\n\n return key;\n }\n\n public rebuldIndex(root: SceneObject) {\n this.index.clear();\n this.buildIndex(root, 0);\n }\n\n private buildIndex(sceneObject: SceneObject, depth: number) {\n if (sceneObject.urlSync) {\n for (const key of sceneObject.urlSync.getKeys()) {\n const hit = this.index.get(key);\n if (hit) {\n hit.push({ sceneObject, depth });\n hit.sort((a, b) => a.depth - b.depth);\n } else {\n this.index.set(key, [{ sceneObject, depth }]);\n }\n }\n }\n\n forEachSceneObjectInState(sceneObject.state, (obj) => this.buildIndex(obj, depth + 1));\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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"}
|
|
1
|
+
{"version":3,"file":"UrlSyncManager.js","sources":["../../../src/services/UrlSyncManager.ts"],"sourcesContent":["import { Location } from 'history';\nimport { isEqual } from 'lodash';\n\nimport { locationService } from '@grafana/runtime';\n\nimport { SceneObjectStateChangedEvent } from '../core/events';\nimport { SceneObject, SceneObjectUrlValue, SceneObjectUrlValues } from '../core/types';\nimport { forEachSceneObjectInState } from '../core/utils';\n\nexport class UrlSyncManager {\n private urlKeyMapper = new UniqueUrlKeyMapper();\n\n public constructor(private sceneRoot: SceneObject) {}\n\n /**\n * Updates the current scene state to match URL state.\n */\n public initSync() {\n this.sceneRoot.addActivationHandler(() => {\n const stateChangeSub = this.sceneRoot.subscribeToEvent(SceneObjectStateChangedEvent, this.onStateChanged);\n const locationListenerUnsub = locationService.getHistory().listen(this.onLocationUpdate);\n\n return () => {\n stateChangeSub.unsubscribe();\n locationListenerUnsub();\n };\n });\n\n const urlParams = locationService.getSearch();\n this.urlKeyMapper.rebuldIndex(this.sceneRoot);\n this.syncSceneStateFromUrl(this.sceneRoot, urlParams);\n }\n\n private onLocationUpdate = (location: Location) => {\n const urlParams = new URLSearchParams(location.search);\n // Rebuild key mapper index before starting sync\n this.urlKeyMapper.rebuldIndex(this.sceneRoot);\n // Sync scene state tree from url\n this.syncSceneStateFromUrl(this.sceneRoot, urlParams);\n };\n\n private onStateChanged = ({ payload }: SceneObjectStateChangedEvent) => {\n const changedObject = payload.changedObject;\n\n if (changedObject.urlSync) {\n const newUrlState = changedObject.urlSync.getUrlState(payload.newState);\n\n const searchParams = locationService.getSearch();\n const mappedUpdated: SceneObjectUrlValues = {};\n\n this.urlKeyMapper.rebuldIndex(this.sceneRoot);\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 locationService.partial(mappedUpdated, true);\n }\n }\n };\n\n private syncSceneStateFromUrl(sceneObject: SceneObject, urlParams: URLSearchParams) {\n if (sceneObject.urlSync) {\n const urlState: SceneObjectUrlValues = {};\n const currentState = sceneObject.urlSync.getUrlState(sceneObject.state);\n\n for (const key of sceneObject.urlSync.getKeys()) {\n const uniqueKey = this.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 forEachSceneObjectInState(sceneObject.state, (obj) => this.syncSceneStateFromUrl(obj, urlParams));\n }\n}\n\ninterface SceneObjectWithDepth {\n sceneObject: SceneObject;\n depth: number;\n}\nclass UniqueUrlKeyMapper {\n private index = new Map<string, SceneObjectWithDepth[]>();\n\n public getUniqueKey(key: string, obj: SceneObject) {\n const objectsWithKey = this.index.get(key);\n if (!objectsWithKey) {\n throw new Error(\"Cannot find any scene object that uses the key '\" + key + \"'\");\n }\n\n const address = objectsWithKey.findIndex((o) => o.sceneObject === obj);\n if (address > 0) {\n return `${key}-${address + 1}`;\n }\n\n return key;\n }\n\n public rebuldIndex(root: SceneObject) {\n this.index.clear();\n this.buildIndex(root, 0);\n }\n\n private buildIndex(sceneObject: SceneObject, depth: number) {\n if (sceneObject.urlSync) {\n for (const key of sceneObject.urlSync.getKeys()) {\n const hit = this.index.get(key);\n if (hit) {\n hit.push({ sceneObject, depth });\n hit.sort((a, b) => a.depth - b.depth);\n } else {\n this.index.set(key, [{ sceneObject, depth }]);\n }\n }\n }\n\n forEachSceneObjectInState(sceneObject.state, (obj) => this.buildIndex(obj, depth + 1));\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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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ScopedVarsVariable.js","sources":["../../../../src/variables/interpolation/ScopedVarsVariable.ts"],"sourcesContent":["import { property } from 'lodash';\n\nimport { ScopedVar } from '@grafana/data';\n\nimport { VariableValue } from '../types';\n\nimport { FormatVariable } from './formatRegistry';\n\nexport class ScopedVarsVariable implements FormatVariable {\n private static fieldAccessorCache: FieldAccessorCache = {};\n\n public state: { name: string; value: ScopedVar; type: string };\n\n public constructor(name: string, value: ScopedVar) {\n this.state = { name, value, type: 'scopedvar' };\n }\n\n public getValue(fieldPath: string): VariableValue {\n let { value } = this.state;\n let realValue = value.value;\n\n if (fieldPath) {\n realValue = this.getFieldAccessor(fieldPath)(value.value);\n } else {\n realValue = value.value;\n }\n\n if (realValue === 'string' || realValue === 'number' || realValue === 'boolean') {\n return realValue;\n }\n\n return String(realValue);\n }\n\n public getValueText(): string {\n const { value } = this.state;\n\n if (value.text != null) {\n return String(value.text);\n }\n\n return String(value);\n }\n\n private getFieldAccessor(fieldPath: string) {\n const accessor = ScopedVarsVariable.fieldAccessorCache[fieldPath];\n if (accessor) {\n return accessor;\n }\n\n return (ScopedVarsVariable.fieldAccessorCache[fieldPath] = property(fieldPath));\n }\n}\n\ninterface FieldAccessorCache {\n [key: string]: (obj: unknown) => unknown;\n}\n\nlet scopedVarsVariable: ScopedVarsVariable | undefined;\n\n/**\n * Reuses a single instance to avoid unnecessary memory allocations\n */\nexport function getSceneVariableForScopedVar(name: string, value: ScopedVar) {\n if (!scopedVarsVariable) {\n scopedVarsVariable = new ScopedVarsVariable(name, value);\n } else {\n scopedVarsVariable.state.name = name;\n scopedVarsVariable.state.value = value;\n }\n\n return scopedVarsVariable;\n}\n"],"names":[],"mappings":";;AAQO,MAAM,sBAAN,MAAmD;AAAA,EAKjD,WAAA,CAAY,MAAc,KAAkB,EAAA;AACjD,IAAA,IAAA,CAAK,KAAQ,GAAA,EAAE,IAAM,EAAA,KAAA,EAAO,MAAM,WAAY,EAAA,CAAA;AAAA,GAChD;AAAA,EAEO,SAAS,SAAkC,EAAA;AAChD,IAAI,IAAA,EAAE,KAAM,EAAA,GAAI,IAAK,CAAA,KAAA,CAAA;AACrB,IAAA,IAAI,YAAY,KAAM,CAAA,KAAA,CAAA;AAEtB,IAAA,IAAI,SAAW,EAAA;AACb,MAAA,SAAA,GAAY,IAAK,CAAA,gBAAA,CAAiB,SAAS,CAAA,CAAE,MAAM,KAAK,CAAA,CAAA;AAAA,KACnD,MAAA;AACL,MAAA,SAAA,GAAY,KAAM,CAAA,KAAA,CAAA;AAAA,KACpB;AAEA,IAAA,IAAI,SAAc,KAAA,QAAA,IAAY,SAAc,KAAA,QAAA,IAAY,cAAc,SAAW,EAAA;AAC/E,MAAO,OAAA,SAAA,CAAA;AAAA,KACT;AAEA,IAAA,OAAO,OAAO,SAAS,CAAA,CAAA;AAAA,GACzB;AAAA,EAEO,YAAuB,GAAA;AAC5B,IAAM,MAAA,EAAE,KAAM,EAAA,GAAI,IAAK,CAAA,KAAA,CAAA;AAEvB,IAAI,IAAA,KAAA,CAAM,QAAQ,IAAM,EAAA;AACtB,MAAO,OAAA,MAAA,CAAO,MAAM,IAAI,CAAA,CAAA;AAAA,KAC1B;AAEA,IAAA,OAAO,OAAO,KAAK,CAAA,CAAA;AAAA,GACrB;AAAA,EAEQ,iBAAiB,SAAmB,EAAA;AAC1C,IAAM,MAAA,QAAA,GAAW,oBAAmB,kBAAmB,CAAA,SAAA,CAAA,CAAA;AACvD,IAAA,IAAI,QAAU,EAAA;AACZ,MAAO,OAAA,QAAA,CAAA;AAAA,KACT;AAEA,IAAA,OAAQ,mBAAmB,CAAA,kBAAA,CAAmB,SAAa,CAAA,GAAA,QAAA,CAAS,SAAS,CAAA,CAAA;AAAA,GAC/E;AACF,CAAA,CAAA;AA5CO,IAAM,kBAAN,GAAA,oBAAA;AAAM,kBAAA,CACI,qBAAyC,EAAC,CAAA;AAiD3D,IAAI,kBAAA,CAAA;AAKY,SAAA,4BAAA,CAA6B,MAAc,
|
|
1
|
+
{"version":3,"file":"ScopedVarsVariable.js","sources":["../../../../src/variables/interpolation/ScopedVarsVariable.ts"],"sourcesContent":["import { property } from 'lodash';\n\nimport { ScopedVar } from '@grafana/data';\n\nimport { VariableValue } from '../types';\n\nimport { FormatVariable } from './formatRegistry';\n\nexport class ScopedVarsVariable implements FormatVariable {\n private static fieldAccessorCache: FieldAccessorCache = {};\n\n public state: { name: string; value: ScopedVar; type: string };\n\n public constructor(name: string, value: ScopedVar) {\n this.state = { name, value, type: 'scopedvar' };\n }\n\n public getValue(fieldPath: string): VariableValue {\n let { value } = this.state;\n let realValue = value.value;\n\n if (fieldPath) {\n realValue = this.getFieldAccessor(fieldPath)(value.value);\n } else {\n realValue = value.value;\n }\n\n if (realValue === 'string' || realValue === 'number' || realValue === 'boolean') {\n return realValue;\n }\n\n return String(realValue);\n }\n\n public getValueText(): string {\n const { value } = this.state;\n\n if (value.text != null) {\n return String(value.text);\n }\n\n return String(value);\n }\n\n private getFieldAccessor(fieldPath: string) {\n const accessor = ScopedVarsVariable.fieldAccessorCache[fieldPath];\n if (accessor) {\n return accessor;\n }\n\n return (ScopedVarsVariable.fieldAccessorCache[fieldPath] = property(fieldPath));\n }\n}\n\ninterface FieldAccessorCache {\n [key: string]: (obj: unknown) => unknown;\n}\n\nlet scopedVarsVariable: ScopedVarsVariable | undefined;\n\n/**\n * Reuses a single instance to avoid unnecessary memory allocations\n */\nexport function getSceneVariableForScopedVar(name: string, value: ScopedVar): FormatVariable {\n if (!scopedVarsVariable) {\n scopedVarsVariable = new ScopedVarsVariable(name, value);\n } else {\n scopedVarsVariable.state.name = name;\n scopedVarsVariable.state.value = value;\n }\n\n return scopedVarsVariable;\n}\n"],"names":[],"mappings":";;AAQO,MAAM,sBAAN,MAAmD;AAAA,EAKjD,WAAA,CAAY,MAAc,KAAkB,EAAA;AACjD,IAAA,IAAA,CAAK,KAAQ,GAAA,EAAE,IAAM,EAAA,KAAA,EAAO,MAAM,WAAY,EAAA,CAAA;AAAA,GAChD;AAAA,EAEO,SAAS,SAAkC,EAAA;AAChD,IAAI,IAAA,EAAE,KAAM,EAAA,GAAI,IAAK,CAAA,KAAA,CAAA;AACrB,IAAA,IAAI,YAAY,KAAM,CAAA,KAAA,CAAA;AAEtB,IAAA,IAAI,SAAW,EAAA;AACb,MAAA,SAAA,GAAY,IAAK,CAAA,gBAAA,CAAiB,SAAS,CAAA,CAAE,MAAM,KAAK,CAAA,CAAA;AAAA,KACnD,MAAA;AACL,MAAA,SAAA,GAAY,KAAM,CAAA,KAAA,CAAA;AAAA,KACpB;AAEA,IAAA,IAAI,SAAc,KAAA,QAAA,IAAY,SAAc,KAAA,QAAA,IAAY,cAAc,SAAW,EAAA;AAC/E,MAAO,OAAA,SAAA,CAAA;AAAA,KACT;AAEA,IAAA,OAAO,OAAO,SAAS,CAAA,CAAA;AAAA,GACzB;AAAA,EAEO,YAAuB,GAAA;AAC5B,IAAM,MAAA,EAAE,KAAM,EAAA,GAAI,IAAK,CAAA,KAAA,CAAA;AAEvB,IAAI,IAAA,KAAA,CAAM,QAAQ,IAAM,EAAA;AACtB,MAAO,OAAA,MAAA,CAAO,MAAM,IAAI,CAAA,CAAA;AAAA,KAC1B;AAEA,IAAA,OAAO,OAAO,KAAK,CAAA,CAAA;AAAA,GACrB;AAAA,EAEQ,iBAAiB,SAAmB,EAAA;AAC1C,IAAM,MAAA,QAAA,GAAW,oBAAmB,kBAAmB,CAAA,SAAA,CAAA,CAAA;AACvD,IAAA,IAAI,QAAU,EAAA;AACZ,MAAO,OAAA,QAAA,CAAA;AAAA,KACT;AAEA,IAAA,OAAQ,mBAAmB,CAAA,kBAAA,CAAmB,SAAa,CAAA,GAAA,QAAA,CAAS,SAAS,CAAA,CAAA;AAAA,GAC/E;AACF,CAAA,CAAA;AA5CO,IAAM,kBAAN,GAAA,oBAAA;AAAM,kBAAA,CACI,qBAAyC,EAAC,CAAA;AAiD3D,IAAI,kBAAA,CAAA;AAKY,SAAA,4BAAA,CAA6B,MAAc,KAAkC,EAAA;AAC3F,EAAA,IAAI,CAAC,kBAAoB,EAAA;AACvB,IAAqB,kBAAA,GAAA,IAAI,kBAAmB,CAAA,IAAA,EAAM,KAAK,CAAA,CAAA;AAAA,GAClD,MAAA;AACL,IAAA,kBAAA,CAAmB,MAAM,IAAO,GAAA,IAAA,CAAA;AAChC,IAAA,kBAAA,CAAmB,MAAM,KAAQ,GAAA,KAAA,CAAA;AAAA,GACnC;AAEA,EAAO,OAAA,kBAAA,CAAA;AACT;;;;"}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import { isCustomVariableValue } from '../types.js';
|
|
1
2
|
import { getSceneVariableForScopedVar } from './ScopedVarsVariable.js';
|
|
2
3
|
import { FormatRegistryID, formatRegistry } from './formatRegistry.js';
|
|
3
4
|
import { VARIABLE_REGEX } from '../constants.js';
|
|
4
5
|
import { lookupVariable } from '../lookupVariable.js';
|
|
6
|
+
import { macrosIndex } from '../macros/index.js';
|
|
5
7
|
|
|
6
8
|
function sceneInterpolator(sceneObject, target, scopedVars, format) {
|
|
7
9
|
if (!target) {
|
|
@@ -11,24 +13,29 @@ function sceneInterpolator(sceneObject, target, scopedVars, format) {
|
|
|
11
13
|
return target.replace(VARIABLE_REGEX, (match, var1, var2, fmt2, var3, fieldPath, fmt3) => {
|
|
12
14
|
const variableName = var1 || var2 || var3;
|
|
13
15
|
const fmt = fmt2 || fmt3 || format;
|
|
14
|
-
|
|
15
|
-
if (scopedVars && scopedVars[variableName]) {
|
|
16
|
-
variable = getSceneVariableForScopedVar(variableName, scopedVars[variableName]);
|
|
17
|
-
} else {
|
|
18
|
-
variable = lookupVariable(variableName, sceneObject);
|
|
19
|
-
}
|
|
16
|
+
const variable = lookupFormatVariable(variableName, scopedVars, sceneObject);
|
|
20
17
|
if (!variable) {
|
|
21
18
|
return match;
|
|
22
19
|
}
|
|
23
20
|
return formatValue(variable, variable.getValue(fieldPath), fmt);
|
|
24
21
|
});
|
|
25
22
|
}
|
|
23
|
+
function lookupFormatVariable(name, scopedVars, sceneObject) {
|
|
24
|
+
if (macrosIndex[name]) {
|
|
25
|
+
return new macrosIndex[name](name, sceneObject);
|
|
26
|
+
}
|
|
27
|
+
if (scopedVars && scopedVars[name]) {
|
|
28
|
+
return getSceneVariableForScopedVar(name, scopedVars[name]);
|
|
29
|
+
} else {
|
|
30
|
+
return lookupVariable(name, sceneObject);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
26
33
|
function formatValue(variable, value, formatNameOrFn) {
|
|
27
34
|
if (value === null || value === void 0) {
|
|
28
35
|
return "";
|
|
29
36
|
}
|
|
30
|
-
if (
|
|
31
|
-
return value.
|
|
37
|
+
if (isCustomVariableValue(value)) {
|
|
38
|
+
return value.formatter(formatNameOrFn);
|
|
32
39
|
}
|
|
33
40
|
if (!Array.isArray(value) && typeof value === "object") {
|
|
34
41
|
value = `${value}`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sceneInterpolator.js","sources":["../../../../src/variables/interpolation/sceneInterpolator.ts"],"sourcesContent":["import { ScopedVars } from '@grafana/data';\nimport { VariableType } from '@grafana/schema';\n\nimport { SceneObject } from '../../core/types';\nimport { VariableCustomFormatterFn, VariableValue } from '../types';\n\nimport { getSceneVariableForScopedVar } from './ScopedVarsVariable';\nimport { formatRegistry, FormatRegistryID, FormatVariable } from './formatRegistry';\nimport { VARIABLE_REGEX } from '../constants';\nimport { lookupVariable } from '../lookupVariable';\n\n/**\n * This function will try
|
|
1
|
+
{"version":3,"file":"sceneInterpolator.js","sources":["../../../../src/variables/interpolation/sceneInterpolator.ts"],"sourcesContent":["import { ScopedVars } from '@grafana/data';\nimport { VariableType } from '@grafana/schema';\n\nimport { SceneObject } from '../../core/types';\nimport { isCustomVariableValue, VariableCustomFormatterFn, VariableValue } from '../types';\n\nimport { getSceneVariableForScopedVar } from './ScopedVarsVariable';\nimport { formatRegistry, FormatRegistryID, FormatVariable } from './formatRegistry';\nimport { VARIABLE_REGEX } from '../constants';\nimport { lookupVariable } from '../lookupVariable';\nimport { macrosIndex } from '../macros';\n\n/**\n * This function will try o parse and replace any variable expression found in the target string. The sceneObject will be used as the source of variables. It will\n * use the scene graph and walk up the parent tree until it finds the closest variable.\n *\n * ScopedVars should not really be needed much in the new scene architecture as they can be added to the local scene node instead of passed in interpolate function.\n * It is supported here for backward compatibility and some edge cases where adding scoped vars to local scene node is not practical.\n */\nexport function sceneInterpolator(\n sceneObject: SceneObject,\n target: string | undefined | null,\n scopedVars?: ScopedVars,\n format?: string | VariableCustomFormatterFn\n): string {\n if (!target) {\n return target ?? '';\n }\n\n VARIABLE_REGEX.lastIndex = 0;\n\n return target.replace(VARIABLE_REGEX, (match, var1, var2, fmt2, var3, fieldPath, fmt3) => {\n const variableName = var1 || var2 || var3;\n const fmt = fmt2 || fmt3 || format;\n const variable = lookupFormatVariable(variableName, scopedVars, sceneObject);\n\n if (!variable) {\n return match;\n }\n\n return formatValue(variable, variable.getValue(fieldPath), fmt);\n });\n}\n\nfunction lookupFormatVariable(\n name: string,\n scopedVars: ScopedVars | undefined,\n sceneObject: SceneObject\n): FormatVariable | null {\n if (macrosIndex[name]) {\n return new macrosIndex[name](name, sceneObject);\n }\n\n if (scopedVars && scopedVars[name]) {\n return getSceneVariableForScopedVar(name, scopedVars[name]);\n } else {\n return lookupVariable(name, sceneObject);\n }\n}\n\nfunction formatValue(\n variable: FormatVariable,\n value: VariableValue | undefined | null,\n formatNameOrFn?: string | VariableCustomFormatterFn\n): string {\n if (value === null || value === undefined) {\n return '';\n }\n\n // Variable can return a custom value that handles formatting\n // This is useful for customAllValue and macros that return values that are already formatted or need special formatting\n if (isCustomVariableValue(value)) {\n return value.formatter(formatNameOrFn);\n }\n\n // if it's an object transform value to string\n if (!Array.isArray(value) && typeof value === 'object') {\n value = `${value}`;\n }\n\n if (typeof formatNameOrFn === 'function') {\n return formatNameOrFn(value, {\n name: variable.state.name,\n type: variable.state.type as VariableType,\n multi: variable.state.isMulti,\n includeAll: variable.state.includeAll,\n });\n }\n\n let args: string[] = [];\n\n if (!formatNameOrFn) {\n formatNameOrFn = FormatRegistryID.glob;\n } else {\n // some formats have arguments that come after ':' character\n args = formatNameOrFn.split(':');\n if (args.length > 1) {\n formatNameOrFn = args[0];\n args = args.slice(1);\n } else {\n args = [];\n }\n }\n\n let formatter = formatRegistry.getIfExists(formatNameOrFn);\n\n if (!formatter) {\n console.error(`Variable format ${formatNameOrFn} not found. Using glob format as fallback.`);\n formatter = formatRegistry.get(FormatRegistryID.glob);\n }\n\n return formatter.formatter(value, args, variable);\n}\n"],"names":[],"mappings":";;;;;;;AAmBO,SAAS,iBACd,CAAA,WAAA,EACA,MACA,EAAA,UAAA,EACA,MACQ,EAAA;AACR,EAAA,IAAI,CAAC,MAAQ,EAAA;AACX,IAAA,OAAO,MAAU,IAAA,IAAA,GAAA,MAAA,GAAA,EAAA,CAAA;AAAA,GACnB;AAEA,EAAA,cAAA,CAAe,SAAY,GAAA,CAAA,CAAA;AAE3B,EAAO,OAAA,MAAA,CAAO,OAAQ,CAAA,cAAA,EAAgB,CAAC,KAAA,EAAO,MAAM,IAAM,EAAA,IAAA,EAAM,IAAM,EAAA,SAAA,EAAW,IAAS,KAAA;AACxF,IAAM,MAAA,YAAA,GAAe,QAAQ,IAAQ,IAAA,IAAA,CAAA;AACrC,IAAM,MAAA,GAAA,GAAM,QAAQ,IAAQ,IAAA,MAAA,CAAA;AAC5B,IAAA,MAAM,QAAW,GAAA,oBAAA,CAAqB,YAAc,EAAA,UAAA,EAAY,WAAW,CAAA,CAAA;AAE3E,IAAA,IAAI,CAAC,QAAU,EAAA;AACb,MAAO,OAAA,KAAA,CAAA;AAAA,KACT;AAEA,IAAA,OAAO,YAAY,QAAU,EAAA,QAAA,CAAS,QAAS,CAAA,SAAS,GAAG,GAAG,CAAA,CAAA;AAAA,GAC/D,CAAA,CAAA;AACH,CAAA;AAEA,SAAS,oBAAA,CACP,IACA,EAAA,UAAA,EACA,WACuB,EAAA;AACvB,EAAA,IAAI,YAAY,IAAO,CAAA,EAAA;AACrB,IAAA,OAAO,IAAI,WAAA,CAAY,IAAM,CAAA,CAAA,IAAA,EAAM,WAAW,CAAA,CAAA;AAAA,GAChD;AAEA,EAAI,IAAA,UAAA,IAAc,WAAW,IAAO,CAAA,EAAA;AAClC,IAAO,OAAA,4BAAA,CAA6B,IAAM,EAAA,UAAA,CAAW,IAAK,CAAA,CAAA,CAAA;AAAA,GACrD,MAAA;AACL,IAAO,OAAA,cAAA,CAAe,MAAM,WAAW,CAAA,CAAA;AAAA,GACzC;AACF,CAAA;AAEA,SAAS,WAAA,CACP,QACA,EAAA,KAAA,EACA,cACQ,EAAA;AACR,EAAI,IAAA,KAAA,KAAU,IAAQ,IAAA,KAAA,KAAU,KAAW,CAAA,EAAA;AACzC,IAAO,OAAA,EAAA,CAAA;AAAA,GACT;AAIA,EAAI,IAAA,qBAAA,CAAsB,KAAK,CAAG,EAAA;AAChC,IAAO,OAAA,KAAA,CAAM,UAAU,cAAc,CAAA,CAAA;AAAA,GACvC;AAGA,EAAA,IAAI,CAAC,KAAM,CAAA,OAAA,CAAQ,KAAK,CAAK,IAAA,OAAO,UAAU,QAAU,EAAA;AACtD,IAAA,KAAA,GAAQ,CAAG,EAAA,KAAA,CAAA,CAAA,CAAA;AAAA,GACb;AAEA,EAAI,IAAA,OAAO,mBAAmB,UAAY,EAAA;AACxC,IAAA,OAAO,eAAe,KAAO,EAAA;AAAA,MAC3B,IAAA,EAAM,SAAS,KAAM,CAAA,IAAA;AAAA,MACrB,IAAA,EAAM,SAAS,KAAM,CAAA,IAAA;AAAA,MACrB,KAAA,EAAO,SAAS,KAAM,CAAA,OAAA;AAAA,MACtB,UAAA,EAAY,SAAS,KAAM,CAAA,UAAA;AAAA,KAC5B,CAAA,CAAA;AAAA,GACH;AAEA,EAAA,IAAI,OAAiB,EAAC,CAAA;AAEtB,EAAA,IAAI,CAAC,cAAgB,EAAA;AACnB,IAAA,cAAA,GAAiB,gBAAiB,CAAA,IAAA,CAAA;AAAA,GAC7B,MAAA;AAEL,IAAO,IAAA,GAAA,cAAA,CAAe,MAAM,GAAG,CAAA,CAAA;AAC/B,IAAI,IAAA,IAAA,CAAK,SAAS,CAAG,EAAA;AACnB,MAAA,cAAA,GAAiB,IAAK,CAAA,CAAA,CAAA,CAAA;AACtB,MAAO,IAAA,GAAA,IAAA,CAAK,MAAM,CAAC,CAAA,CAAA;AAAA,KACd,MAAA;AACL,MAAA,IAAA,GAAO,EAAC,CAAA;AAAA,KACV;AAAA,GACF;AAEA,EAAI,IAAA,SAAA,GAAY,cAAe,CAAA,WAAA,CAAY,cAAc,CAAA,CAAA;AAEzD,EAAA,IAAI,CAAC,SAAW,EAAA;AACd,IAAQ,OAAA,CAAA,KAAA,CAAM,mBAAmB,cAA0D,CAAA,0CAAA,CAAA,CAAA,CAAA;AAC3F,IAAY,SAAA,GAAA,cAAA,CAAe,GAAI,CAAA,gBAAA,CAAiB,IAAI,CAAA,CAAA;AAAA,GACtD;AAEA,EAAA,OAAO,SAAU,CAAA,SAAA,CAAU,KAAO,EAAA,IAAA,EAAM,QAAQ,CAAA,CAAA;AAClD;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lookupVariable.js","sources":["../../../src/variables/lookupVariable.ts"],"sourcesContent":["import { SceneObject } from '../core/types';\nimport { SceneVariable } from './types';\n\n/**\n * Will walk the scene object graph up to the root looking for the first variable with the specified name\n */\nexport function lookupVariable(name: string, sceneObject: SceneObject): SceneVariable | null
|
|
1
|
+
{"version":3,"file":"lookupVariable.js","sources":["../../../src/variables/lookupVariable.ts"],"sourcesContent":["import { SceneObject } from '../core/types';\nimport { SceneVariable } from './types';\n\n/**\n * Will walk the scene object graph up to the root looking for the first variable with the specified name\n */\nexport function lookupVariable(name: string, sceneObject: SceneObject): SceneVariable | null {\n const variables = sceneObject.state.$variables;\n if (!variables) {\n if (sceneObject.parent) {\n return lookupVariable(name, sceneObject.parent);\n } else {\n return null;\n }\n }\n\n const found = variables.getByName(name);\n if (found) {\n return found;\n } else if (sceneObject.parent) {\n return lookupVariable(name, sceneObject.parent);\n }\n\n return null;\n}\n"],"names":[],"mappings":"AAMgB,SAAA,cAAA,CAAe,MAAc,WAAgD,EAAA;AAC3F,EAAM,MAAA,SAAA,GAAY,YAAY,KAAM,CAAA,UAAA,CAAA;AACpC,EAAA,IAAI,CAAC,SAAW,EAAA;AACd,IAAA,IAAI,YAAY,MAAQ,EAAA;AACtB,MAAO,OAAA,cAAA,CAAe,IAAM,EAAA,WAAA,CAAY,MAAM,CAAA,CAAA;AAAA,KACzC,MAAA;AACL,MAAO,OAAA,IAAA,CAAA;AAAA,KACT;AAAA,GACF;AAEA,EAAM,MAAA,KAAA,GAAQ,SAAU,CAAA,SAAA,CAAU,IAAI,CAAA,CAAA;AACtC,EAAA,IAAI,KAAO,EAAA;AACT,IAAO,OAAA,KAAA,CAAA;AAAA,GACT,MAAA,IAAW,YAAY,MAAQ,EAAA;AAC7B,IAAO,OAAA,cAAA,CAAe,IAAM,EAAA,WAAA,CAAY,MAAM,CAAA,CAAA;AAAA,GAChD;AAEA,EAAO,OAAA,IAAA,CAAA;AACT;;;;"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { isCustomVariableValue } from '../types.js';
|
|
2
|
+
import { formatRegistry, FormatRegistryID } from '../interpolation/formatRegistry.js';
|
|
3
|
+
import { SkipFormattingValue } from './types.js';
|
|
4
|
+
|
|
5
|
+
class AllVariablesMacro {
|
|
6
|
+
constructor(name, sceneObject) {
|
|
7
|
+
this.state = { name, type: "url_variable" };
|
|
8
|
+
this._sceneObject = sceneObject;
|
|
9
|
+
}
|
|
10
|
+
getValue() {
|
|
11
|
+
const allVars = collectAllVariables(this._sceneObject);
|
|
12
|
+
const format = formatRegistry.get(FormatRegistryID.queryParam);
|
|
13
|
+
const params = [];
|
|
14
|
+
for (const name of Object.keys(allVars)) {
|
|
15
|
+
const variable = allVars[name];
|
|
16
|
+
const value = variable.getValue();
|
|
17
|
+
if (!value) {
|
|
18
|
+
continue;
|
|
19
|
+
}
|
|
20
|
+
if (isCustomVariableValue(value)) {
|
|
21
|
+
params.push(value.formatter(FormatRegistryID.queryParam));
|
|
22
|
+
} else {
|
|
23
|
+
params.push(format.formatter(value, [], variable));
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return new SkipFormattingValue(params.join("&"));
|
|
27
|
+
}
|
|
28
|
+
getValueText() {
|
|
29
|
+
return "";
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function collectAllVariables(sceneObject, record = {}) {
|
|
33
|
+
if (sceneObject.state.$variables) {
|
|
34
|
+
for (const variable of sceneObject.state.$variables.state.variables) {
|
|
35
|
+
if (variable.state.skipUrlSync) {
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
if (!record[variable.state.name]) {
|
|
39
|
+
record[variable.state.name] = variable;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
if (sceneObject.parent) {
|
|
44
|
+
collectAllVariables(sceneObject.parent, record);
|
|
45
|
+
}
|
|
46
|
+
return record;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export { AllVariablesMacro };
|
|
50
|
+
//# sourceMappingURL=AllVariablesMacro.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AllVariablesMacro.js","sources":["../../../../src/variables/macros/AllVariablesMacro.ts"],"sourcesContent":["import { SceneObject } from '../../core/types';\nimport { isCustomVariableValue, SceneVariable } from '../types';\nimport { formatRegistry, FormatRegistryID, FormatVariable } from '../interpolation/formatRegistry';\nimport { SkipFormattingValue } from './types';\n\nexport class AllVariablesMacro implements FormatVariable {\n public state: { name: string; type: string };\n private _sceneObject: SceneObject;\n\n public constructor(name: string, sceneObject: SceneObject) {\n this.state = { name, type: 'url_variable' };\n this._sceneObject = sceneObject;\n }\n\n public getValue(): SkipFormattingValue {\n const allVars = collectAllVariables(this._sceneObject);\n const format = formatRegistry.get(FormatRegistryID.queryParam);\n const params: string[] = [];\n\n for (const name of Object.keys(allVars)) {\n const variable = allVars[name];\n const value = variable.getValue();\n\n if (!value) {\n continue;\n }\n\n if (isCustomVariableValue(value)) {\n params.push(value.formatter(FormatRegistryID.queryParam));\n } else {\n params.push(format.formatter(value, [], variable));\n }\n }\n\n return new SkipFormattingValue(params.join('&'));\n }\n\n public getValueText?(): string {\n return '';\n }\n}\n\nfunction collectAllVariables(\n sceneObject: SceneObject,\n record: Record<string, SceneVariable> = {}\n): Record<string, SceneVariable> {\n if (sceneObject.state.$variables) {\n for (const variable of sceneObject.state.$variables.state.variables) {\n if (variable.state.skipUrlSync) {\n continue;\n }\n\n if (!record[variable.state.name]) {\n record[variable.state.name] = variable;\n }\n }\n }\n\n if (sceneObject.parent) {\n collectAllVariables(sceneObject.parent, record);\n }\n\n return record;\n}\n"],"names":[],"mappings":";;;;AAKO,MAAM,iBAA4C,CAAA;AAAA,EAIhD,WAAA,CAAY,MAAc,WAA0B,EAAA;AACzD,IAAA,IAAA,CAAK,KAAQ,GAAA,EAAE,IAAM,EAAA,IAAA,EAAM,cAAe,EAAA,CAAA;AAC1C,IAAA,IAAA,CAAK,YAAe,GAAA,WAAA,CAAA;AAAA,GACtB;AAAA,EAEO,QAAgC,GAAA;AACrC,IAAM,MAAA,OAAA,GAAU,mBAAoB,CAAA,IAAA,CAAK,YAAY,CAAA,CAAA;AACrD,IAAA,MAAM,MAAS,GAAA,cAAA,CAAe,GAAI,CAAA,gBAAA,CAAiB,UAAU,CAAA,CAAA;AAC7D,IAAA,MAAM,SAAmB,EAAC,CAAA;AAE1B,IAAA,KAAA,MAAW,IAAQ,IAAA,MAAA,CAAO,IAAK,CAAA,OAAO,CAAG,EAAA;AACvC,MAAA,MAAM,WAAW,OAAQ,CAAA,IAAA,CAAA,CAAA;AACzB,MAAM,MAAA,KAAA,GAAQ,SAAS,QAAS,EAAA,CAAA;AAEhC,MAAA,IAAI,CAAC,KAAO,EAAA;AACV,QAAA,SAAA;AAAA,OACF;AAEA,MAAI,IAAA,qBAAA,CAAsB,KAAK,CAAG,EAAA;AAChC,QAAA,MAAA,CAAO,IAAK,CAAA,KAAA,CAAM,SAAU,CAAA,gBAAA,CAAiB,UAAU,CAAC,CAAA,CAAA;AAAA,OACnD,MAAA;AACL,QAAA,MAAA,CAAO,KAAK,MAAO,CAAA,SAAA,CAAU,OAAO,EAAC,EAAG,QAAQ,CAAC,CAAA,CAAA;AAAA,OACnD;AAAA,KACF;AAEA,IAAA,OAAO,IAAI,mBAAA,CAAoB,MAAO,CAAA,IAAA,CAAK,GAAG,CAAC,CAAA,CAAA;AAAA,GACjD;AAAA,EAEO,YAAwB,GAAA;AAC7B,IAAO,OAAA,EAAA,CAAA;AAAA,GACT;AACF,CAAA;AAEA,SAAS,mBACP,CAAA,WAAA,EACA,MAAwC,GAAA,EACT,EAAA;AAC/B,EAAI,IAAA,WAAA,CAAY,MAAM,UAAY,EAAA;AAChC,IAAA,KAAA,MAAW,QAAY,IAAA,WAAA,CAAY,KAAM,CAAA,UAAA,CAAW,MAAM,SAAW,EAAA;AACnE,MAAI,IAAA,QAAA,CAAS,MAAM,WAAa,EAAA;AAC9B,QAAA,SAAA;AAAA,OACF;AAEA,MAAA,IAAI,CAAC,MAAA,CAAO,QAAS,CAAA,KAAA,CAAM,IAAO,CAAA,EAAA;AAChC,QAAO,MAAA,CAAA,QAAA,CAAS,MAAM,IAAQ,CAAA,GAAA,QAAA,CAAA;AAAA,OAChC;AAAA,KACF;AAAA,GACF;AAEA,EAAA,IAAI,YAAY,MAAQ,EAAA;AACtB,IAAoB,mBAAA,CAAA,WAAA,CAAY,QAAQ,MAAM,CAAA,CAAA;AAAA,GAChD;AAEA,EAAO,OAAA,MAAA,CAAA;AACT;;;;"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { urlUtil } from '@grafana/data';
|
|
2
|
+
import { DefaultTimeRange } from '../interpolation/defaults.js';
|
|
3
|
+
import { SkipFormattingValue } from './types.js';
|
|
4
|
+
|
|
5
|
+
class UrlTimeRangeMacro {
|
|
6
|
+
constructor(name, sceneObject) {
|
|
7
|
+
this.state = { name, type: "url_variable" };
|
|
8
|
+
this._sceneObject = sceneObject;
|
|
9
|
+
}
|
|
10
|
+
getValue() {
|
|
11
|
+
var _a;
|
|
12
|
+
const timeRange = getTimeRange(this._sceneObject);
|
|
13
|
+
const urlState = (_a = timeRange.urlSync) == null ? void 0 : _a.getUrlState(timeRange.state);
|
|
14
|
+
return new SkipFormattingValue(urlUtil.toUrlParams(urlState));
|
|
15
|
+
}
|
|
16
|
+
getValueText() {
|
|
17
|
+
return "";
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function getTimeRange(sceneObject) {
|
|
21
|
+
const { $timeRange } = sceneObject.state;
|
|
22
|
+
if ($timeRange) {
|
|
23
|
+
return $timeRange;
|
|
24
|
+
}
|
|
25
|
+
if (sceneObject.parent) {
|
|
26
|
+
return getTimeRange(sceneObject.parent);
|
|
27
|
+
}
|
|
28
|
+
return DefaultTimeRange;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export { UrlTimeRangeMacro };
|
|
32
|
+
//# sourceMappingURL=UrlTimeRangeMacro.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"UrlTimeRangeMacro.js","sources":["../../../../src/variables/macros/UrlTimeRangeMacro.ts"],"sourcesContent":["import { urlUtil } from '@grafana/data';\nimport { SceneObject, SceneTimeRangeLike } from '../../core/types';\nimport { FormatVariable } from '../interpolation/formatRegistry';\nimport { DefaultTimeRange } from '../interpolation/defaults';\nimport { SkipFormattingValue } from './types';\n\nexport class UrlTimeRangeMacro implements FormatVariable {\n public state: { name: string; type: string };\n private _sceneObject: SceneObject;\n\n public constructor(name: string, sceneObject: SceneObject) {\n this.state = { name: name, type: 'url_variable' };\n this._sceneObject = sceneObject;\n }\n\n public getValue(): SkipFormattingValue {\n const timeRange = getTimeRange(this._sceneObject);\n const urlState = timeRange.urlSync?.getUrlState(timeRange.state);\n return new SkipFormattingValue(urlUtil.toUrlParams(urlState));\n }\n\n public getValueText?(): string {\n return '';\n }\n}\n\nfunction getTimeRange(sceneObject: SceneObject): SceneTimeRangeLike {\n const { $timeRange } = sceneObject.state;\n if ($timeRange) {\n return $timeRange;\n }\n\n if (sceneObject.parent) {\n return getTimeRange(sceneObject.parent);\n }\n\n return DefaultTimeRange;\n}\n"],"names":[],"mappings":";;;;AAMO,MAAM,iBAA4C,CAAA;AAAA,EAIhD,WAAA,CAAY,MAAc,WAA0B,EAAA;AACzD,IAAA,IAAA,CAAK,KAAQ,GAAA,EAAE,IAAY,EAAA,IAAA,EAAM,cAAe,EAAA,CAAA;AAChD,IAAA,IAAA,CAAK,YAAe,GAAA,WAAA,CAAA;AAAA,GACtB;AAAA,EAEO,QAAgC,GAAA;AAfzC,IAAA,IAAA,EAAA,CAAA;AAgBI,IAAM,MAAA,SAAA,GAAY,YAAa,CAAA,IAAA,CAAK,YAAY,CAAA,CAAA;AAChD,IAAA,MAAM,QAAW,GAAA,CAAA,EAAA,GAAA,SAAA,CAAU,OAAV,KAAA,IAAA,GAAA,KAAA,CAAA,GAAA,EAAA,CAAmB,YAAY,SAAU,CAAA,KAAA,CAAA,CAAA;AAC1D,IAAA,OAAO,IAAI,mBAAA,CAAoB,OAAQ,CAAA,WAAA,CAAY,QAAQ,CAAC,CAAA,CAAA;AAAA,GAC9D;AAAA,EAEO,YAAwB,GAAA;AAC7B,IAAO,OAAA,EAAA,CAAA;AAAA,GACT;AACF,CAAA;AAEA,SAAS,aAAa,WAA8C,EAAA;AAClE,EAAM,MAAA,EAAE,UAAW,EAAA,GAAI,WAAY,CAAA,KAAA,CAAA;AACnC,EAAA,IAAI,UAAY,EAAA;AACd,IAAO,OAAA,UAAA,CAAA;AAAA,GACT;AAEA,EAAA,IAAI,YAAY,MAAQ,EAAA;AACtB,IAAO,OAAA,YAAA,CAAa,YAAY,MAAM,CAAA,CAAA;AAAA,GACxC;AAEA,EAAO,OAAA,gBAAA,CAAA;AACT;;;;"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { DataLinkBuiltInVars } from '@grafana/data';
|
|
2
|
+
import { UrlTimeRangeMacro } from './UrlTimeRangeMacro.js';
|
|
3
|
+
import { AllVariablesMacro } from './AllVariablesMacro.js';
|
|
4
|
+
|
|
5
|
+
const macrosIndex = {
|
|
6
|
+
[DataLinkBuiltInVars.includeVars]: AllVariablesMacro,
|
|
7
|
+
[DataLinkBuiltInVars.keepTime]: UrlTimeRangeMacro
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export { macrosIndex };
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../src/variables/macros/index.ts"],"sourcesContent":["import { DataLinkBuiltInVars } from '@grafana/data';\nimport { MacroVariableConstructor } from './types';\nimport { UrlTimeRangeMacro } from './UrlTimeRangeMacro';\nimport { AllVariablesMacro } from './AllVariablesMacro';\n\nexport const macrosIndex: Record<string, MacroVariableConstructor> = {\n [DataLinkBuiltInVars.includeVars]: AllVariablesMacro,\n [DataLinkBuiltInVars.keepTime]: UrlTimeRangeMacro,\n};\n"],"names":[],"mappings":";;;;AAKO,MAAM,WAAwD,GAAA;AAAA,EACnE,CAAC,oBAAoB,WAAc,GAAA,iBAAA;AAAA,EACnC,CAAC,oBAAoB,QAAW,GAAA,iBAAA;AAClC;;;;"}
|