@grafana/scenes 0.0.19 → 0.0.21

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.
Files changed (38) hide show
  1. package/README.md +20 -10
  2. package/dist/esm/components/EmbeddedScene.js +10 -9
  3. package/dist/esm/components/EmbeddedScene.js.map +1 -1
  4. package/dist/esm/components/SceneApp/SceneApp.js +3 -145
  5. package/dist/esm/components/SceneApp/SceneApp.js.map +1 -1
  6. package/dist/esm/components/SceneApp/SceneAppPage.js +151 -0
  7. package/dist/esm/components/SceneApp/SceneAppPage.js.map +1 -0
  8. package/dist/esm/components/SceneByFrameRepeater.js +8 -8
  9. package/dist/esm/components/SceneByFrameRepeater.js.map +1 -1
  10. package/dist/esm/components/SceneReactObject.js +34 -0
  11. package/dist/esm/components/SceneReactObject.js.map +1 -0
  12. package/dist/esm/components/SceneRefreshPicker.js +8 -9
  13. package/dist/esm/components/SceneRefreshPicker.js.map +1 -1
  14. package/dist/esm/components/VizPanel/VizPanel.js.map +1 -1
  15. package/dist/esm/components/VizPanel/VizPanelMenu.js +42 -0
  16. package/dist/esm/components/VizPanel/VizPanelMenu.js.map +1 -0
  17. package/dist/esm/components/VizPanel/VizPanelRenderer.js +11 -3
  18. package/dist/esm/components/VizPanel/VizPanelRenderer.js.map +1 -1
  19. package/dist/esm/components/layout/SceneFlexLayout.js +2 -1
  20. package/dist/esm/components/layout/SceneFlexLayout.js.map +1 -1
  21. package/dist/esm/core/SceneObjectBase.js +21 -9
  22. package/dist/esm/core/SceneObjectBase.js.map +1 -1
  23. package/dist/esm/core/types.js.map +1 -1
  24. package/dist/esm/index.js +4 -1
  25. package/dist/esm/index.js.map +1 -1
  26. package/dist/esm/querying/SceneDataTransformer.js +10 -9
  27. package/dist/esm/querying/SceneDataTransformer.js.map +1 -1
  28. package/dist/esm/querying/SceneQueryRunner.js +34 -18
  29. package/dist/esm/querying/SceneQueryRunner.js.map +1 -1
  30. package/dist/esm/variables/interpolation/formatRegistry.js.map +1 -1
  31. package/dist/esm/variables/sets/SceneVariableSet.js +29 -29
  32. package/dist/esm/variables/sets/SceneVariableSet.js.map +1 -1
  33. package/dist/esm/variables/variants/query/QueryVariable.js +10 -12
  34. package/dist/esm/variables/variants/query/QueryVariable.js.map +1 -1
  35. package/dist/index.d.ts +112 -43
  36. package/dist/index.js +472 -366
  37. package/dist/index.js.map +1 -1
  38. package/package.json +21 -25
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  <div align="center">
2
2
  <img
3
- src="./docs/img/grafana_icon.svg"
3
+ src="https://raw.githubusercontent.com/grafana/scenes/main/docs/img/grafana_icon.svg"
4
4
  alt="Grafana Logo"
5
5
  width="100px"
6
6
  padding="40px"
@@ -9,27 +9,37 @@
9
9
  <p>Create dashboard-like experiences in Grafana app plugins</p>
10
10
  </div>
11
11
 
12
- ## Important notice
12
+ ## About @grafana/scenes
13
13
 
14
- @grafana/scenes is in its early days. We do not encourage anyone to use it in plugins yet. APIs can (and probably will) change significantly in the months to come.
14
+ @grafana/scenes provides a framework to build dashboard-like experiences within Grafana's app plugins. It comes with the following features:
15
+
16
+ - Versatile layout options.
17
+ - Grafana panels rendering.
18
+ - Querying & transformations support
19
+ - Multiple time ranges support.
20
+ - Template variables support.
21
+ - URL sync.
22
+ - ... and more.
15
23
 
16
24
  ## Development
17
25
 
18
- ### Working with Grafana
26
+ To work on @grafana/scenes SDK, please follow the guides below.
27
+
28
+ ### Setting up local version of @grafana/scenes with local Grafana instance
19
29
 
20
- @grafana/scenes does not come with dedicated playground yet. It is currently possible to run Scene demos using Grafana. To do that, the following setup is required.
30
+ It is currently possible to run Scene demos using Grafana. To do that, the following setup is required.
21
31
 
22
- 1. Clone @grafana/scenes repository.
32
+ 1. Clone [Grafana Scenes repository](https://github.com/grafana/grafana/).
23
33
  1. Clone [Grafana](https://github.com/grafana/grafana/) repository and follow [Development guide](https://github.com/grafana/grafana/blob/main/contribute/developer-guide.md#developer-guide).
24
34
  1. Setup env variable `GRAFANA_PATH` to point to your Grafana repository directory, `export GRAFANA_PATH=<path-to-grafana-directory>`
25
- 1. From @grafana/scenes directory run `./scripts/dev.sh`. This will compile @grafana/scenes with watch mode enabled and link it to your Grafana.
35
+ 1. From Grafana Scenes root directory run `./scripts/dev.sh`. This will compile @grafana/scenes with watch mode enabled and link it to your Grafana.
26
36
  1. From Grafana directory run `yarn install`.
27
37
  1. Start Grafana with `scenes` [feature toggle enabled](https://grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/#feature_toggles)
28
38
  1. Navigate to `http://localhost:3000/scenes` to explore demo scenes.
29
39
 
30
- ### Working with Grafana app plugin
40
+ ### Setting up local version of @grafana/scenes with app plugin
31
41
 
32
- 1. Run `YARN_IGNORE_PATH=1 yarn link` from @grafana/scenes directory.
33
- 1. Run `yarn dev` from @grafana/scenes directory.
42
+ 1. Run `YARN_IGNORE_PATH=1 yarn link` from `packages/scenes` directory.
43
+ 1. Run `yarn dev` from `packages/scenes` directory.
34
44
  1. Run `yarn link @grafana/scenes` from app plugin directory.
35
45
  1. Start app plugin development server.
@@ -5,19 +5,20 @@ 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
+ }
8
18
  initUrlSync() {
9
19
  this.urlSyncManager = new UrlSyncManager(this);
10
20
  this.urlSyncManager.initSync();
11
21
  }
12
- activate() {
13
- super.activate();
14
- }
15
- deactivate() {
16
- super.deactivate();
17
- if (this.urlSyncManager) {
18
- this.urlSyncManager.cleanUp();
19
- }
20
- }
21
22
  }
22
23
  EmbeddedScene.Component = EmbeddedSceneRenderer;
23
24
  function EmbeddedSceneRenderer({ model }) {
@@ -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 /**\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 this.urlSyncManager = new UrlSyncManager(this);\n this.urlSyncManager.initSync();\n }\n\n public activate() {\n super.activate();\n }\n\n public deactivate() {\n super.deactivate();\n if (this.urlSyncManager) {\n this.urlSyncManager!.cleanUp();\n }\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,IAAK,IAAA,CAAA,cAAA,GAAiB,IAAI,cAAA,CAAe,IAAI,CAAA,CAAA;AAC7C,IAAA,IAAA,CAAK,eAAe,QAAS,EAAA,CAAA;AAAA,GAC/B;AAAA,EAEO,QAAW,GAAA;AAChB,IAAA,KAAA,CAAM,QAAS,EAAA,CAAA;AAAA,GACjB;AAAA,EAEO,UAAa,GAAA;AAClB,IAAA,KAAA,CAAM,UAAW,EAAA,CAAA;AACjB,IAAA,IAAI,KAAK,cAAgB,EAAA;AACvB,MAAA,IAAA,CAAK,eAAgB,OAAQ,EAAA,CAAA;AAAA,KAC/B;AAAA,GACF;AACF,CAAA;AAzBa,aAAA,CACG,SAAY,GAAA,qBAAA,CAAA;AA0B5B,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
+ {"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 public constructor(state: EmbeddedSceneState) {\n super(state);\n\n this.addActivationHandler(() => {\n // Clean up url sync when the scene is deactivated\n return () => {\n if (this.urlSyncManager) {\n this.urlSyncManager!.cleanUp();\n }\n };\n });\n }\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 this.urlSyncManager = new UrlSyncManager(this);\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,EAK9D,YAAY,KAA2B,EAAA;AAC5C,IAAA,KAAA,CAAM,KAAK,CAAA,CAAA;AAEX,IAAA,IAAA,CAAK,qBAAqB,MAAM;AAE9B,MAAA,OAAO,MAAM;AACX,QAAA,IAAI,KAAK,cAAgB,EAAA;AACvB,UAAA,IAAA,CAAK,eAAgB,OAAQ,EAAA,CAAA;AAAA,SAC/B;AAAA,OACF,CAAA;AAAA,KACD,CAAA,CAAA;AAAA,GACH;AAAA,EAOO,WAAc,GAAA;AACnB,IAAK,IAAA,CAAA,cAAA,GAAiB,IAAI,cAAA,CAAe,IAAI,CAAA,CAAA;AAC7C,IAAA,IAAA,CAAK,eAAe,QAAS,EAAA,CAAA;AAAA,GAC/B;AACF,CAAA;AA3Ba,aAAA,CACG,SAAY,GAAA,qBAAA,CAAA;AA4B5B,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,10 +1,7 @@
1
- import React, { useState, useEffect } from 'react';
2
- import { Switch, Route, useRouteMatch } from 'react-router-dom';
3
- import { PluginPage } from '@grafana/runtime';
1
+ import React from 'react';
2
+ import { Switch, Route } from 'react-router-dom';
4
3
  import { SceneObjectBase } from '../../core/SceneObjectBase.js';
5
- import { useAppQueryParams, getLinkUrlWithAppUrlState } from './utils.js';
6
4
 
7
- const sceneCache = /* @__PURE__ */ new Map();
8
5
  class SceneApp extends SceneObjectBase {
9
6
  }
10
7
  SceneApp.Component = ({ model }) => {
@@ -20,145 +17,6 @@ SceneApp.Component = ({ model }) => {
20
17
  }
21
18
  })));
