@grafana/scenes 5.15.0 → 5.15.1
Sign up to get free protection for your applications and to get access to all the features.
- package/CHANGELOG.md +14 -0
- package/dist/esm/components/SceneApp/SceneAppPageView.js +14 -6
- package/dist/esm/components/SceneApp/SceneAppPageView.js.map +1 -1
- package/dist/esm/components/SceneApp/utils.js +3 -3
- package/dist/esm/components/SceneApp/utils.js.map +1 -1
- package/dist/esm/core/SceneTimeRange.js +2 -7
- package/dist/esm/core/SceneTimeRange.js.map +1 -1
- package/dist/esm/services/UrlSyncManager.js +20 -15
- package/dist/esm/services/UrlSyncManager.js.map +1 -1
- package/dist/esm/services/useUrlSync.js +4 -3
- package/dist/esm/services/useUrlSync.js.map +1 -1
- package/dist/esm/utils/utils.js +6 -1
- package/dist/esm/utils/utils.js.map +1 -1
- package/dist/index.d.ts +6 -4
- package/dist/index.js +44 -33
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
@@ -1,3 +1,17 @@
|
|
1
|
+
# v5.15.1 (Wed Sep 25 2024)
|
2
|
+
|
3
|
+
#### 🐛 Bug Fix
|
4
|
+
|
5
|
+
- SceneTimeRange: Fixes inconsistent representation of time range [#907](https://github.com/grafana/scenes/pull/907) ([@torkelo](https://github.com/torkelo))
|
6
|
+
- Use locationService from context in UrlSyncManager [#899](https://github.com/grafana/scenes/pull/899) ([@aocenas](https://github.com/aocenas))
|
7
|
+
|
8
|
+
#### Authors: 2
|
9
|
+
|
10
|
+
- Andrej Ocenas ([@aocenas](https://github.com/aocenas))
|
11
|
+
- Torkel Ödegaard ([@torkelo](https://github.com/torkelo))
|
12
|
+
|
13
|
+
---
|
14
|
+
|
1
15
|
# v5.15.0 (Wed Sep 25 2024)
|
2
16
|
|
3
17
|
#### 🚀 Enhancement
|
@@ -5,6 +5,7 @@ import { SceneAppPage } from './SceneAppPage.js';
|
|
5
5
|
import { useAppQueryParams, getUrlWithAppState, renderSceneComponentWithRouteProps } from './utils.js';
|
6
6
|
import { useUrlSync } from '../../services/useUrlSync.js';
|
7
7
|
import { SceneAppContext } from './SceneApp.js';
|
8
|
+
import { useLocationServiceSafe } from '../../utils/utils.js';
|
8
9
|
|
9
10
|
function SceneAppPageView({ page, routeProps }) {
|
10
11
|
const containerPage = getParentPageIfTab(page);
|
@@ -14,6 +15,7 @@ function SceneAppPageView({ page, routeProps }) {
|
|
14
15
|
const appContext = useContext(SceneAppContext);
|
15
16
|
const isInitialized = containerState.initializedScene === scene;
|
16
17
|
const { layout } = page.state;
|
18
|
+
const locationService = useLocationServiceSafe();
|
17
19
|
useLayoutEffect(() => {
|
18
20
|
if (!isInitialized) {
|
19
21
|
containerPage.initializeScene(scene);
|
@@ -30,10 +32,13 @@ function SceneAppPageView({ page, routeProps }) {
|
|
30
32
|
text: containerState.title,
|
31
33
|
img: containerState.titleImg,
|
32
34
|
icon: containerState.titleIcon,
|
33
|
-
url: getUrlWithAppState(containerState.url, containerState.preserveUrlKeys),
|
35
|
+
url: getUrlWithAppState(containerState.url, locationService.getSearchObject(), containerState.preserveUrlKeys),
|
34
36
|
hideFromBreadcrumbs: containerState.hideFromBreadcrumbs,
|
35
37
|
parentItem: getParentBreadcrumbs(
|
36
|
-
containerState.getParentPage ? containerState.getParentPage() : containerPage.parent
|
38
|
+
containerState.getParentPage ? containerState.getParentPage() : containerPage.parent,
|
39
|
+
params,
|
40
|
+
locationService.getSearchObject()
|
41
|
+
)
|
37
42
|
};
|
38
43
|
if (containerState.tabs) {
|
39
44
|
pageNav.children = containerState.tabs.map((tab) => {
|
@@ -42,7 +47,7 @@ function SceneAppPageView({ page, routeProps }) {
|
|
42
47
|
icon: tab.state.titleIcon,
|
43
48
|
tabSuffix: tab.state.tabSuffix,
|
44
49
|
active: page === tab,
|
45
|
-
url: getUrlWithAppState(tab.state.url, tab.state.preserveUrlKeys),
|
50
|
+
url: getUrlWithAppState(tab.state.url, locationService.getSearchObject(), tab.state.preserveUrlKeys),
|
46
51
|
parentItem: pageNav
|
47
52
|
};
|
48
53
|
});
|
@@ -76,14 +81,17 @@ function getParentPageIfTab(page) {
|
|
76
81
|
}
|
77
82
|
return page;
|
78
83
|
}
|
79
|
-
function getParentBreadcrumbs(parent, params) {
|
84
|
+
function getParentBreadcrumbs(parent, params, searchObject) {
|
80
85
|
if (parent instanceof SceneAppPage) {
|
81
86
|
return {
|
82
87
|
text: parent.state.title,
|
83
|
-
url: getUrlWithAppState(parent.state.url, parent.state.preserveUrlKeys),
|
88
|
+
url: getUrlWithAppState(parent.state.url, searchObject, parent.state.preserveUrlKeys),
|
84
89
|
hideFromBreadcrumbs: parent.state.hideFromBreadcrumbs,
|
85
90
|
parentItem: getParentBreadcrumbs(
|
86
|
-
parent.state.getParentPage ? parent.state.getParentPage() : parent.parent
|
91
|
+
parent.state.getParentPage ? parent.state.getParentPage() : parent.parent,
|
92
|
+
params,
|
93
|
+
searchObject
|
94
|
+
)
|
87
95
|
};
|
88
96
|
}
|
89
97
|
return void 0;
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"SceneAppPageView.js","sources":["../../../../src/components/SceneApp/SceneAppPageView.tsx"],"sourcesContent":["import { NavModelItem, UrlQueryMap } from '@grafana/data';\nimport { PluginPage } from '@grafana/runtime';\nimport React, { useContext, useEffect, useLayoutEffect } from 'react';\n\nimport { RouteComponentProps } from 'react-router-dom';\nimport { SceneObject } from '../../core/types';\nimport { SceneDebugger } from '../SceneDebugger/SceneDebugger';\nimport { SceneAppPage } from './SceneAppPage';\nimport { SceneAppDrilldownView, SceneAppPageLike } from './types';\nimport { getUrlWithAppState, renderSceneComponentWithRouteProps, useAppQueryParams } from './utils';\nimport { useUrlSync } from '../../services/useUrlSync';\nimport { SceneAppContext } from './SceneApp';\n\nexport interface Props {\n page: SceneAppPageLike;\n routeProps: RouteComponentProps;\n}\n\nexport function SceneAppPageView({ page, routeProps }: Props) {\n const containerPage = getParentPageIfTab(page);\n const containerState = containerPage.useState();\n const params = useAppQueryParams();\n const scene = page.getScene(routeProps.match);\n const appContext = useContext(SceneAppContext);\n const isInitialized = containerState.initializedScene === scene;\n const { layout } = page.state;\n\n useLayoutEffect(() => {\n // Before rendering scene components, we are making sure the URL sync is enabled for.\n if (!isInitialized) {\n containerPage.initializeScene(scene);\n }\n }, [scene, containerPage, isInitialized]);\n\n useEffect(() => {\n // Clear initializedScene when unmounting\n return () => containerPage.setState({ initializedScene: undefined });\n }, [containerPage]);\n\n const urlSyncInitialized = useUrlSync(containerPage, appContext?.state.urlSyncOptions);\n\n if (!isInitialized && !urlSyncInitialized) {\n return null;\n }\n\n const pageNav: NavModelItem = {\n text: containerState.title,\n img: containerState.titleImg,\n icon: containerState.titleIcon,\n url: getUrlWithAppState(containerState.url, containerState.preserveUrlKeys),\n hideFromBreadcrumbs: containerState.hideFromBreadcrumbs,\n parentItem: getParentBreadcrumbs(\n containerState.getParentPage ? containerState.getParentPage() : containerPage.parent,\n params\n ),\n };\n\n if (containerState.tabs) {\n pageNav.children = containerState.tabs.map((tab) => {\n return {\n text: tab.state.title,\n icon: tab.state.titleIcon,\n tabSuffix: tab.state.tabSuffix,\n active: page === tab,\n url: getUrlWithAppState(tab.state.url, tab.state.preserveUrlKeys),\n parentItem: pageNav,\n };\n });\n }\n\n let pageActions: React.ReactNode[] = [];\n if (containerState.controls) {\n pageActions = containerState.controls.map((control) => (\n <control.Component model={control} key={control.state.key} />\n ));\n }\n\n if (params['scene-debugger']) {\n pageActions.push(<SceneDebugger scene={containerPage} key={'scene-debugger'} />);\n }\n\n return (\n <PluginPage\n layout={layout}\n pageNav={pageNav}\n actions={pageActions}\n renderTitle={containerState.renderTitle}\n subTitle={containerState.subTitle}\n >\n <scene.Component model={scene} />\n </PluginPage>\n );\n}\n\n/**\n * For pages that are \"tabs\" this will return the parent page\n */\nfunction getParentPageIfTab(page: SceneAppPageLike) {\n if (page.parent instanceof SceneAppPage) {\n return page.parent;\n }\n\n return page;\n}\n\nfunction getParentBreadcrumbs(parent: SceneObject | undefined
|
1
|
+
{"version":3,"file":"SceneAppPageView.js","sources":["../../../../src/components/SceneApp/SceneAppPageView.tsx"],"sourcesContent":["import { NavModelItem, UrlQueryMap } from '@grafana/data';\nimport { PluginPage } from '@grafana/runtime';\nimport React, { useContext, useEffect, useLayoutEffect } from 'react';\n\nimport { RouteComponentProps } from 'react-router-dom';\nimport { SceneObject } from '../../core/types';\nimport { SceneDebugger } from '../SceneDebugger/SceneDebugger';\nimport { SceneAppPage } from './SceneAppPage';\nimport { SceneAppDrilldownView, SceneAppPageLike } from './types';\nimport { getUrlWithAppState, renderSceneComponentWithRouteProps, useAppQueryParams } from './utils';\nimport { useUrlSync } from '../../services/useUrlSync';\nimport { SceneAppContext } from './SceneApp';\nimport { useLocationServiceSafe } from '../../utils/utils';\n\nexport interface Props {\n page: SceneAppPageLike;\n routeProps: RouteComponentProps;\n}\n\nexport function SceneAppPageView({ page, routeProps }: Props) {\n const containerPage = getParentPageIfTab(page);\n const containerState = containerPage.useState();\n const params = useAppQueryParams();\n const scene = page.getScene(routeProps.match);\n const appContext = useContext(SceneAppContext);\n const isInitialized = containerState.initializedScene === scene;\n const { layout } = page.state;\n const locationService = useLocationServiceSafe();\n\n useLayoutEffect(() => {\n // Before rendering scene components, we are making sure the URL sync is enabled for.\n if (!isInitialized) {\n containerPage.initializeScene(scene);\n }\n }, [scene, containerPage, isInitialized]);\n\n useEffect(() => {\n // Clear initializedScene when unmounting\n return () => containerPage.setState({ initializedScene: undefined });\n }, [containerPage]);\n\n const urlSyncInitialized = useUrlSync(containerPage, appContext?.state.urlSyncOptions);\n\n if (!isInitialized && !urlSyncInitialized) {\n return null;\n }\n\n const pageNav: NavModelItem = {\n text: containerState.title,\n img: containerState.titleImg,\n icon: containerState.titleIcon,\n url: getUrlWithAppState(containerState.url, locationService.getSearchObject(), containerState.preserveUrlKeys),\n hideFromBreadcrumbs: containerState.hideFromBreadcrumbs,\n parentItem: getParentBreadcrumbs(\n containerState.getParentPage ? containerState.getParentPage() : containerPage.parent,\n params,\n locationService.getSearchObject()\n ),\n };\n\n if (containerState.tabs) {\n pageNav.children = containerState.tabs.map((tab) => {\n return {\n text: tab.state.title,\n icon: tab.state.titleIcon,\n tabSuffix: tab.state.tabSuffix,\n active: page === tab,\n url: getUrlWithAppState(tab.state.url, locationService.getSearchObject(), tab.state.preserveUrlKeys),\n parentItem: pageNav,\n };\n });\n }\n\n let pageActions: React.ReactNode[] = [];\n if (containerState.controls) {\n pageActions = containerState.controls.map((control) => (\n <control.Component model={control} key={control.state.key} />\n ));\n }\n\n if (params['scene-debugger']) {\n pageActions.push(<SceneDebugger scene={containerPage} key={'scene-debugger'} />);\n }\n\n return (\n <PluginPage\n layout={layout}\n pageNav={pageNav}\n actions={pageActions}\n renderTitle={containerState.renderTitle}\n subTitle={containerState.subTitle}\n >\n <scene.Component model={scene} />\n </PluginPage>\n );\n}\n\n/**\n * For pages that are \"tabs\" this will return the parent page\n */\nfunction getParentPageIfTab(page: SceneAppPageLike) {\n if (page.parent instanceof SceneAppPage) {\n return page.parent;\n }\n\n return page;\n}\n\nfunction getParentBreadcrumbs(\n parent: SceneObject | undefined,\n params: UrlQueryMap,\n searchObject: UrlQueryMap\n): NavModelItem | undefined {\n if (parent instanceof SceneAppPage) {\n return {\n text: parent.state.title,\n url: getUrlWithAppState(parent.state.url, searchObject, parent.state.preserveUrlKeys),\n hideFromBreadcrumbs: parent.state.hideFromBreadcrumbs,\n parentItem: getParentBreadcrumbs(\n parent.state.getParentPage ? parent.state.getParentPage() : parent.parent,\n params,\n searchObject\n ),\n };\n }\n\n return undefined;\n}\n\nexport interface SceneAppDrilldownViewRenderProps {\n drilldown: SceneAppDrilldownView;\n parent: SceneAppPageLike;\n routeProps: RouteComponentProps;\n}\n\nexport function SceneAppDrilldownViewRender({ drilldown, parent, routeProps }: SceneAppDrilldownViewRenderProps) {\n return renderSceneComponentWithRouteProps(parent.getDrilldownPage(drilldown, routeProps.match), routeProps);\n}\n"],"names":[],"mappings":"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"}
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import React from 'react';
|
2
2
|
import { useLocation } from 'react-router-dom';
|
3
3
|
import { urlUtil, locationUtil } from '@grafana/data';
|
4
|
-
import {
|
4
|
+
import { locationSearchToObject } from '@grafana/runtime';
|
5
5
|
|
6
6
|
var __defProp = Object.defineProperty;
|
7
7
|
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
@@ -23,8 +23,8 @@ function useAppQueryParams() {
|
|
23
23
|
const location = useLocation();
|
24
24
|
return locationSearchToObject(location.search || "");
|
25
25
|
}
|
26
|
-
function getUrlWithAppState(path, preserveParams) {
|
27
|
-
const paramsCopy = __spreadValues({},
|
26
|
+
function getUrlWithAppState(path, searchObject, preserveParams) {
|
27
|
+
const paramsCopy = __spreadValues({}, searchObject);
|
28
28
|
if (preserveParams) {
|
29
29
|
for (const key of Object.keys(paramsCopy)) {
|
30
30
|
if (!preserveParams.includes(key)) {
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"utils.js","sources":["../../../../src/components/SceneApp/utils.ts"],"sourcesContent":["import React from 'react';\nimport { RouteComponentProps, useLocation } from 'react-router-dom';\nimport { UrlQueryMap, locationUtil, urlUtil } from '@grafana/data';\nimport { locationSearchToObject
|
1
|
+
{"version":3,"file":"utils.js","sources":["../../../../src/components/SceneApp/utils.ts"],"sourcesContent":["import React from 'react';\nimport { RouteComponentProps, useLocation } from 'react-router-dom';\nimport { UrlQueryMap, locationUtil, urlUtil } from '@grafana/data';\nimport { locationSearchToObject } from '@grafana/runtime';\nimport { SceneObject } from '../../core/types';\n\nexport function useAppQueryParams(): UrlQueryMap {\n const location = useLocation();\n return locationSearchToObject(location.search || '');\n}\n\n/**\n *\n * @param path Url to append query params to\n * @param searchObject Query params of the URL\n * @param preserveParams Query params to preserve\n * @returns Url with query params\n */\nexport function getUrlWithAppState(path: string, searchObject: UrlQueryMap, preserveParams?: string[]): string {\n // make a copy of params as the renderUrl function mutates the object\n const paramsCopy = { ...searchObject };\n\n if (preserveParams) {\n for (const key of Object.keys(paramsCopy)) {\n // if param is not in preserveParams, remove it\n if (!preserveParams.includes(key)) {\n delete paramsCopy[key];\n }\n }\n }\n\n return urlUtil.renderUrl(locationUtil.assureBaseUrl(path), paramsCopy);\n}\n\nexport function renderSceneComponentWithRouteProps(sceneObject: SceneObject, routeProps: RouteComponentProps) {\n // @ts-ignore\n return React.createElement(sceneObject.Component, { model: sceneObject, routeProps: routeProps });\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;AAMO,SAAS,iBAAiC,GAAA;AAC/C,EAAA,MAAM,WAAW,WAAY,EAAA,CAAA;AAC7B,EAAO,OAAA,sBAAA,CAAuB,QAAS,CAAA,MAAA,IAAU,EAAE,CAAA,CAAA;AACrD,CAAA;AASgB,SAAA,kBAAA,CAAmB,IAAc,EAAA,YAAA,EAA2B,cAAmC,EAAA;AAE7G,EAAA,MAAM,aAAa,cAAK,CAAA,EAAA,EAAA,YAAA,CAAA,CAAA;AAExB,EAAA,IAAI,cAAgB,EAAA;AAClB,IAAA,KAAA,MAAW,GAAO,IAAA,MAAA,CAAO,IAAK,CAAA,UAAU,CAAG,EAAA;AAEzC,MAAA,IAAI,CAAC,cAAA,CAAe,QAAS,CAAA,GAAG,CAAG,EAAA;AACjC,QAAA,OAAO,UAAW,CAAA,GAAA,CAAA,CAAA;AAAA,OACpB;AAAA,KACF;AAAA,GACF;AAEA,EAAA,OAAO,QAAQ,SAAU,CAAA,YAAA,CAAa,aAAc,CAAA,IAAI,GAAG,UAAU,CAAA,CAAA;AACvE,CAAA;AAEgB,SAAA,kCAAA,CAAmC,aAA0B,UAAiC,EAAA;AAE5G,EAAO,OAAA,KAAA,CAAM,cAAc,WAAY,CAAA,SAAA,EAAW,EAAE,KAAO,EAAA,WAAA,EAAa,YAAwB,CAAA,CAAA;AAClG;;;;"}
|
@@ -40,24 +40,19 @@ class SceneTimeRange extends SceneObjectBase {
|
|
40
40
|
this._urlSync = new SceneObjectUrlSyncConfig(this, { keys: ["from", "to", "timezone", "time", "time.window"] });
|
41
41
|
this.onTimeRangeChange = (timeRange) => {
|
42
42
|
const update = {};
|
43
|
-
const updateToEval = {};
|
44
43
|
if (typeof timeRange.raw.from === "string") {
|
45
44
|
update.from = timeRange.raw.from;
|
46
|
-
updateToEval.from = timeRange.raw.from;
|
47
45
|
} else {
|
48
46
|
update.from = timeRange.raw.from.toISOString();
|
49
|
-
updateToEval.from = timeRange.raw.from.toISOString(true);
|
50
47
|
}
|
51
48
|
if (typeof timeRange.raw.to === "string") {
|
52
49
|
update.to = timeRange.raw.to;
|
53
|
-
updateToEval.to = timeRange.raw.to;
|
54
50
|
} else {
|
55
51
|
update.to = timeRange.raw.to.toISOString();
|
56
|
-
updateToEval.to = timeRange.raw.to.toISOString(true);
|
57
52
|
}
|
58
53
|
update.value = evaluateTimeRange(
|
59
|
-
|
60
|
-
|
54
|
+
update.from,
|
55
|
+
update.to,
|
61
56
|
this.getTimeZone(),
|
62
57
|
this.state.fiscalYearStartMonth,
|
63
58
|
this.state.UNSAFE_nowDelay
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"SceneTimeRange.js","sources":["../../../src/core/SceneTimeRange.tsx"],"sourcesContent":["import { getTimeZone, rangeUtil, TimeRange, toUtc } from '@grafana/data';\nimport { TimeZone } from '@grafana/schema';\n\nimport { SceneObjectUrlSyncConfig } from '../services/SceneObjectUrlSyncConfig';\n\nimport { SceneObjectBase } from './SceneObjectBase';\nimport { SceneTimeRangeLike, SceneTimeRangeState, SceneObjectUrlValues } from './types';\nimport { getClosest } from './sceneGraph/utils';\nimport { parseUrlParam } from '../utils/parseUrlParam';\nimport { evaluateTimeRange } from '../utils/evaluateTimeRange';\nimport { locationService, RefreshEvent } from '@grafana/runtime';\n\nexport class SceneTimeRange extends SceneObjectBase<SceneTimeRangeState> implements SceneTimeRangeLike {\n protected _urlSync = new SceneObjectUrlSyncConfig(this, { keys: ['from', 'to', 'timezone', 'time', 'time.window'] });\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;\n const value = evaluateTimeRange(\n from,\n to,\n timeZone || getTimeZone(),\n state.fiscalYearStartMonth,\n state.UNSAFE_nowDelay\n );\n const refreshOnActivate = state.refreshOnActivate ?? { percent: 10 };\n super({ from, to, timeZone, value, refreshOnActivate, ...state });\n\n this.addActivationHandler(this._onActivate.bind(this));\n }\n\n private _onActivate() {\n // When SceneTimeRange has no time zone provided, find closest source of time zone and subscribe to it\n if (!this.state.timeZone) {\n const timeZoneSource = this.getTimeZoneSource();\n if (timeZoneSource !== this) {\n this._subs.add(\n timeZoneSource.subscribeToState((n, p) => {\n if (n.timeZone !== undefined && n.timeZone !== p.timeZone) {\n this.setState({\n value: evaluateTimeRange(\n this.state.from,\n this.state.to,\n timeZoneSource.getTimeZone(),\n this.state.fiscalYearStartMonth,\n this.state.UNSAFE_nowDelay\n ),\n });\n }\n })\n );\n }\n }\n\n if (rangeUtil.isRelativeTimeRange(this.state.value.raw)) {\n this.refreshIfStale();\n }\n }\n\n private refreshIfStale() {\n let ms;\n if (this.state?.refreshOnActivate?.percent !== undefined) {\n ms = this.calculatePercentOfInterval(this.state.refreshOnActivate.percent);\n }\n if (this.state?.refreshOnActivate?.afterMs !== undefined) {\n ms = Math.min(this.state.refreshOnActivate.afterMs, ms ?? Infinity);\n }\n if (ms !== undefined) {\n this.refreshRange(ms);\n }\n }\n\n /**\n * Will traverse up the scene graph to find the closest SceneTimeRangeLike with time zone set\n */\n private getTimeZoneSource() {\n if (!this.parent || !this.parent.parent) {\n return this;\n }\n // Find the closest source of time zone\n const source = getClosest<SceneTimeRangeLike>(this.parent.parent, (o) => {\n if (o.state.$timeRange && o.state.$timeRange.state.timeZone) {\n return o.state.$timeRange;\n }\n return undefined;\n });\n\n if (!source) {\n return this;\n }\n\n return source;\n }\n\n /**\n * Refreshes time range if it is older than the invalidation interval\n * @param refreshAfterMs invalidation interval (milliseconds)\n * @private\n */\n private refreshRange(refreshAfterMs: number) {\n const value = evaluateTimeRange(\n this.state.from,\n this.state.to,\n this.state.timeZone ?? getTimeZone(),\n this.state.fiscalYearStartMonth,\n this.state.UNSAFE_nowDelay\n );\n\n const diff = value.to.diff(this.state.value.to, 'milliseconds');\n if (diff >= refreshAfterMs) {\n this.setState({\n value,\n });\n }\n }\n\n private calculatePercentOfInterval(percent: number): number {\n const intervalMs = this.state.value.to.diff(this.state.value.from, 'milliseconds');\n return Math.ceil(intervalMs / percent);\n }\n\n public getTimeZone(): TimeZone {\n // Return local time zone if provided\n if (this.state.timeZone) {\n return this.state.timeZone;\n }\n\n // Resolve higher level time zone source\n const timeZoneSource = this.getTimeZoneSource();\n if (timeZoneSource !== this) {\n return timeZoneSource.state.timeZone!;\n }\n\n // Return default time zone\n return getTimeZone();\n }\n\n public onTimeRangeChange = (timeRange: TimeRange) => {\n const update: Partial<SceneTimeRangeState> = {};\n const updateToEval: Partial<SceneTimeRangeState> = {};\n\n if (typeof timeRange.raw.from === 'string') {\n update.from = timeRange.raw.from;\n updateToEval.from = timeRange.raw.from;\n } else {\n update.from = timeRange.raw.from.toISOString();\n updateToEval.from = timeRange.raw.from.toISOString(true);\n }\n\n if (typeof timeRange.raw.to === 'string') {\n update.to = timeRange.raw.to;\n updateToEval.to = timeRange.raw.to;\n } else {\n update.to = timeRange.raw.to.toISOString();\n updateToEval.to = timeRange.raw.to.toISOString(true);\n }\n\n update.value = evaluateTimeRange(\n updateToEval.from,\n updateToEval.to,\n this.getTimeZone(),\n this.state.fiscalYearStartMonth,\n this.state.UNSAFE_nowDelay\n );\n\n // Only update if time range actually changed\n if (update.from !== this.state.from || update.to !== this.state.to) {\n this._urlSync.performBrowserHistoryAction(() => {\n this.setState(update);\n });\n }\n };\n\n public onTimeZoneChange = (timeZone: TimeZone) => {\n this._urlSync.performBrowserHistoryAction(() => {\n this.setState({ timeZone });\n });\n };\n\n public onRefresh = () => {\n this.setState({\n value: evaluateTimeRange(\n this.state.from,\n this.state.to,\n this.getTimeZone(),\n this.state.fiscalYearStartMonth,\n this.state.UNSAFE_nowDelay\n ),\n });\n\n this.publishEvent(new RefreshEvent(), true);\n };\n\n public getUrlState() {\n const params = locationService.getSearchObject();\n const urlValues: SceneObjectUrlValues = { from: this.state.from, to: this.state.to };\n\n if (this.state.timeZone) {\n urlValues.timezone = this.state.timeZone;\n }\n\n // Clear time and time.window once they are converted to from and to\n if (params.time && params['time.window']) {\n urlValues.time = null;\n urlValues['time.window'] = null;\n }\n\n return urlValues;\n }\n\n public updateFromUrl(values: SceneObjectUrlValues) {\n const update: Partial<SceneTimeRangeState> = {};\n\n let from = parseUrlParam(values.from);\n let to = parseUrlParam(values.to);\n\n if (values.time && values['time.window']) {\n const time = Array.isArray(values.time) ? values.time[0] : values.time;\n const timeWindow = Array.isArray(values['time.window']) ? values['time.window'][0] : values['time.window'];\n const timeRange = getTimeWindow(time, timeWindow);\n from = timeRange.from;\n to = timeRange.to;\n }\n\n if (!from && !to) {\n return;\n }\n\n if (from) {\n update.from = from;\n }\n\n if (to) {\n update.to = to;\n }\n\n if (typeof values.timezone === 'string') {\n update.timeZone = values.timezone !== '' ? values.timezone : undefined;\n }\n\n update.value = evaluateTimeRange(\n update.from ?? this.state.from,\n update.to ?? this.state.to,\n update.timeZone ?? this.getTimeZone(),\n this.state.fiscalYearStartMonth,\n this.state.UNSAFE_nowDelay\n );\n\n this.setState(update);\n }\n}\n\n/**\n * Calculates the duration of the time range from time-time.window/2 to time+time.window/2. Both be specified in ms. For example ?time=1500000000000&time.window=10000 results in a 10-second time range from 1499999995000 to 1500000005000`.\n * @param time - time in ms\n * @param timeWindow - time window in ms or interval string\n */\nfunction getTimeWindow(time: string, timeWindow: string) {\n // Parse the time, assuming it could be an ISO string or a number in milliseconds\n const valueTime = isNaN(Date.parse(time)) ? parseInt(time, 10) : Date.parse(time);\n\n let timeWindowMs;\n\n if (timeWindow.match(/^\\d+$/) && parseInt(timeWindow, 10)) {\n // when time window is specified in ms\n timeWindowMs = parseInt(timeWindow, 10);\n } else {\n timeWindowMs = rangeUtil.intervalToMs(timeWindow);\n }\n\n return {\n from: toUtc(valueTime - timeWindowMs / 2).toISOString(),\n to: toUtc(valueTime + timeWindowMs / 2).toISOString(),\n };\n}\n"],"names":[],"mappings":"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"}
|
1
|
+
{"version":3,"file":"SceneTimeRange.js","sources":["../../../src/core/SceneTimeRange.tsx"],"sourcesContent":["import { getTimeZone, rangeUtil, TimeRange, toUtc } from '@grafana/data';\nimport { TimeZone } from '@grafana/schema';\n\nimport { SceneObjectUrlSyncConfig } from '../services/SceneObjectUrlSyncConfig';\n\nimport { SceneObjectBase } from './SceneObjectBase';\nimport { SceneTimeRangeLike, SceneTimeRangeState, SceneObjectUrlValues } from './types';\nimport { getClosest } from './sceneGraph/utils';\nimport { parseUrlParam } from '../utils/parseUrlParam';\nimport { evaluateTimeRange } from '../utils/evaluateTimeRange';\nimport { locationService, RefreshEvent } from '@grafana/runtime';\n\nexport class SceneTimeRange extends SceneObjectBase<SceneTimeRangeState> implements SceneTimeRangeLike {\n protected _urlSync = new SceneObjectUrlSyncConfig(this, { keys: ['from', 'to', 'timezone', 'time', 'time.window'] });\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;\n const value = evaluateTimeRange(\n from,\n to,\n timeZone || getTimeZone(),\n state.fiscalYearStartMonth,\n state.UNSAFE_nowDelay\n );\n const refreshOnActivate = state.refreshOnActivate ?? { percent: 10 };\n super({ from, to, timeZone, value, refreshOnActivate, ...state });\n\n this.addActivationHandler(this._onActivate.bind(this));\n }\n\n private _onActivate() {\n // When SceneTimeRange has no time zone provided, find closest source of time zone and subscribe to it\n if (!this.state.timeZone) {\n const timeZoneSource = this.getTimeZoneSource();\n if (timeZoneSource !== this) {\n this._subs.add(\n timeZoneSource.subscribeToState((n, p) => {\n if (n.timeZone !== undefined && n.timeZone !== p.timeZone) {\n this.setState({\n value: evaluateTimeRange(\n this.state.from,\n this.state.to,\n timeZoneSource.getTimeZone(),\n this.state.fiscalYearStartMonth,\n this.state.UNSAFE_nowDelay\n ),\n });\n }\n })\n );\n }\n }\n\n if (rangeUtil.isRelativeTimeRange(this.state.value.raw)) {\n this.refreshIfStale();\n }\n }\n\n private refreshIfStale() {\n let ms;\n if (this.state?.refreshOnActivate?.percent !== undefined) {\n ms = this.calculatePercentOfInterval(this.state.refreshOnActivate.percent);\n }\n if (this.state?.refreshOnActivate?.afterMs !== undefined) {\n ms = Math.min(this.state.refreshOnActivate.afterMs, ms ?? Infinity);\n }\n if (ms !== undefined) {\n this.refreshRange(ms);\n }\n }\n\n /**\n * Will traverse up the scene graph to find the closest SceneTimeRangeLike with time zone set\n */\n private getTimeZoneSource() {\n if (!this.parent || !this.parent.parent) {\n return this;\n }\n // Find the closest source of time zone\n const source = getClosest<SceneTimeRangeLike>(this.parent.parent, (o) => {\n if (o.state.$timeRange && o.state.$timeRange.state.timeZone) {\n return o.state.$timeRange;\n }\n return undefined;\n });\n\n if (!source) {\n return this;\n }\n\n return source;\n }\n\n /**\n * Refreshes time range if it is older than the invalidation interval\n * @param refreshAfterMs invalidation interval (milliseconds)\n * @private\n */\n private refreshRange(refreshAfterMs: number) {\n const value = evaluateTimeRange(\n this.state.from,\n this.state.to,\n this.state.timeZone ?? getTimeZone(),\n this.state.fiscalYearStartMonth,\n this.state.UNSAFE_nowDelay\n );\n\n const diff = value.to.diff(this.state.value.to, 'milliseconds');\n if (diff >= refreshAfterMs) {\n this.setState({\n value,\n });\n }\n }\n\n private calculatePercentOfInterval(percent: number): number {\n const intervalMs = this.state.value.to.diff(this.state.value.from, 'milliseconds');\n return Math.ceil(intervalMs / percent);\n }\n\n public getTimeZone(): TimeZone {\n // Return local time zone if provided\n if (this.state.timeZone) {\n return this.state.timeZone;\n }\n\n // Resolve higher level time zone source\n const timeZoneSource = this.getTimeZoneSource();\n if (timeZoneSource !== this) {\n return timeZoneSource.state.timeZone!;\n }\n\n // Return default time zone\n return getTimeZone();\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(\n update.from,\n update.to,\n this.getTimeZone(),\n this.state.fiscalYearStartMonth,\n this.state.UNSAFE_nowDelay\n );\n\n // Only update if time range actually changed\n if (update.from !== this.state.from || update.to !== this.state.to) {\n this._urlSync.performBrowserHistoryAction(() => {\n this.setState(update);\n });\n }\n };\n\n public onTimeZoneChange = (timeZone: TimeZone) => {\n this._urlSync.performBrowserHistoryAction(() => {\n this.setState({ timeZone });\n });\n };\n\n public onRefresh = () => {\n this.setState({\n value: evaluateTimeRange(\n this.state.from,\n this.state.to,\n this.getTimeZone(),\n this.state.fiscalYearStartMonth,\n this.state.UNSAFE_nowDelay\n ),\n });\n\n this.publishEvent(new RefreshEvent(), true);\n };\n\n public getUrlState() {\n const params = locationService.getSearchObject();\n const urlValues: SceneObjectUrlValues = { from: this.state.from, to: this.state.to };\n\n if (this.state.timeZone) {\n urlValues.timezone = this.state.timeZone;\n }\n\n // Clear time and time.window once they are converted to from and to\n if (params.time && params['time.window']) {\n urlValues.time = null;\n urlValues['time.window'] = null;\n }\n\n return urlValues;\n }\n\n public updateFromUrl(values: SceneObjectUrlValues) {\n const update: Partial<SceneTimeRangeState> = {};\n\n let from = parseUrlParam(values.from);\n let to = parseUrlParam(values.to);\n\n if (values.time && values['time.window']) {\n const time = Array.isArray(values.time) ? values.time[0] : values.time;\n const timeWindow = Array.isArray(values['time.window']) ? values['time.window'][0] : values['time.window'];\n const timeRange = getTimeWindow(time, timeWindow);\n from = timeRange.from;\n to = timeRange.to;\n }\n\n if (!from && !to) {\n return;\n }\n\n if (from) {\n update.from = from;\n }\n\n if (to) {\n update.to = to;\n }\n\n if (typeof values.timezone === 'string') {\n update.timeZone = values.timezone !== '' ? values.timezone : undefined;\n }\n\n update.value = evaluateTimeRange(\n update.from ?? this.state.from,\n update.to ?? this.state.to,\n update.timeZone ?? this.getTimeZone(),\n this.state.fiscalYearStartMonth,\n this.state.UNSAFE_nowDelay\n );\n\n this.setState(update);\n }\n}\n\n/**\n * Calculates the duration of the time range from time-time.window/2 to time+time.window/2. Both be specified in ms. For example ?time=1500000000000&time.window=10000 results in a 10-second time range from 1499999995000 to 1500000005000`.\n * @param time - time in ms\n * @param timeWindow - time window in ms or interval string\n */\nfunction getTimeWindow(time: string, timeWindow: string) {\n // Parse the time, assuming it could be an ISO string or a number in milliseconds\n const valueTime = isNaN(Date.parse(time)) ? parseInt(time, 10) : Date.parse(time);\n\n let timeWindowMs;\n\n if (timeWindow.match(/^\\d+$/) && parseInt(timeWindow, 10)) {\n // when time window is specified in ms\n timeWindowMs = parseInt(timeWindow, 10);\n } else {\n timeWindowMs = rangeUtil.intervalToMs(timeWindow);\n }\n\n return {\n from: toUtc(valueTime - timeWindowMs / 2).toISOString(),\n to: toUtc(valueTime + timeWindowMs / 2).toISOString(),\n };\n}\n"],"names":[],"mappings":"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"}
|
@@ -30,10 +30,11 @@ class NewSceneObjectAddedEvent extends BusEventWithPayload {
|
|
30
30
|
}
|
31
31
|
NewSceneObjectAddedEvent.type = "new-scene-object-added";
|
32
32
|
class UrlSyncManager {
|
33
|
-
constructor(_options = {}) {
|
33
|
+
constructor(_options = {}, locationService$1 = locationService) {
|
34
34
|
this._urlKeyMapper = new UniqueUrlKeyMapper();
|
35
|
-
this._paramsCache = new UrlParamsCache();
|
36
35
|
this._options = _options;
|
36
|
+
this._locationService = locationService$1;
|
37
|
+
this._paramsCache = new UrlParamsCache(locationService$1);
|
37
38
|
}
|
38
39
|
initSync(root) {
|
39
40
|
var _a;
|
@@ -55,12 +56,12 @@ class UrlSyncManager {
|
|
55
56
|
})
|
56
57
|
);
|
57
58
|
this._urlKeyMapper.clear();
|
58
|
-
this._lastLocation =
|
59
|
+
this._lastLocation = this._locationService.getLocation();
|
59
60
|
this.handleNewObject(this._sceneRoot);
|
60
61
|
if (this._options.updateUrlOnInit) {
|
61
62
|
const urlState = getUrlState(root);
|
62
63
|
if (isUrlStateDifferent(urlState, this._paramsCache.getParams())) {
|
63
|
-
|
64
|
+
this._locationService.partial(urlState, true);
|
64
65
|
}
|
65
66
|
}
|
66
67
|
}
|
@@ -102,7 +103,7 @@ class UrlSyncManager {
|
|
102
103
|
return;
|
103
104
|
}
|
104
105
|
const newUrlState = changedObject.urlSync.getUrlState();
|
105
|
-
const searchParams =
|
106
|
+
const searchParams = this._locationService.getSearch();
|
106
107
|
const mappedUpdated = {};
|
107
108
|
for (const [key, newUrlValue] of Object.entries(newUrlState)) {
|
108
109
|
const uniqueKey = this._urlKeyMapper.getUniqueKey(key, changedObject);
|
@@ -115,8 +116,8 @@ class UrlSyncManager {
|
|
115
116
|
const shouldCreateHistoryEntry = (_b = (_a = changedObject.urlSync).shouldCreateHistoryStep) == null ? void 0 : _b.call(_a, newUrlState);
|
116
117
|
const shouldReplace = shouldCreateHistoryEntry !== true;
|
117
118
|
writeSceneLog("UrlSyncManager", "onStateChange updating URL");
|
118
|
-
|
119
|
-
this._lastLocation =
|
119
|
+
this._locationService.partial(mappedUpdated, shouldReplace);
|
120
|
+
this._lastLocation = this._locationService.getLocation();
|
120
121
|
}
|
121
122
|
}
|
122
123
|
getUrlState(root) {
|
@@ -124,12 +125,13 @@ class UrlSyncManager {
|
|
124
125
|
}
|
125
126
|
}
|
126
127
|
class UrlParamsCache {
|
127
|
-
constructor() {
|
128
|
+
constructor(locationService) {
|
129
|
+
this.locationService = locationService;
|
128
130
|
__privateAdd(this, _cache, void 0);
|
129
131
|
__privateAdd(this, _location, void 0);
|
130
132
|
}
|
131
133
|
getParams() {
|
132
|
-
const location = locationService.getLocation();
|
134
|
+
const location = this.locationService.getLocation();
|
133
135
|
if (__privateGet(this, _location) === location) {
|
134
136
|
return __privateGet(this, _cache);
|
135
137
|
}
|
@@ -148,13 +150,16 @@ function isUrlStateDifferent(sceneUrlState, currentParams) {
|
|
148
150
|
}
|
149
151
|
return false;
|
150
152
|
}
|
151
|
-
function useUrlSyncManager(options) {
|
153
|
+
function useUrlSyncManager(options, locationService) {
|
152
154
|
return useMemo(
|
153
|
-
() => new UrlSyncManager(
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
155
|
+
() => new UrlSyncManager(
|
156
|
+
{
|
157
|
+
updateUrlOnInit: options.updateUrlOnInit,
|
158
|
+
createBrowserHistorySteps: options.createBrowserHistorySteps
|
159
|
+
},
|
160
|
+
locationService
|
161
|
+
),
|
162
|
+
[options.updateUrlOnInit, options.createBrowserHistorySteps, locationService]
|
158
163
|
);
|
159
164
|
}
|
160
165
|
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"UrlSyncManager.js","sources":["../../../src/services/UrlSyncManager.ts"],"sourcesContent":["import { Location } from 'history';\n\nimport { locationService } from '@grafana/runtime';\n\nimport { SceneObjectStateChangedEvent } from '../core/events';\nimport { SceneObject, SceneObjectUrlValues, SceneUrlSyncOptions } from '../core/types';\nimport { writeSceneLog } from '../utils/writeSceneLog';\nimport { Subscription } from 'rxjs';\nimport { UniqueUrlKeyMapper } from './UniqueUrlKeyMapper';\nimport { getUrlState, isUrlValueEqual, syncStateFromUrl } from './utils';\nimport { BusEventWithPayload } from '@grafana/data';\nimport { useMemo } from 'react';\n\nexport interface UrlSyncManagerLike {\n initSync(root: SceneObject): void;\n cleanUp(root: SceneObject): void;\n handleNewLocation(location: Location): void;\n handleNewObject(sceneObj: SceneObject): void;\n}\n\n/**\n * Notify the url sync manager of a new object that has been added to the scene\n * that needs to init state from URL.\n */\nexport class NewSceneObjectAddedEvent extends BusEventWithPayload<SceneObject> {\n public static readonly type = 'new-scene-object-added';\n}\n\nexport class UrlSyncManager implements UrlSyncManagerLike {\n private _urlKeyMapper = new UniqueUrlKeyMapper();\n private _sceneRoot?: SceneObject;\n private _subs: Subscription | undefined;\n private _lastLocation: Location | undefined;\n private _paramsCache = new UrlParamsCache();\n private _options: SceneUrlSyncOptions;\n\n public constructor(_options: SceneUrlSyncOptions = {}) {\n this._options = _options;\n }\n\n /**\n * Updates the current scene state to match URL state.\n */\n public initSync(root: SceneObject) {\n if (this._subs) {\n writeSceneLog('UrlSyncManager', 'Unregister previous scene state subscription', this._sceneRoot?.state.key);\n this._subs.unsubscribe();\n }\n\n writeSceneLog('UrlSyncManager', 'init', root.state.key);\n\n this._sceneRoot = root;\n this._subs = new Subscription();\n\n this._subs.add(\n root.subscribeToEvent(SceneObjectStateChangedEvent, (evt) => {\n this.handleSceneObjectStateChanged(evt.payload.changedObject);\n })\n );\n\n this._subs.add(\n root.subscribeToEvent(NewSceneObjectAddedEvent, (evt) => {\n this.handleNewObject(evt.payload);\n })\n );\n\n this._urlKeyMapper.clear();\n this._lastLocation = locationService.getLocation();\n\n // Sync current url with state\n this.handleNewObject(this._sceneRoot);\n\n if (this._options.updateUrlOnInit) {\n // Get current url state and update url to match\n const urlState = getUrlState(root);\n\n if (isUrlStateDifferent(urlState, this._paramsCache.getParams())) {\n locationService.partial(urlState, true);\n }\n }\n }\n\n public cleanUp(root: SceneObject) {\n // Ignore this if we have a new or different root\n if (this._sceneRoot !== root) {\n return;\n }\n\n writeSceneLog('UrlSyncManager', 'Clean up');\n\n if (this._subs) {\n this._subs.unsubscribe();\n this._subs = undefined;\n\n writeSceneLog(\n 'UrlSyncManager',\n 'Root deactived, unsub to state',\n 'same key',\n this._sceneRoot.state.key === root.state.key\n );\n }\n\n this._sceneRoot = undefined;\n this._lastLocation = undefined;\n }\n\n public handleNewLocation(location: Location) {\n if (!this._sceneRoot || this._lastLocation === location) {\n return;\n }\n\n writeSceneLog('UrlSyncManager', 'handleNewLocation');\n\n this._lastLocation = location;\n\n // Sync scene state tree from url\n syncStateFromUrl(this._sceneRoot!, this._paramsCache.getParams(), this._urlKeyMapper);\n }\n\n public handleNewObject(sceneObj: SceneObject) {\n if (!this._sceneRoot) {\n return;\n }\n\n syncStateFromUrl(sceneObj, this._paramsCache.getParams(), this._urlKeyMapper);\n }\n\n private handleSceneObjectStateChanged(changedObject: SceneObject) {\n if (!changedObject.urlSync) {\n return;\n }\n\n const newUrlState = changedObject.urlSync.getUrlState();\n\n const searchParams = locationService.getSearch();\n const mappedUpdated: SceneObjectUrlValues = {};\n\n for (const [key, newUrlValue] of Object.entries(newUrlState)) {\n const uniqueKey = this._urlKeyMapper.getUniqueKey(key, changedObject);\n const currentUrlValue = searchParams.getAll(uniqueKey);\n\n if (!isUrlValueEqual(currentUrlValue, newUrlValue)) {\n mappedUpdated[uniqueKey] = newUrlValue;\n }\n }\n\n if (Object.keys(mappedUpdated).length > 0) {\n const shouldCreateHistoryEntry = changedObject.urlSync.shouldCreateHistoryStep?.(newUrlState);\n const shouldReplace = shouldCreateHistoryEntry !== true;\n\n writeSceneLog('UrlSyncManager', 'onStateChange updating URL');\n locationService.partial(mappedUpdated, shouldReplace);\n\n /// Mark the location already handled\n this._lastLocation = locationService.getLocation();\n }\n }\n\n public getUrlState(root: SceneObject): SceneObjectUrlValues {\n return getUrlState(root);\n }\n}\n\nclass UrlParamsCache {\n #cache: URLSearchParams | undefined;\n #location: Location | undefined;\n\n public getParams(): URLSearchParams {\n const location = locationService.getLocation();\n\n if (this.#location === location) {\n return this.#cache!;\n }\n\n this.#location = location;\n this.#cache = new URLSearchParams(location.search);\n\n return this.#cache;\n }\n}\n\nfunction isUrlStateDifferent(sceneUrlState: SceneObjectUrlValues, currentParams: URLSearchParams) {\n for (let key in sceneUrlState) {\n if (!isUrlValueEqual(currentParams.getAll(key), sceneUrlState[key])) {\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * Creates a new memoized instance of the UrlSyncManager based on options\n */\nexport function useUrlSyncManager(options: SceneUrlSyncOptions): UrlSyncManagerLike {\n return useMemo(\n () =>\n new UrlSyncManager({\n updateUrlOnInit: options.updateUrlOnInit,\n createBrowserHistorySteps: options.createBrowserHistorySteps,\n }),\n [options.updateUrlOnInit, options.createBrowserHistorySteps]\n );\n}\n"],"names":[],"mappings":"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"}
|
1
|
+
{"version":3,"file":"UrlSyncManager.js","sources":["../../../src/services/UrlSyncManager.ts"],"sourcesContent":["import { Location } from 'history';\n\nimport { LocationService, locationService as locationServiceRuntime } from '@grafana/runtime';\n\nimport { SceneObjectStateChangedEvent } from '../core/events';\nimport { SceneObject, SceneObjectUrlValues, SceneUrlSyncOptions } from '../core/types';\nimport { writeSceneLog } from '../utils/writeSceneLog';\nimport { Subscription } from 'rxjs';\nimport { UniqueUrlKeyMapper } from './UniqueUrlKeyMapper';\nimport { getUrlState, isUrlValueEqual, syncStateFromUrl } from './utils';\nimport { BusEventWithPayload } from '@grafana/data';\nimport { useMemo } from 'react';\n\nexport interface UrlSyncManagerLike {\n initSync(root: SceneObject): void;\n cleanUp(root: SceneObject): void;\n handleNewLocation(location: Location): void;\n handleNewObject(sceneObj: SceneObject): void;\n}\n\n/**\n * Notify the url sync manager of a new object that has been added to the scene\n * that needs to init state from URL.\n */\nexport class NewSceneObjectAddedEvent extends BusEventWithPayload<SceneObject> {\n public static readonly type = 'new-scene-object-added';\n}\n\nexport class UrlSyncManager implements UrlSyncManagerLike {\n private _urlKeyMapper = new UniqueUrlKeyMapper();\n private _sceneRoot?: SceneObject;\n private _subs: Subscription | undefined;\n private _lastLocation: Location | undefined;\n private _locationService: LocationService;\n private _paramsCache: UrlParamsCache;\n private _options: SceneUrlSyncOptions;\n\n public constructor(_options: SceneUrlSyncOptions = {}, locationService: LocationService = locationServiceRuntime) {\n this._options = _options;\n this._locationService = locationService;\n this._paramsCache = new UrlParamsCache(locationService);\n }\n\n /**\n * Updates the current scene state to match URL state.\n */\n public initSync(root: SceneObject) {\n if (this._subs) {\n writeSceneLog('UrlSyncManager', 'Unregister previous scene state subscription', this._sceneRoot?.state.key);\n this._subs.unsubscribe();\n }\n\n writeSceneLog('UrlSyncManager', 'init', root.state.key);\n\n this._sceneRoot = root;\n this._subs = new Subscription();\n\n this._subs.add(\n root.subscribeToEvent(SceneObjectStateChangedEvent, (evt) => {\n this.handleSceneObjectStateChanged(evt.payload.changedObject);\n })\n );\n\n this._subs.add(\n root.subscribeToEvent(NewSceneObjectAddedEvent, (evt) => {\n this.handleNewObject(evt.payload);\n })\n );\n\n this._urlKeyMapper.clear();\n this._lastLocation = this._locationService.getLocation();\n\n // Sync current url with state\n this.handleNewObject(this._sceneRoot);\n\n if (this._options.updateUrlOnInit) {\n // Get current url state and update url to match\n const urlState = getUrlState(root);\n\n if (isUrlStateDifferent(urlState, this._paramsCache.getParams())) {\n this._locationService.partial(urlState, true);\n }\n }\n }\n\n public cleanUp(root: SceneObject) {\n // Ignore this if we have a new or different root\n if (this._sceneRoot !== root) {\n return;\n }\n\n writeSceneLog('UrlSyncManager', 'Clean up');\n\n if (this._subs) {\n this._subs.unsubscribe();\n this._subs = undefined;\n\n writeSceneLog(\n 'UrlSyncManager',\n 'Root deactived, unsub to state',\n 'same key',\n this._sceneRoot.state.key === root.state.key\n );\n }\n\n this._sceneRoot = undefined;\n this._lastLocation = undefined;\n }\n\n public handleNewLocation(location: Location) {\n if (!this._sceneRoot || this._lastLocation === location) {\n return;\n }\n\n writeSceneLog('UrlSyncManager', 'handleNewLocation');\n\n this._lastLocation = location;\n\n // Sync scene state tree from url\n syncStateFromUrl(this._sceneRoot!, this._paramsCache.getParams(), this._urlKeyMapper);\n }\n\n public handleNewObject(sceneObj: SceneObject) {\n if (!this._sceneRoot) {\n return;\n }\n\n syncStateFromUrl(sceneObj, this._paramsCache.getParams(), this._urlKeyMapper);\n }\n\n private handleSceneObjectStateChanged(changedObject: SceneObject) {\n if (!changedObject.urlSync) {\n return;\n }\n\n const newUrlState = changedObject.urlSync.getUrlState();\n\n const searchParams = this._locationService.getSearch();\n const mappedUpdated: SceneObjectUrlValues = {};\n\n for (const [key, newUrlValue] of Object.entries(newUrlState)) {\n const uniqueKey = this._urlKeyMapper.getUniqueKey(key, changedObject);\n const currentUrlValue = searchParams.getAll(uniqueKey);\n\n if (!isUrlValueEqual(currentUrlValue, newUrlValue)) {\n mappedUpdated[uniqueKey] = newUrlValue;\n }\n }\n\n if (Object.keys(mappedUpdated).length > 0) {\n const shouldCreateHistoryEntry = changedObject.urlSync.shouldCreateHistoryStep?.(newUrlState);\n const shouldReplace = shouldCreateHistoryEntry !== true;\n\n writeSceneLog('UrlSyncManager', 'onStateChange updating URL');\n this._locationService.partial(mappedUpdated, shouldReplace);\n\n /// Mark the location already handled\n this._lastLocation = this._locationService.getLocation();\n }\n }\n\n public getUrlState(root: SceneObject): SceneObjectUrlValues {\n return getUrlState(root);\n }\n}\n\nclass UrlParamsCache {\n #cache: URLSearchParams | undefined;\n #location: Location | undefined;\n\n public constructor(private locationService: LocationService) {}\n\n public getParams(): URLSearchParams {\n const location = this.locationService.getLocation();\n\n if (this.#location === location) {\n return this.#cache!;\n }\n\n this.#location = location;\n this.#cache = new URLSearchParams(location.search);\n\n return this.#cache;\n }\n}\n\nfunction isUrlStateDifferent(sceneUrlState: SceneObjectUrlValues, currentParams: URLSearchParams) {\n for (let key in sceneUrlState) {\n if (!isUrlValueEqual(currentParams.getAll(key), sceneUrlState[key])) {\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * Creates a new memoized instance of the UrlSyncManager based on options\n */\nexport function useUrlSyncManager(options: SceneUrlSyncOptions, locationService: LocationService): UrlSyncManagerLike {\n return useMemo(\n () =>\n new UrlSyncManager(\n {\n updateUrlOnInit: options.updateUrlOnInit,\n createBrowserHistorySteps: options.createBrowserHistorySteps,\n },\n locationService\n ),\n [options.updateUrlOnInit, options.createBrowserHistorySteps, locationService]\n );\n}\n"],"names":["locationService","locationServiceRuntime"],"mappings":"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"}
|
@@ -1,13 +1,14 @@
|
|
1
1
|
import { useState, useEffect } from 'react';
|
2
2
|
import { useLocation } from 'react-router-dom';
|
3
|
-
import { locationService } from '@grafana/runtime';
|
4
3
|
import { writeSceneLog } from '../utils/writeSceneLog.js';
|
5
4
|
import { useUrlSyncManager } from './UrlSyncManager.js';
|
5
|
+
import { useLocationServiceSafe } from '../utils/utils.js';
|
6
6
|
|
7
7
|
function useUrlSync(sceneRoot, options = {}) {
|
8
8
|
const location = useLocation();
|
9
|
+
const locationService = useLocationServiceSafe();
|
9
10
|
const [isInitialized, setIsInitialized] = useState(false);
|
10
|
-
const urlSyncManager = useUrlSyncManager(options);
|
11
|
+
const urlSyncManager = useUrlSyncManager(options, locationService);
|
11
12
|
useEffect(() => {
|
12
13
|
urlSyncManager.initSync(sceneRoot);
|
13
14
|
setIsInitialized(true);
|
@@ -20,7 +21,7 @@ function useUrlSync(sceneRoot, options = {}) {
|
|
20
21
|
writeSceneLog("useUrlSync", "latestLocation different from location");
|
21
22
|
}
|
22
23
|
urlSyncManager.handleNewLocation(locationToHandle);
|
23
|
-
}, [sceneRoot, urlSyncManager, location]);
|
24
|
+
}, [sceneRoot, urlSyncManager, location, locationService]);
|
24
25
|
return isInitialized;
|
25
26
|
}
|
26
27
|
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"useUrlSync.js","sources":["../../../src/services/useUrlSync.ts"],"sourcesContent":["import { SceneObject, SceneUrlSyncOptions } from '../core/types';\nimport { useEffect, useState } from 'react';\nimport { useLocation } from 'react-router-dom';\nimport {
|
1
|
+
{"version":3,"file":"useUrlSync.js","sources":["../../../src/services/useUrlSync.ts"],"sourcesContent":["import { SceneObject, SceneUrlSyncOptions } from '../core/types';\nimport { useEffect, useState } from 'react';\nimport { useLocation } from 'react-router-dom';\nimport { writeSceneLog } from '../utils/writeSceneLog';\nimport { useUrlSyncManager } from './UrlSyncManager';\nimport { useLocationServiceSafe } from '../utils/utils';\n\nexport function useUrlSync(sceneRoot: SceneObject, options: SceneUrlSyncOptions = {}): boolean {\n const location = useLocation();\n const locationService = useLocationServiceSafe();\n const [isInitialized, setIsInitialized] = useState(false);\n const urlSyncManager = useUrlSyncManager(options, locationService);\n\n useEffect(() => {\n urlSyncManager.initSync(sceneRoot);\n setIsInitialized(true);\n return () => urlSyncManager.cleanUp(sceneRoot);\n }, [sceneRoot, urlSyncManager]);\n\n useEffect(() => {\n // Use latest location, as by the time this effect runs, the location might have changed again\n const latestLocation = locationService.getLocation();\n const locationToHandle = latestLocation !== location ? latestLocation : location;\n\n if (latestLocation !== location) {\n writeSceneLog('useUrlSync', 'latestLocation different from location');\n }\n\n urlSyncManager.handleNewLocation(locationToHandle);\n }, [sceneRoot, urlSyncManager, location, locationService]);\n\n return isInitialized;\n}\n\nexport interface UrlSyncContextProviderProps {\n scene: SceneObject;\n children: React.ReactNode;\n}\n"],"names":[],"mappings":";;;;;;AAOO,SAAS,UAAW,CAAA,SAAA,EAAwB,OAA+B,GAAA,EAAa,EAAA;AAC7F,EAAA,MAAM,WAAW,WAAY,EAAA,CAAA;AAC7B,EAAA,MAAM,kBAAkB,sBAAuB,EAAA,CAAA;AAC/C,EAAA,MAAM,CAAC,aAAA,EAAe,gBAAgB,CAAA,GAAI,SAAS,KAAK,CAAA,CAAA;AACxD,EAAM,MAAA,cAAA,GAAiB,iBAAkB,CAAA,OAAA,EAAS,eAAe,CAAA,CAAA;AAEjE,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,cAAA,CAAe,SAAS,SAAS,CAAA,CAAA;AACjC,IAAA,gBAAA,CAAiB,IAAI,CAAA,CAAA;AACrB,IAAO,OAAA,MAAM,cAAe,CAAA,OAAA,CAAQ,SAAS,CAAA,CAAA;AAAA,GAC5C,EAAA,CAAC,SAAW,EAAA,cAAc,CAAC,CAAA,CAAA;AAE9B,EAAA,SAAA,CAAU,MAAM;AAEd,IAAM,MAAA,cAAA,GAAiB,gBAAgB,WAAY,EAAA,CAAA;AACnD,IAAM,MAAA,gBAAA,GAAmB,cAAmB,KAAA,QAAA,GAAW,cAAiB,GAAA,QAAA,CAAA;AAExE,IAAA,IAAI,mBAAmB,QAAU,EAAA;AAC/B,MAAA,aAAA,CAAc,cAAc,wCAAwC,CAAA,CAAA;AAAA,KACtE;AAEA,IAAA,cAAA,CAAe,kBAAkB,gBAAgB,CAAA,CAAA;AAAA,KAChD,CAAC,SAAA,EAAW,cAAgB,EAAA,QAAA,EAAU,eAAe,CAAC,CAAA,CAAA;AAEzD,EAAO,OAAA,aAAA,CAAA;AACT;;;;"}
|
package/dist/esm/utils/utils.js
CHANGED
@@ -1,6 +1,11 @@
|
|
1
|
+
import { useLocationService, locationService } from '@grafana/runtime';
|
2
|
+
|
1
3
|
function setBaseClassState(sceneObject, newState) {
|
2
4
|
sceneObject.setState(newState);
|
3
5
|
}
|
6
|
+
function useLocationServiceSafe() {
|
7
|
+
return useLocationService ? useLocationService() : locationService;
|
8
|
+
}
|
4
9
|
|
5
|
-
export { setBaseClassState };
|
10
|
+
export { setBaseClassState, useLocationServiceSafe };
|
6
11
|
//# sourceMappingURL=utils.js.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"utils.js","sources":["../../../src/utils/utils.ts"],"sourcesContent":["import { SceneObject, SceneObjectState } from '../core/types';\n\n/**\n * This function works around the problem of Contravariance of the SceneObject.setState function\n * Contravariance is not enforce by interfaces and here we use the SceneObject interface to access the setState function\n */\nexport function setBaseClassState<T extends SceneObjectState>(sceneObject: SceneObject<T>, newState: Partial<T>) {\n sceneObject.setState(newState);\n}\n"],"names":[],"mappings":"
|
1
|
+
{"version":3,"file":"utils.js","sources":["../../../src/utils/utils.ts"],"sourcesContent":["import { SceneObject, SceneObjectState } from '../core/types';\nimport { locationService as locationServiceRuntime } from '@grafana/runtime';\n// @ts-ignore\n// eslint-disable-next-line no-duplicate-imports\nimport { useLocationService } from '@grafana/runtime';\n\n/**\n * This function works around the problem of Contravariance of the SceneObject.setState function\n * Contravariance is not enforce by interfaces and here we use the SceneObject interface to access the setState function\n */\nexport function setBaseClassState<T extends SceneObjectState>(sceneObject: SceneObject<T>, newState: Partial<T>) {\n sceneObject.setState(newState);\n}\n\n/**\n * Safe way to get location service that fallbacks to singleton for older runtime versions where useLocationService is\n * not available.\n */\nexport function useLocationServiceSafe() {\n // This is basically a version/feature check for grafana/runtime so this 'if' should be stable (ie for one instance\n // of grafana this will always be true or false) so it should be safe to ignore the hook rule here\n // eslint-disable-next-line react-hooks/rules-of-hooks\n return useLocationService ? useLocationService() : locationServiceRuntime;\n}\n"],"names":["locationServiceRuntime"],"mappings":";;AAUgB,SAAA,iBAAA,CAA8C,aAA6B,QAAsB,EAAA;AAC/G,EAAA,WAAA,CAAY,SAAS,QAAQ,CAAA,CAAA;AAC/B,CAAA;AAMO,SAAS,sBAAyB,GAAA;AAIvC,EAAO,OAAA,kBAAA,GAAqB,oBAAuB,GAAAA,eAAA,CAAA;AACrD;;;;"}
|
package/dist/index.d.ts
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
import * as _grafana_data from '@grafana/data';
|
2
|
-
import { BusEventWithPayload, PanelData, BusEvent, BusEventType, BusEventHandler, TimeRange, DataQueryRequest, DataSourceGetTagKeysOptions, DataSourceGetTagValuesOptions, DataTransformContext, DataFrame, PanelPlugin, EventBus, DataQuery as DataQuery$1, DataSourceApi, Registry, RegistryItem, ScopedVars, AdHocVariableFilter, SelectableValue, MetricFindValue, GetTagResponse, VariableRefresh as VariableRefresh$1, VariableSort, EventFilterOptions, AnnotationEvent, AnnotationQuery, DataTransformerConfig, PanelMenuItem, FieldConfigSource, PanelModel, AbsoluteTimeRange, InterpolateFunction, IconName as IconName$1, PageLayoutType, FieldConfig, FieldType, FieldValueMatcherConfig, ScopedVar } from '@grafana/data';
|
2
|
+
import { BusEventWithPayload, PanelData, BusEvent, BusEventType, BusEventHandler, TimeRange, DataQueryRequest, DataSourceGetTagKeysOptions, DataSourceGetTagValuesOptions, DataTransformContext, DataFrame, UrlQueryMap, PanelPlugin, EventBus, DataQuery as DataQuery$1, DataSourceApi, Registry, RegistryItem, ScopedVars, AdHocVariableFilter, SelectableValue, MetricFindValue, GetTagResponse, VariableRefresh as VariableRefresh$1, VariableSort, EventFilterOptions, AnnotationEvent, AnnotationQuery, DataTransformerConfig, PanelMenuItem, FieldConfigSource, PanelModel, AbsoluteTimeRange, InterpolateFunction, IconName as IconName$1, PageLayoutType, FieldConfig, FieldType, FieldValueMatcherConfig, ScopedVar } from '@grafana/data';
|
3
3
|
import * as React$1 from 'react';
|
4
4
|
import React__default, { CSSProperties, ComponentType } from 'react';
|
5
5
|
import * as rxjs from 'rxjs';
|
6
6
|
import { Observable, Unsubscribable, MonoTypeOperatorFunction, Subscription, ReplaySubject } from 'rxjs';
|
7
7
|
import * as _grafana_schema from '@grafana/schema';
|
8
8
|
import { VariableType, VariableHide, TimeZone, DataTopic, DataQuery, DataSourceRef, VariableRefresh, LoadingState, DashboardCursorSync, MatcherConfig, TableFieldOptions } from '@grafana/schema';
|
9
|
-
import { VariableInterpolation } from '@grafana/runtime';
|
9
|
+
import { LocationService, VariableInterpolation } from '@grafana/runtime';
|
10
10
|
import { Location } from 'history';
|
11
11
|
import { PanelContext, IconName } from '@grafana/ui';
|
12
12
|
import ReactGridLayout from 'react-grid-layout';
|
@@ -349,10 +349,11 @@ interface SceneUrlSyncOptions {
|
|
349
349
|
/**
|
350
350
|
*
|
351
351
|
* @param path Url to append query params to
|
352
|
+
* @param searchObject Query params of the URL
|
352
353
|
* @param preserveParams Query params to preserve
|
353
354
|
* @returns Url with query params
|
354
355
|
*/
|
355
|
-
declare function getUrlWithAppState(path: string, preserveParams?: string[]): string;
|
356
|
+
declare function getUrlWithAppState(path: string, searchObject: UrlQueryMap, preserveParams?: string[]): string;
|
356
357
|
|
357
358
|
interface RuntimePanelPluginOptions {
|
358
359
|
/**
|
@@ -997,9 +998,10 @@ declare class UrlSyncManager implements UrlSyncManagerLike {
|
|
997
998
|
private _sceneRoot?;
|
998
999
|
private _subs;
|
999
1000
|
private _lastLocation;
|
1001
|
+
private _locationService;
|
1000
1002
|
private _paramsCache;
|
1001
1003
|
private _options;
|
1002
|
-
constructor(_options?: SceneUrlSyncOptions);
|
1004
|
+
constructor(_options?: SceneUrlSyncOptions, locationService?: LocationService);
|
1003
1005
|
/**
|
1004
1006
|
* Updates the current scene state to match URL state.
|
1005
1007
|
*/
|