mirror of https://github.com/grafana/grafana
Dashboards: Reload the dashboard based on time range and filters changes (#94190)
parent
bdab0bc8c0
commit
97c0ff2ae4
|
@ -0,0 +1,79 @@ |
||||
import { isEqual } from 'lodash'; |
||||
|
||||
import { UrlQueryMap } from '@grafana/data'; |
||||
import { sceneGraph, SceneObjectBase, SceneObjectState, VariableDependencyConfig } from '@grafana/scenes'; |
||||
import { getClosestScopesFacade, ScopesFacade } from 'app/features/scopes'; |
||||
|
||||
import { getDashboardScenePageStateManager } from '../pages/DashboardScenePageStateManager'; |
||||
|
||||
export interface DashboardReloadBehaviorState extends SceneObjectState { |
||||
reloadOnParamsChange?: boolean; |
||||
uid?: string; |
||||
version?: number; |
||||
} |
||||
|
||||
export class DashboardReloadBehavior extends SceneObjectBase<DashboardReloadBehaviorState> { |
||||
private _scopesFacade: ScopesFacade | null = null; |
||||
|
||||
constructor(state: DashboardReloadBehaviorState) { |
||||
const shouldReload = state.reloadOnParamsChange && state.uid; |
||||
|
||||
super(state); |
||||
|
||||
this.reloadDashboard = this.reloadDashboard.bind(this); |
||||
|
||||
if (shouldReload) { |
||||
this.addActivationHandler(() => { |
||||
this._scopesFacade = getClosestScopesFacade(this); |
||||
|
||||
this._variableDependency = new VariableDependencyConfig(this, { |
||||
onAnyVariableChanged: this.reloadDashboard, |
||||
}); |
||||
|
||||
this._scopesFacade?.setState({ |
||||
handler: this.reloadDashboard, |
||||
}); |
||||
|
||||
this._subs.add( |
||||
sceneGraph.getTimeRange(this).subscribeToState((newState, prevState) => { |
||||
if (!isEqual(newState.value, prevState.value)) { |
||||
this.reloadDashboard(); |
||||
} |
||||
}) |
||||
); |
||||
}); |
||||
} |
||||
} |
||||
|
||||
private isEditing() { |
||||
return this.parent && 'isEditing' in this.parent.state && this.parent.state.isEditing; |
||||
} |
||||
|
||||
private isWaitingForVariables() { |
||||
const varSet = sceneGraph.getVariables(this.parent!); |
||||
|
||||
return varSet.state.variables.some((variable) => varSet.isVariableLoadingOrWaitingToUpdate(variable)); |
||||
} |
||||
|
||||
private reloadDashboard() { |
||||
if (!this.isEditing() && !this.isWaitingForVariables()) { |
||||
const timeRange = sceneGraph.getTimeRange(this); |
||||
|
||||
let params: UrlQueryMap = { |
||||
version: this.state.version, |
||||
scopes: this._scopesFacade?.value.map((scope) => scope.metadata.name), |
||||
...timeRange.urlSync?.getUrlState(), |
||||
}; |
||||
|
||||
params = sceneGraph.getVariables(this).state.variables.reduce<UrlQueryMap>( |
||||
(acc, variable) => ({ |
||||
...acc, |
||||
...variable.urlSync?.getUrlState(), |
||||
}), |
||||
params |
||||
); |
||||
|
||||
getDashboardScenePageStateManager().reloadDashboard(params); |
||||
} |
||||
} |
||||
} |
@ -1,48 +0,0 @@ |
||||
import { config } from '@grafana/runtime'; |
||||
import { setDashboardAPI } from 'app/features/dashboard/api/dashboard_api'; |
||||
|
||||
import { getDashboardDTO, updateScopes } from './utils/actions'; |
||||
import { expectNewDashboardDTO, expectOldDashboardDTO } from './utils/assertions'; |
||||
import { getDatasource, getInstanceSettings, getMock } from './utils/mocks'; |
||||
import { renderDashboard, resetScenes } from './utils/render'; |
||||
|
||||
jest.mock('@grafana/runtime', () => ({ |
||||
__esModule: true, |
||||
...jest.requireActual('@grafana/runtime'), |
||||
useChromeHeaderHeight: jest.fn(), |
||||
getBackendSrv: () => ({ get: getMock }), |
||||
getDataSourceSrv: () => ({ get: getDatasource, getInstanceSettings }), |
||||
usePluginLinks: jest.fn().mockReturnValue({ links: [] }), |
||||
})); |
||||
|
||||
const runTest = async (passScopes: boolean, kubernetesApi: boolean) => { |
||||
config.featureToggles.scopeFilters = true; |
||||
config.featureToggles.passScopeToDashboardApi = passScopes; |
||||
config.featureToggles.kubernetesDashboards = kubernetesApi; |
||||
setDashboardAPI(undefined); |
||||
renderDashboard({}, { reloadOnScopesChange: true }); |
||||
await updateScopes(['grafana', 'mimir']); |
||||
await getDashboardDTO(); |
||||
|
||||
if (kubernetesApi) { |
||||
return expectNewDashboardDTO(); |
||||
} |
||||
|
||||
if (passScopes) { |
||||
return expectOldDashboardDTO(['grafana', 'mimir']); |
||||
} |
||||
|
||||
return expectOldDashboardDTO(); |
||||
}; |
||||
|
||||
describe('Dashboards API', () => { |
||||
afterEach(async () => { |
||||
setDashboardAPI(undefined); |
||||
await resetScenes(); |
||||
}); |
||||
|
||||
it('Legacy API should not pass the scopes with feature flag off', async () => runTest(false, false)); |
||||
it('K8s API should not pass the scopes with feature flag off', async () => runTest(false, true)); |
||||
it('Legacy API should pass the scopes with feature flag on', async () => runTest(true, false)); |
||||
it('K8s API should not pass the scopes with feature flag on', async () => runTest(true, true)); |
||||
}); |
Loading…
Reference in new issue