22
19
  };
23
- class SceneAppPage extends SceneObjectBase {
24
- }
25
- SceneAppPage.Component = SceneAppPageRenderer;
26
- function SceneAppPageRenderer({ model }) {
27
- var _a;
28
- const { tabs, drilldowns, url, routePath } = model.state;
29
- const routes = [];
30
- if (tabs) {
31
- for (const page2 of tabs) {
32
- routes.push(
33
- /* @__PURE__ */ React.createElement(Route, {
34
- exact: true,
35
- key: page2.state.url,
36
- path: (_a = page2.state.routePath) != null ? _a : page2.state.url,
37
- render: () => {
38
- return /* @__PURE__ */ React.createElement(page2.Component, {
39
- model: page2
40
- });
41
- }
42
- })
43
- );
44
- if (page2.state.drilldowns) {
45
- for (const drilldown of page2.state.drilldowns) {
46
- routes.push(
47
- /* @__PURE__ */ React.createElement(Route, {
48
- exact: false,
49
- key: drilldown.routePath,
50
- path: drilldown.routePath,
51
- render: () => {
52
- return /* @__PURE__ */ React.createElement(SceneAppDrilldownViewRender, {
53
- drilldown,
54
- parent: page2
55
- });
56
- }
57
- })
58
- );
59
- }
60
- }
61
- }
62
- return /* @__PURE__ */ React.createElement(Switch, null, routes);
63
- }
64
- if (drilldowns) {
65
- for (const drilldown of drilldowns) {
66
- routes.push(
67
- /* @__PURE__ */ React.createElement(Route, {
68
- key: drilldown.routePath,
69
- exact: false,
70
- path: drilldown.routePath,
71
- render: () => {
72
- return /* @__PURE__ */ React.createElement(SceneAppDrilldownViewRender, {
73
- drilldown,
74
- parent: model
75
- });
76
- }
77
- })
78
- );
79
- }
80
- }
81
- let page = /* @__PURE__ */ React.createElement(ScenePageRenderer, {
82
- page: model
83
- });
84
- if (model.parent instanceof SceneAppPage) {
85
- page = /* @__PURE__ */ React.createElement(ScenePageRenderer, {
86
- page: model.parent,
87
- activeTab: model,
88
- tabs: model.parent.state.tabs
89
- });
90
- }
91
- return /* @__PURE__ */ React.createElement(Switch, null, /* @__PURE__ */ React.createElement(Route, {
92
- key: url,
93
- exact: true,
94
- path: routePath != null ? routePath : url,
95
- render: () => {
96
- return page;
97
- }
98
- }), routes);
99
- }
100
- function ScenePageRenderer({ page, tabs, activeTab }) {
101
- const [isInitialized, setIsInitialized] = useState(false);
102
- const params = useAppQueryParams();
103
- const routeMatch = useRouteMatch();
104
- let scene = sceneCache.get(routeMatch.url);
105
- if (!scene) {
106
- scene = activeTab ? activeTab.state.getScene(routeMatch) : page.state.getScene(routeMatch);
107
- sceneCache.set(routeMatch.url, scene);
108
- }
109
- useEffect(() => {
110
- if (!isInitialized && scene) {
111
- scene.initUrlSync();
112
- setIsInitialized(true);
113
- }
114
- }, [isInitialized, scene]);
115
- if (!isInitialized) {
116
- return null;
117
- }
118
- const pageNav = {
119
- text: page.state.title,
120
- subTitle: page.state.subTitle,
121
- url: getLinkUrlWithAppUrlState(page.state.url, params, page.state.preserveUrlKeys),
122
- hideFromBreadcrumbs: page.state.hideFromBreadcrumbs,
123
- parentItem: getParentBreadcrumbs(page.state.getParentPage ? page.state.getParentPage() : page.parent, params)
124
- };
125
- if (tabs) {
126
- pageNav.children = tabs.map((tab) => {
127
- return {
128
- text: tab.state.title,
129
- active: activeTab === tab,
130
- url: getLinkUrlWithAppUrlState(tab.state.url, params, tab.state.preserveUrlKeys),
131
- parentItem: pageNav
132
- };
133
- });
134
- }
135
- return /* @__PURE__ */ React.createElement(PluginPage, {
136
- pageNav
137
- }, /* @__PURE__ */ React.createElement(scene.Component, {
138
- model: scene
139
- }));
140
- }
141
- function SceneAppDrilldownViewRender(props) {
142
- const routeMatch = useRouteMatch();
143
- const scene = props.drilldown.getPage(routeMatch, props.parent);
144
- return /* @__PURE__ */ React.createElement(scene.Component, {
145
- model: scene
146
- });
147
- }
148
- function getParentBreadcrumbs(parent, params) {
149
- if (parent instanceof SceneAppPage) {
150
- return {
151
- text: parent.state.title,
152
- url: getLinkUrlWithAppUrlState(parent.state.url, params, parent.state.preserveUrlKeys),
153
- hideFromBreadcrumbs: parent.state.hideFromBreadcrumbs,
154
- parentItem: getParentBreadcrumbs(
155
- parent.state.getParentPage ? parent.state.getParentPage() : parent.parent,
156
- params
157
- )
158
- };
159
- }
160
- return void 0;
161
- }
162
20
 
163
- export { SceneApp, SceneAppDrilldownViewRender, SceneAppPage };
21
+ export { SceneApp };
164
22
  //# sourceMappingURL=SceneApp.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"SceneApp.js","sources":["../../../../src/components/SceneApp/SceneApp.tsx"],"sourcesContent":["import React, { useEffect, useState } from 'react';\nimport { Route, Switch, useRouteMatch } from 'react-router-dom';\n\nimport { NavModelItem, UrlQueryMap } from '@grafana/data';\nimport { PluginPage } from '@grafana/runtime';\n\nimport { SceneComponentProps, SceneObject, SceneObjectStatePlain } from '../../core/types';\nimport { SceneObjectBase } from '../../core/SceneObjectBase';\nimport { getLinkUrlWithAppUrlState, useAppQueryParams } from './utils';\nimport { EmbeddedScene } from '../EmbeddedScene';\n\nconst sceneCache = new Map<string, EmbeddedScene>();\n\nexport interface SceneAppState extends SceneObjectStatePlain {\n // Array of SceneAppPage objects that are considered app's top level pages\n pages: SceneAppPage[];\n}\n\nexport interface SceneRouteMatch<Params extends { [K in keyof Params]?: string } = {}> {\n params: Params;\n isExact: boolean;\n path: string;\n url: string;\n}\n\nexport interface SceneAppRoute {\n path: string;\n page?: SceneAppPage;\n drilldown?: SceneAppDrilldownView;\n}\n\n/**\n * Responsible for top level pages routing\n */\nexport class SceneApp extends SceneObjectBase<SceneAppState> {\n public static Component = ({ model }: SceneComponentProps<SceneApp>) => {\n const { pages } = model.useState();\n\n return (\n <Switch>\n {pages.map((page) => (\n <Route\n key={page.state.url}\n exact={false}\n path={page.state.url}\n render={() => {\n return page && <page.Component model={page} />;\n }}\n ></Route>\n ))}\n </Switch>\n );\n };\n}\n\nexport interface SceneAppPageState extends SceneObjectStatePlain {\n title: string;\n subTitle?: string;\n // Use to provide page absolute URL, i.e. /app/overview\n url: string;\n // Use to provide parametrized page URL, i.e. /app/overview/:clusterId\n routePath?: string;\n // Whether or not page should be visible in the breadcrumbs path\n hideFromBreadcrumbs?: boolean;\n // Array of SceneAppPage objects that are used as page tabs displayed on top of the page\n tabs?: SceneAppPage[];\n // Function that returns a scene object for the page\n getScene: (routeMatch: SceneRouteMatch) => EmbeddedScene;\n // Array of scenes used for drilldown views\n drilldowns?: SceneAppDrilldownView[];\n // Function that returns a parent page object, used to create breadcrumbs structure\n getParentPage?: () => SceneAppPage;\n // Array of query params that will be preserved in breadcrumb and page tab links, i.e. ['from', 'to', 'var-datacenter',...]\n preserveUrlKeys?: string[];\n}\n\n/**\n * Responsible for page's drilldown & tabs routing\n */\nexport class SceneAppPage extends SceneObjectBase<SceneAppPageState> {\n public static Component = SceneAppPageRenderer;\n}\n\nfunction SceneAppPageRenderer({ model }: SceneComponentProps<SceneAppPage>) {\n const { tabs, drilldowns, url, routePath } = model.state;\n const routes: React.ReactNode[] = [];\n\n if (tabs) {\n for (const page of tabs) {\n routes.push(\n <Route\n exact={true}\n key={page.state.url}\n path={page.state.routePath ?? page.state.url}\n render={() => {\n return <page.Component model={page} />;\n }}\n ></Route>\n );\n\n if (page.state.drilldowns) {\n for (const drilldown of page.state.drilldowns) {\n routes.push(\n <Route\n exact={false}\n key={drilldown.routePath}\n path={drilldown.routePath}\n render={() => {\n return <SceneAppDrilldownViewRender drilldown={drilldown} parent={page} />;\n }}\n ></Route>\n );\n }\n }\n }\n\n return <Switch>{routes}</Switch>;\n }\n\n if (drilldowns) {\n for (const drilldown of drilldowns) {\n routes.push(\n <Route\n key={drilldown.routePath}\n exact={false}\n path={drilldown.routePath}\n render={() => {\n return <SceneAppDrilldownViewRender drilldown={drilldown} parent={model} />;\n }}\n ></Route>\n );\n }\n }\n\n let page = <ScenePageRenderer page={model} />;\n\n // if parent is a SceneAppPage we are a tab\n if (model.parent instanceof SceneAppPage) {\n page = <ScenePageRenderer page={model.parent} activeTab={model} tabs={model.parent.state.tabs} />;\n }\n\n return (\n <Switch>\n {/* page route */}\n <Route\n key={url}\n exact={true}\n path={routePath ?? url}\n render={() => {\n return page;\n }}\n ></Route>\n\n {/* drilldown routes */}\n {routes}\n </Switch>\n );\n}\n\ninterface ScenePageRenderProps {\n page: SceneAppPage;\n tabs?: SceneAppPage[];\n activeTab?: SceneAppPage;\n}\n\nfunction ScenePageRenderer({ page, tabs, activeTab }: ScenePageRenderProps) {\n /**\n * We use this flag to make sure the URL sync is enabled before the scene is actually rendered.\n */\n const [isInitialized, setIsInitialized] = useState(false);\n const params = useAppQueryParams();\n const routeMatch = useRouteMatch();\n\n let scene = sceneCache.get(routeMatch!.url);\n if (!scene) {\n // If we are rendering a tab, we need to get the scene f rom the tab, otherwise, use page's scene\n scene = activeTab ? activeTab.state.getScene(routeMatch) : page.state.getScene(routeMatch);\n sceneCache.set(routeMatch!.url, scene);\n }\n\n useEffect(() => {\n // Before rendering scene components, we are making sure the URL sync is enabled for.\n if (!isInitialized && scene) {\n scene.initUrlSync();\n setIsInitialized(true);\n }\n }, [isInitialized, scene]);\n\n if (!isInitialized) {\n return null;\n }\n\n const pageNav: NavModelItem = {\n text: page.state.title,\n subTitle: page.state.subTitle,\n url: getLinkUrlWithAppUrlState(page.state.url, params, page.state.preserveUrlKeys),\n hideFromBreadcrumbs: page.state.hideFromBreadcrumbs,\n parentItem: getParentBreadcrumbs(page.state.getParentPage ? page.state.getParentPage() : page.parent, params),\n };\n\n if (tabs) {\n pageNav.children = tabs.map((tab) => {\n return {\n text: tab.state.title,\n active: activeTab === tab,\n url: getLinkUrlWithAppUrlState(tab.state.url, params, tab.state.preserveUrlKeys),\n parentItem: pageNav,\n };\n });\n }\n\n return (\n <PluginPage pageNav={pageNav} /*hideFooter={true}*/>\n <scene.Component model={scene} />\n </PluginPage>\n );\n}\n\nexport interface SceneAppDrilldownView {\n // Use to provide parametrized drilldown URL, i.e. /app/clusters/:clusterId\n routePath: string;\n // Function that returns a page object for a given drilldown route match. Use parent to configure drilldown view parent SceneAppPage via getParentPage method.\n getPage: (routeMatch: SceneRouteMatch<any>, parent: SceneAppPage) => SceneAppPage;\n}\n\nexport function SceneAppDrilldownViewRender(props: { drilldown: SceneAppDrilldownView; parent: SceneAppPage }) {\n const routeMatch = useRouteMatch();\n const scene = props.drilldown.getPage(routeMatch, props.parent);\n return <scene.Component model={scene} />;\n}\n\nfunction getParentBreadcrumbs(parent: SceneObject | undefined, params: UrlQueryMap): NavModelItem | undefined {\n if (parent instanceof SceneAppPage) {\n return {\n text: parent.state.title,\n url: getLinkUrlWithAppUrlState(parent.state.url, params, parent.state.preserveUrlKeys),\n hideFromBreadcrumbs: parent.state.hideFromBreadcrumbs,\n parentItem: getParentBreadcrumbs(\n parent.state.getParentPage ? parent.state.getParentPage() : parent.parent,\n params\n ),\n };\n }\n\n return undefined;\n}\n"],"names":["page"],"mappings":"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"}
1
+ {"version":3,"file":"SceneApp.js","sources":["../../../../src/components/SceneApp/SceneApp.tsx"],"sourcesContent":["import React from 'react';\nimport { Route, Switch } from 'react-router-dom';\n\nimport { SceneComponentProps } from '../../core/types';\nimport { SceneObjectBase } from '../../core/SceneObjectBase';\nimport { SceneAppState } from './types';\n\n/**\n * Responsible for top level pages routing\n */\nexport class SceneApp extends SceneObjectBase<SceneAppState> {\n public static Component = ({ model }: SceneComponentProps<SceneApp>) => {\n const { pages } = model.useState();\n\n return (\n <Switch>\n {pages.map((page) => (\n <Route\n key={page.state.url}\n exact={false}\n path={page.state.url}\n render={() => {\n return page && <page.Component model={page} />;\n }}\n ></Route>\n ))}\n </Switch>\n );\n };\n}\n"],"names":[],"mappings":";;;;AAUO,MAAM,iBAAiB,eAA+B,CAAA;AAmB7D,CAAA;AAnBa,QAAA,CACG,SAAY,GAAA,CAAC,EAAE,KAAA,EAA2C,KAAA;AACtE,EAAA,MAAM,EAAE,KAAA,EAAU,GAAA,KAAA,CAAM,QAAS,EAAA,CAAA;AAEjC,EAAA,2CACG,MACE,EAAA,IAAA,EAAA,KAAA,CAAM,GAAI,CAAA,CAAC,yBACT,KAAA,CAAA,aAAA,CAAA,KAAA,EAAA;AAAA,IACC,GAAA,EAAK,KAAK,KAAM,CAAA,GAAA;AAAA,IAChB,KAAO,EAAA,KAAA;AAAA,IACP,IAAA,EAAM,KAAK,KAAM,CAAA,GAAA;AAAA,IACjB,QAAQ,MAAM;AACZ,MAAO,OAAA,IAAA,oBAAS,KAAA,CAAA,aAAA,CAAA,IAAA,CAAK,SAAL,EAAA;AAAA,QAAe,KAAO,EAAA,IAAA;AAAA,OAAM,CAAA,CAAA;AAAA,KAC9C;AAAA,GACD,CACF,CACH,CAAA,CAAA;AAEJ,CAAA;;;;"}
@@ -0,0 +1,151 @@
1
+ import React, { useState, useEffect } from 'react';
2
+ import { PluginPage } from '@grafana/runtime';
3
+ import { Route, Switch, useRouteMatch } from 'react-router-dom';
4
+ import { SceneObjectBase } from '../../core/SceneObjectBase.js';
5
+ import { useAppQueryParams, getLinkUrlWithAppUrlState } from './utils.js';
6
+
7
+ const sceneCache = /* @__PURE__ */ new Map();
8
+ class SceneAppPage extends SceneObjectBase {
9
+ }
10
+ SceneAppPage.Component = SceneAppPageRenderer;
11
+ function SceneAppPageRenderer({ model }) {
12
+ var _a;
13
+ const { tabs, drilldowns, url, routePath } = model.state;
14
+ const routes = [];
15
+ if (tabs) {
16
+ for (const page2 of tabs) {
17
+ routes.push(
18
+ /* @__PURE__ */ React.createElement(Route, {
19
+ exact: true,
20
+ key: page2.state.url,
21
+ path: (_a = page2.state.routePath) != null ? _a : page2.state.url,
22
+ render: () => {
23
+ return /* @__PURE__ */ React.createElement(page2.Component, {
24
+ model: page2
25
+ });
26
+ }
27
+ })
28
+ );
29
+ if (page2.state.drilldowns) {
30
+ for (const drilldown of page2.state.drilldowns) {
31
+ routes.push(
32
+ /* @__PURE__ */ React.createElement(Route, {
33
+ exact: false,
34
+ key: drilldown.routePath,
35
+ path: drilldown.routePath,
36
+ render: () => {
37
+ return /* @__PURE__ */ React.createElement(SceneAppDrilldownViewRender, {
38
+ drilldown,
39
+ parent: page2
40
+ });
41
+ }
42
+ })
43
+ );
44
+ }
45
+ }
46
+ }
47
+ return /* @__PURE__ */ React.createElement(Switch, null, routes);
48
+ }
49
+ if (drilldowns) {
50
+ for (const drilldown of drilldowns) {
51
+ routes.push(
52
+ /* @__PURE__ */ React.createElement(Route, {
53
+ key: drilldown.routePath,
54
+ exact: false,
55
+ path: drilldown.routePath,
56
+ render: () => {
57
+ return /* @__PURE__ */ React.createElement(SceneAppDrilldownViewRender, {
58
+ drilldown,
59
+ parent: model
60
+ });
61
+ }
62
+ })
63
+ );
64
+ }
65
+ }
66
+ let page = /* @__PURE__ */ React.createElement(ScenePageRenderer, {
67
+ page: model
68
+ });
69
+ if (model.parent instanceof SceneAppPage) {
70
+ page = /* @__PURE__ */ React.createElement(ScenePageRenderer, {
71
+ page: model.parent,
72
+ activeTab: model,
73
+ tabs: model.parent.state.tabs
74
+ });
75
+ }
76
+ return /* @__PURE__ */ React.createElement(Switch, null, /* @__PURE__ */ React.createElement(Route, {
77
+ key: url,
78
+ exact: true,
79
+ path: routePath != null ? routePath : url,
80
+ render: () => {
81
+ return page;
82
+ }
83
+ }), routes);
84
+ }
85
+ function ScenePageRenderer({ page, tabs, activeTab }) {
86
+ const [isInitialized, setIsInitialized] = useState(false);
87
+ const params = useAppQueryParams();
88
+ const routeMatch = useRouteMatch();
89
+ let scene = sceneCache.get(routeMatch.url);
90
+ if (!scene) {
91
+ scene = activeTab ? activeTab.state.getScene(routeMatch) : page.state.getScene(routeMatch);
92
+ sceneCache.set(routeMatch.url, scene);
93
+ }
94
+ useEffect(() => {
95
+ if (!isInitialized && scene) {
96
+ scene.initUrlSync();
97
+ setIsInitialized(true);
98
+ }
99
+ }, [isInitialized, scene]);
100
+ if (!isInitialized) {
101
+ return null;
102
+ }
103
+ const pageNav = {
104
+ text: page.state.title,
105
+ subTitle: page.state.subTitle,
106
+ img: page.state.titleImg,
107
+ icon: page.state.titleIcon,
108
+ url: getLinkUrlWithAppUrlState(page.state.url, params, page.state.preserveUrlKeys),
109
+ hideFromBreadcrumbs: page.state.hideFromBreadcrumbs,
110
+ parentItem: getParentBreadcrumbs(page.state.getParentPage ? page.state.getParentPage() : page.parent, params)
111
+ };
112
+ if (tabs) {
113
+ pageNav.children = tabs.map((tab) => {
114
+ return {
115
+ text: tab.state.title,
116
+ active: activeTab === tab,
117
+ url: getLinkUrlWithAppUrlState(tab.state.url, params, tab.state.preserveUrlKeys),
118
+ parentItem: pageNav
119
+ };
120
+ });
121
+ }
122
+ return /* @__PURE__ */ React.createElement(PluginPage, {
123
+ pageNav
124
+ }, /* @__PURE__ */ React.createElement(scene.Component, {
125
+ model: scene
126
+ }));
127
+ }
128
+ function SceneAppDrilldownViewRender(props) {
129
+ const routeMatch = useRouteMatch();
130
+ const scene = props.drilldown.getPage(routeMatch, props.parent);
131
+ return /* @__PURE__ */ React.createElement(scene.Component, {
132
+ model: scene
133
+ });
134
+ }
135
+ function getParentBreadcrumbs(parent, params) {
136
+ if (parent instanceof SceneAppPage) {
137
+ return {
138
+ text: parent.state.title,
139
+ url: getLinkUrlWithAppUrlState(parent.state.url, params, parent.state.preserveUrlKeys),
140
+ hideFromBreadcrumbs: parent.state.hideFromBreadcrumbs,
141
+ parentItem: getParentBreadcrumbs(
142
+ parent.state.getParentPage ? parent.state.getParentPage() : parent.parent,
143
+ params
144
+ )
145
+ };
146
+ }
147
+ return void 0;
148
+ }
149
+
150
+ export { SceneAppPage };
151
+ //# sourceMappingURL=SceneAppPage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SceneAppPage.js","sources":["../../../../src/components/SceneApp/SceneAppPage.tsx"],"sourcesContent":["import React, { useState, useEffect } from 'react';\nimport { NavModelItem, UrlQueryMap } from '@grafana/data';\nimport { PluginPage } from '@grafana/runtime';\nimport { Route, Switch, useRouteMatch } from 'react-router-dom';\nimport { SceneObjectBase } from '../../core/SceneObjectBase';\nimport { SceneComponentProps, SceneObject } from '../../core/types';\nimport { EmbeddedScene } from '../EmbeddedScene';\nimport { SceneAppDrilldownView, SceneAppPageLike, SceneAppPageState } from './types';\nimport { getLinkUrlWithAppUrlState, useAppQueryParams } from './utils';\n\nconst sceneCache = new Map<string, EmbeddedScene>();\n\n/**\n * Responsible for page's drilldown & tabs routing\n */\nexport class SceneAppPage extends SceneObjectBase<SceneAppPageState> {\n public static Component = SceneAppPageRenderer;\n}\n\nfunction SceneAppPageRenderer({ model }: SceneComponentProps<SceneAppPage>) {\n const { tabs, drilldowns, url, routePath } = model.state;\n const routes: React.ReactNode[] = [];\n\n if (tabs) {\n for (const page of tabs) {\n routes.push(\n <Route\n exact={true}\n key={page.state.url}\n path={page.state.routePath ?? page.state.url}\n render={() => {\n return <page.Component model={page} />;\n }}\n ></Route>\n );\n\n if (page.state.drilldowns) {\n for (const drilldown of page.state.drilldowns) {\n routes.push(\n <Route\n exact={false}\n key={drilldown.routePath}\n path={drilldown.routePath}\n render={() => {\n return <SceneAppDrilldownViewRender drilldown={drilldown} parent={page} />;\n }}\n ></Route>\n );\n }\n }\n }\n\n return <Switch>{routes}</Switch>;\n }\n\n if (drilldowns) {\n for (const drilldown of drilldowns) {\n routes.push(\n <Route\n key={drilldown.routePath}\n exact={false}\n path={drilldown.routePath}\n render={() => {\n return <SceneAppDrilldownViewRender drilldown={drilldown} parent={model} />;\n }}\n ></Route>\n );\n }\n }\n\n let page = <ScenePageRenderer page={model} />;\n\n // if parent is a SceneAppPage we are a tab\n if (model.parent instanceof SceneAppPage) {\n page = <ScenePageRenderer page={model.parent} activeTab={model} tabs={model.parent.state.tabs} />;\n }\n\n return (\n <Switch>\n {/* page route */}\n <Route\n key={url}\n exact={true}\n path={routePath ?? url}\n render={() => {\n return page;\n }}\n ></Route>\n\n {/* drilldown routes */}\n {routes}\n </Switch>\n );\n}\n\ninterface ScenePageRenderProps {\n page: SceneAppPageLike;\n tabs?: SceneAppPageLike[];\n activeTab?: SceneAppPage;\n}\n\nfunction ScenePageRenderer({ page, tabs, activeTab }: ScenePageRenderProps) {\n /**\n * We use this flag to make sure the URL sync is enabled before the scene is actually rendered.\n */\n const [isInitialized, setIsInitialized] = useState(false);\n const params = useAppQueryParams();\n const routeMatch = useRouteMatch();\n\n let scene = sceneCache.get(routeMatch!.url);\n if (!scene) {\n // If we are rendering a tab, we need to get the scene f rom the tab, otherwise, use page's scene\n scene = activeTab ? activeTab.state.getScene(routeMatch) : page.state.getScene(routeMatch);\n sceneCache.set(routeMatch!.url, scene);\n }\n\n useEffect(() => {\n // Before rendering scene components, we are making sure the URL sync is enabled for.\n if (!isInitialized && scene) {\n scene.initUrlSync();\n setIsInitialized(true);\n }\n }, [isInitialized, scene]);\n\n if (!isInitialized) {\n return null;\n }\n\n const pageNav: NavModelItem = {\n text: page.state.title,\n subTitle: page.state.subTitle,\n img: page.state.titleImg,\n icon: page.state.titleIcon,\n url: getLinkUrlWithAppUrlState(page.state.url, params, page.state.preserveUrlKeys),\n hideFromBreadcrumbs: page.state.hideFromBreadcrumbs,\n parentItem: getParentBreadcrumbs(page.state.getParentPage ? page.state.getParentPage() : page.parent, params),\n };\n\n if (tabs) {\n pageNav.children = tabs.map((tab) => {\n return {\n text: tab.state.title,\n active: activeTab === tab,\n url: getLinkUrlWithAppUrlState(tab.state.url, params, tab.state.preserveUrlKeys),\n parentItem: pageNav,\n };\n });\n }\n\n return (\n <PluginPage pageNav={pageNav}>\n <scene.Component model={scene} />\n </PluginPage>\n );\n}\n\nfunction SceneAppDrilldownViewRender(props: { drilldown: SceneAppDrilldownView; parent: SceneAppPageLike }) {\n const routeMatch = useRouteMatch();\n const scene = props.drilldown.getPage(routeMatch, props.parent);\n return <scene.Component model={scene} />;\n}\n\nfunction getParentBreadcrumbs(parent: SceneObject | undefined, params: UrlQueryMap): NavModelItem | undefined {\n if (parent instanceof SceneAppPage) {\n return {\n text: parent.state.title,\n url: getLinkUrlWithAppUrlState(parent.state.url, params, parent.state.preserveUrlKeys),\n hideFromBreadcrumbs: parent.state.hideFromBreadcrumbs,\n parentItem: getParentBreadcrumbs(\n parent.state.getParentPage ? parent.state.getParentPage() : parent.parent,\n params\n ),\n };\n }\n\n return undefined;\n}\n"],"names":["page"],"mappings":"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"}
@@ -4,18 +4,18 @@ import { SceneObjectBase } from '../core/SceneObjectBase.js';
4
4
  import { sceneGraph } from '../core/sceneGraph.js';
5
5
 
6
6
  class SceneByFrameRepeater extends SceneObjectBase {
7
- activate() {
8
- super.activate();
9
- this._subs.add(
10
- sceneGraph.getData(this).subscribeToState({
11
- next: (data) => {
7
+ constructor(state) {
8
+ super(state);
9
+ this.addActivationHandler(() => {
10
+ this._subs.add(
11
+ sceneGraph.getData(this).subscribeToState((data) => {
12
12
  var _a;
13
13
  if (((_a = data.data) == null ? void 0 : _a.state) === LoadingState.Done) {
14
14
  this.performRepeat(data.data);
15
15
  }
16
- }
17
- })
18
- );
16
+ })
17
+ );
18
+ });
19
19
  }
20
20
  performRepeat(data) {
21
21
  const newChildren = [];
@@ -1 +1 @@
1
- {"version":3,"file":"SceneByFrameRepeater.js","sources":["../../../src/components/SceneByFrameRepeater.tsx"],"sourcesContent":["import React from 'react';\n\nimport { LoadingState, PanelData, DataFrame } from '@grafana/data';\n\nimport { SceneObjectBase } from '../core/SceneObjectBase';\nimport { sceneGraph } from '../core/sceneGraph';\nimport {\n SceneComponentProps,\n SceneObject,\n SceneObjectStatePlain,\n SceneLayoutState,\n SceneLayoutChild,\n} from '../core/types';\n\ninterface RepeatOptions extends SceneObjectStatePlain {\n body: SceneObject<SceneLayoutState>;\n getLayoutChild(data: PanelData, frame: DataFrame, frameIndex: number): SceneLayoutChild;\n}\n\nexport class SceneByFrameRepeater extends SceneObjectBase<RepeatOptions> {\n public activate(): void {\n super.activate();\n\n this._subs.add(\n sceneGraph.getData(this).subscribeToState({\n next: (data) => {\n if (data.data?.state === LoadingState.Done) {\n this.performRepeat(data.data);\n }\n },\n })\n );\n }\n\n private performRepeat(data: PanelData) {\n const newChildren: SceneLayoutChild[] = [];\n\n for (let seriesIndex = 0; seriesIndex < data.series.length; seriesIndex++) {\n const layoutChild = this.state.getLayoutChild(data, data.series[seriesIndex], seriesIndex);\n newChildren.push(layoutChild);\n }\n\n this.state.body.setState({ children: newChildren });\n }\n\n public static Component = ({ model, isEditing }: SceneComponentProps<SceneByFrameRepeater>) => {\n const { body } = model.useState();\n return <body.Component model={body} isEditing={isEditing} />;\n };\n}\n"],"names":[],"mappings":";;;;;AAmBO,MAAM,6BAA6B,eAA+B,CAAA;AAAA,EAChE,QAAiB,GAAA;AACtB,IAAA,KAAA,CAAM,QAAS,EAAA,CAAA;AAEf,IAAA,IAAA,CAAK,KAAM,CAAA,GAAA;AAAA,MACT,UAAW,CAAA,OAAA,CAAQ,IAAI,CAAA,CAAE,gBAAiB,CAAA;AAAA,QACxC,IAAA,EAAM,CAAC,IAAS,KAAA;AAzBxB,UAAA,IAAA,EAAA,CAAA;AA0BU,UAAA,IAAA,CAAA,CAAI,EAAK,GAAA,IAAA,CAAA,IAAA,KAAL,IAAW,GAAA,KAAA,CAAA,GAAA,EAAA,CAAA,KAAA,MAAU,aAAa,IAAM,EAAA;AAC1C,YAAK,IAAA,CAAA,aAAA,CAAc,KAAK,IAAI,CAAA,CAAA;AAAA,WAC9B;AAAA,SACF;AAAA,OACD,CAAA;AAAA,KACH,CAAA;AAAA,GACF;AAAA,EAEQ,cAAc,IAAiB,EAAA;AACrC,IAAA,MAAM,cAAkC,EAAC,CAAA;AAEzC,IAAA,KAAA,IAAS,cAAc,CAAG,EAAA,WAAA,GAAc,IAAK,CAAA,MAAA,CAAO,QAAQ,WAAe,EAAA,EAAA;AACzE,MAAM,MAAA,WAAA,GAAc,KAAK,KAAM,CAAA,cAAA,CAAe,MAAM,IAAK,CAAA,MAAA,CAAO,cAAc,WAAW,CAAA,CAAA;AACzF,MAAA,WAAA,CAAY,KAAK,WAAW,CAAA,CAAA;AAAA,KAC9B;AAEA,IAAA,IAAA,CAAK,MAAM,IAAK,CAAA,QAAA,CAAS,EAAE,QAAA,EAAU,aAAa,CAAA,CAAA;AAAA,GACpD;AAMF,CAAA;AA9Ba,oBAAA,CA0BG,SAAY,GAAA,CAAC,EAAE,KAAA,EAAO,WAA2D,KAAA;AAC7F,EAAA,MAAM,EAAE,IAAA,EAAS,GAAA,KAAA,CAAM,QAAS,EAAA,CAAA;AAChC,EAAO,uBAAA,KAAA,CAAA,aAAA,CAAC,KAAK,SAAL,EAAA;AAAA,IAAe,KAAO,EAAA,IAAA;AAAA,IAAM,SAAA;AAAA,GAAsB,CAAA,CAAA;AAC5D,CAAA;;;;"}
1
+ {"version":3,"file":"SceneByFrameRepeater.js","sources":["../../../src/components/SceneByFrameRepeater.tsx"],"sourcesContent":["import React from 'react';\n\nimport { LoadingState, PanelData, DataFrame } from '@grafana/data';\n\nimport { SceneObjectBase } from '../core/SceneObjectBase';\nimport { sceneGraph } from '../core/sceneGraph';\nimport {\n SceneComponentProps,\n SceneObject,\n SceneObjectStatePlain,\n SceneLayoutState,\n SceneLayoutChild,\n} from '../core/types';\n\ninterface SceneByFrameRepeaterState extends SceneObjectStatePlain {\n body: SceneObject<SceneLayoutState>;\n getLayoutChild(data: PanelData, frame: DataFrame, frameIndex: number): SceneLayoutChild;\n}\n\nexport class SceneByFrameRepeater extends SceneObjectBase<SceneByFrameRepeaterState> {\n public constructor(state: SceneByFrameRepeaterState) {\n super(state);\n\n this.addActivationHandler(() => {\n this._subs.add(\n sceneGraph.getData(this).subscribeToState((data) => {\n if (data.data?.state === LoadingState.Done) {\n this.performRepeat(data.data);\n }\n })\n );\n });\n }\n\n private performRepeat(data: PanelData) {\n const newChildren: SceneLayoutChild[] = [];\n\n for (let seriesIndex = 0; seriesIndex < data.series.length; seriesIndex++) {\n const layoutChild = this.state.getLayoutChild(data, data.series[seriesIndex], seriesIndex);\n newChildren.push(layoutChild);\n }\n\n this.state.body.setState({ children: newChildren });\n }\n\n public static Component = ({ model, isEditing }: SceneComponentProps<SceneByFrameRepeater>) => {\n const { body } = model.useState();\n return <body.Component model={body} isEditing={isEditing} />;\n };\n}\n"],"names":[],"mappings":";;;;;AAmBO,MAAM,6BAA6B,eAA2C,CAAA;AAAA,EAC5E,YAAY,KAAkC,EAAA;AACnD,IAAA,KAAA,CAAM,KAAK,CAAA,CAAA;AAEX,IAAA,IAAA,CAAK,qBAAqB,MAAM;AAC9B,MAAA,IAAA,CAAK,KAAM,CAAA,GAAA;AAAA,QACT,WAAW,OAAQ,CAAA,IAAI,CAAE,CAAA,gBAAA,CAAiB,CAAC,IAAS,KAAA;AAzB5D,UAAA,IAAA,EAAA,CAAA;AA0BU,UAAA,IAAA,CAAA,CAAI,EAAK,GAAA,IAAA,CAAA,IAAA,KAAL,IAAW,GAAA,KAAA,CAAA,GAAA,EAAA,CAAA,KAAA,MAAU,aAAa,IAAM,EAAA;AAC1C,YAAK,IAAA,CAAA,aAAA,CAAc,KAAK,IAAI,CAAA,CAAA;AAAA,WAC9B;AAAA,SACD,CAAA;AAAA,OACH,CAAA;AAAA,KACD,CAAA,CAAA;AAAA,GACH;AAAA,EAEQ,cAAc,IAAiB,EAAA;AACrC,IAAA,MAAM,cAAkC,EAAC,CAAA;AAEzC,IAAA,KAAA,IAAS,cAAc,CAAG,EAAA,WAAA,GAAc,IAAK,CAAA,MAAA,CAAO,QAAQ,WAAe,EAAA,EAAA;AACzE,MAAM,MAAA,WAAA,GAAc,KAAK,KAAM,CAAA,cAAA,CAAe,MAAM,IAAK,CAAA,MAAA,CAAO,cAAc,WAAW,CAAA,CAAA;AACzF,MAAA,WAAA,CAAY,KAAK,WAAW,CAAA,CAAA;AAAA,KAC9B;AAEA,IAAA,IAAA,CAAK,MAAM,IAAK,CAAA,QAAA,CAAS,EAAE,QAAA,EAAU,aAAa,CAAA,CAAA;AAAA,GACpD;AAMF,CAAA;AA9Ba,oBAAA,CA0BG,SAAY,GAAA,CAAC,EAAE,KAAA,EAAO,WAA2D,KAAA;AAC7F,EAAA,MAAM,EAAE,IAAA,EAAS,GAAA,KAAA,CAAM,QAAS,EAAA,CAAA;AAChC,EAAO,uBAAA,KAAA,CAAA,aAAA,CAAC,KAAK,SAAL,EAAA;AAAA,IAAe,KAAO,EAAA,IAAA;AAAA,IAAM,SAAA;AAAA,GAAsB,CAAA,CAAA;AAC5D,CAAA;;;;"}
@@ -0,0 +1,34 @@
1
+ import React from 'react';
2
+ import { SceneObjectBase } from '../core/SceneObjectBase.js';
3
+
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
8
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
9
+ var __spreadValues = (a, b) => {
10
+ for (var prop in b || (b = {}))
11
+ if (__hasOwnProp.call(b, prop))
12
+ __defNormalProp(a, prop, b[prop]);
13
+ if (__getOwnPropSymbols)
14
+ for (var prop of __getOwnPropSymbols(b)) {
15
+ if (__propIsEnum.call(b, prop))
16
+ __defNormalProp(a, prop, b[prop]);
17
+ }
18
+ return a;
19
+ };
20
+ class SceneReactObject extends SceneObjectBase {
21
+ }
22
+ SceneReactObject.Component = ({ model }) => {
23
+ const { component: Component, props, reactNode } = model.useState();
24
+ if (Component) {
25
+ return /* @__PURE__ */ React.createElement(Component, __spreadValues({}, props));
26
+ }
27
+ if (reactNode) {
28
+ return reactNode;
29
+ }
30
+ return null;
31
+ };
32
+
33
+ export { SceneReactObject };
34
+ //# sourceMappingURL=SceneReactObject.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SceneReactObject.js","sources":["../../../src/components/SceneReactObject.tsx"],"sourcesContent":["import React from 'react';\n\nimport { SceneObjectBase } from '../core/SceneObjectBase';\nimport { SceneComponentProps, SceneLayoutChildState } from '../core/types';\n\nexport interface SceneReactObjectState<TProps = {}> extends SceneLayoutChildState {\n /**\n * React component to render\n */\n component?: React.ComponentType<TProps>;\n /**\n * Props to pass to the component\n */\n props?: TProps;\n /**\n * Alternative to component and props is just to pass a React node\n */\n reactNode?: React.ReactNode;\n}\n\n/**\n * A utility object that can be used to render any React component or ReactNode\n */\nexport class SceneReactObject extends SceneObjectBase<SceneReactObjectState> {\n public static Component = ({ model }: SceneComponentProps<SceneReactObject>) => {\n const { component: Component, props, reactNode } = model.useState();\n\n if (Component) {\n return <Component {...props} />;\n }\n\n if (reactNode) {\n return reactNode;\n }\n\n return null;\n };\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;AAuBO,MAAM,yBAAyB,eAAuC,CAAA;AAc7E,CAAA;AAda,gBAAA,CACG,SAAY,GAAA,CAAC,EAAE,KAAA,EAAmD,KAAA;AAC9E,EAAA,MAAM,EAAE,SAAW,EAAA,SAAA,EAAW,OAAO,SAAU,EAAA,GAAI,MAAM,QAAS,EAAA,CAAA;AAElE,EAAA,IAAI,SAAW,EAAA;AACb,IAAO,uBAAA,KAAA,CAAA,aAAA,CAAC,8BAAc,KAAO,CAAA,CAAA,CAAA;AAAA,GAC/B;AAEA,EAAA,IAAI,SAAW,EAAA;AACb,IAAO,OAAA,SAAA,CAAA;AAAA,GACT;AAEA,EAAO,OAAA,IAAA,CAAA;AACT,CAAA;;;;"}
@@ -63,15 +63,14 @@ class SceneRefreshPicker extends SceneObjectBase {
63
63
  timeRange.onRefresh();
64
64
  }, intervalMs);
65
65
  };
66
- }
67
- activate() {
68
- super.activate();
69
- this.setupIntervalTimer();
70
- }
71
- deactivate() {
72
- if (this._intervalTimer) {
73
- clearInterval(this._intervalTimer);
74
- }
66
+ this.addActivationHandler(() => {
67
+ this.setupIntervalTimer();
68
+ return () => {
69
+ if (this._intervalTimer) {
70
+ clearInterval(this._intervalTimer);
71
+ }
72
+ };
73
+ });
75
74
  }
76
75
  getUrlState() {
77
76
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"SceneRefreshPicker.js","sources":["../../../src/components/SceneRefreshPicker.tsx"],"sourcesContent":["import React from 'react';\n\nimport { rangeUtil } from '@grafana/data';\nimport { RefreshPicker } from '@grafana/ui';\n\nimport { SceneObjectBase } from '../core/SceneObjectBase';\nimport { sceneGraph } from '../core/sceneGraph';\nimport { SceneComponentProps, SceneObjectStatePlain, SceneObjectUrlValues } from '../core/types';\nimport { SceneObjectUrlSyncConfig } from '../services/SceneObjectUrlSyncConfig';\n\nexport const DEFAULT_INTERVALS = ['5s', '10s', '30s', '1m', '5m', '15m', '30m', '1h', '2h', '1d'];\n\nexport interface SceneRefreshPickerState extends SceneObjectStatePlain {\n // Refresh interval, e.g. 5s, 1m, 2h\n refresh: string;\n // List of allowed refresh intervals, e.g. ['5s', '1m']\n intervals?: string[];\n isOnCanvas?: boolean;\n}\n\nexport class SceneRefreshPicker extends SceneObjectBase<SceneRefreshPickerState> {\n public static Component = SceneRefreshPickerRenderer;\n protected _urlSync = new SceneObjectUrlSyncConfig(this, { keys: ['refresh'] });\n\n private _intervalTimer: ReturnType<typeof setInterval> | undefined;\n\n public constructor(state: Partial<SceneRefreshPickerState>) {\n super({\n refresh: '',\n ...state,\n intervals: state.intervals ?? DEFAULT_INTERVALS,\n });\n }\n\n public activate(): void {\n super.activate();\n this.setupIntervalTimer();\n }\n\n public deactivate(): void {\n if (this._intervalTimer) {\n clearInterval(this._intervalTimer);\n }\n }\n\n public onRefresh = () => {\n const timeRange = sceneGraph.getTimeRange(this);\n\n if (this._intervalTimer) {\n clearInterval(this._intervalTimer);\n }\n\n timeRange.onRefresh();\n this.setupIntervalTimer();\n };\n\n public onIntervalChanged = (interval: string) => {\n this.setState({ refresh: interval });\n this.setupIntervalTimer();\n };\n\n public getUrlState() {\n return {\n refresh: this.state.refresh,\n };\n }\n\n public updateFromUrl(values: SceneObjectUrlValues) {\n const refresh = values.refresh;\n\n if (refresh && typeof refresh === 'string') {\n this.setState({\n refresh,\n });\n }\n }\n\n private setupIntervalTimer = () => {\n const timeRange = sceneGraph.getTimeRange(this);\n const { refresh, intervals } = this.state;\n\n if (this._intervalTimer || refresh === '') {\n clearInterval(this._intervalTimer);\n }\n\n if (refresh === '') {\n return;\n }\n\n // When the provided interval is not allowed\n if (intervals && !intervals.includes(refresh)) {\n return;\n }\n\n const intervalMs = rangeUtil.intervalToMs(refresh);\n\n this._intervalTimer = setInterval(() => {\n timeRange.onRefresh();\n }, intervalMs);\n };\n}\n\nexport function SceneRefreshPickerRenderer({ model }: SceneComponentProps<SceneRefreshPicker>) {\n const { refresh, intervals, isOnCanvas } = model.useState();\n\n return (\n <RefreshPicker\n value={refresh}\n intervals={intervals}\n onRefresh={model.onRefresh}\n onIntervalChanged={model.onIntervalChanged}\n isOnCanvas={isOnCanvas}\n />\n );\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"SceneRefreshPicker.js","sources":["../../../src/components/SceneRefreshPicker.tsx"],"sourcesContent":["import React from 'react';\n\nimport { rangeUtil } from '@grafana/data';\nimport { RefreshPicker } from '@grafana/ui';\n\nimport { SceneObjectBase } from '../core/SceneObjectBase';\nimport { sceneGraph } from '../core/sceneGraph';\nimport { SceneComponentProps, SceneObjectStatePlain, SceneObjectUrlValues } from '../core/types';\nimport { SceneObjectUrlSyncConfig } from '../services/SceneObjectUrlSyncConfig';\n\nexport const DEFAULT_INTERVALS = ['5s', '10s', '30s', '1m', '5m', '15m', '30m', '1h', '2h', '1d'];\n\nexport interface SceneRefreshPickerState extends SceneObjectStatePlain {\n // Refresh interval, e.g. 5s, 1m, 2h\n refresh: string;\n // List of allowed refresh intervals, e.g. ['5s', '1m']\n intervals?: string[];\n isOnCanvas?: boolean;\n}\n\nexport class SceneRefreshPicker extends SceneObjectBase<SceneRefreshPickerState> {\n public static Component = SceneRefreshPickerRenderer;\n protected _urlSync = new SceneObjectUrlSyncConfig(this, { keys: ['refresh'] });\n\n private _intervalTimer: ReturnType<typeof setInterval> | undefined;\n\n public constructor(state: Partial<SceneRefreshPickerState>) {\n super({\n refresh: '',\n ...state,\n intervals: state.intervals ?? DEFAULT_INTERVALS,\n });\n\n this.addActivationHandler(() => {\n this.setupIntervalTimer();\n\n return () => {\n if (this._intervalTimer) {\n clearInterval(this._intervalTimer);\n }\n };\n });\n }\n\n public onRefresh = () => {\n const timeRange = sceneGraph.getTimeRange(this);\n\n if (this._intervalTimer) {\n clearInterval(this._intervalTimer);\n }\n\n timeRange.onRefresh();\n this.setupIntervalTimer();\n };\n\n public onIntervalChanged = (interval: string) => {\n this.setState({ refresh: interval });\n this.setupIntervalTimer();\n };\n\n public getUrlState() {\n return {\n refresh: this.state.refresh,\n };\n }\n\n public updateFromUrl(values: SceneObjectUrlValues) {\n const refresh = values.refresh;\n\n if (refresh && typeof refresh === 'string') {\n this.setState({\n refresh,\n });\n }\n }\n\n private setupIntervalTimer = () => {\n const timeRange = sceneGraph.getTimeRange(this);\n const { refresh, intervals } = this.state;\n\n if (this._intervalTimer || refresh === '') {\n clearInterval(this._intervalTimer);\n }\n\n if (refresh === '') {\n return;\n }\n\n // When the provided interval is not allowed\n if (intervals && !intervals.includes(refresh)) {\n return;\n }\n\n const intervalMs = rangeUtil.intervalToMs(refresh);\n\n this._intervalTimer = setInterval(() => {\n timeRange.onRefresh();\n }, intervalMs);\n };\n}\n\nexport function SceneRefreshPickerRenderer({ model }: SceneComponentProps<SceneRefreshPicker>) {\n const { refresh, intervals, isOnCanvas } = model.useState();\n\n return (\n <RefreshPicker\n value={refresh}\n intervals={intervals}\n onRefresh={model.onRefresh}\n onIntervalChanged={model.onIntervalChanged}\n isOnCanvas={isOnCanvas}\n />\n );\n}\n"],"names":[],"mappings":"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"}