diff --git a/public/app/features/dashboard-scene/serialization/transformSaveModelToScene.test.ts b/public/app/features/dashboard-scene/serialization/transformSaveModelToScene.test.ts index 7660265d0e4..10671a0fc27 100644 --- a/public/app/features/dashboard-scene/serialization/transformSaveModelToScene.test.ts +++ b/public/app/features/dashboard-scene/serialization/transformSaveModelToScene.test.ts @@ -1,4 +1,12 @@ -import { LoadingState } from '@grafana/data'; +import { + LoadingState, + ConstantVariableModel, + CustomVariableModel, + DataSourceVariableModel, + QueryVariableModel, + IntervalVariableModel, + TypedVariableModel, +} from '@grafana/data'; import { getPanelPlugin } from '@grafana/data/test/__mocks__/pluginMocks'; import { config } from '@grafana/runtime'; import { @@ -374,7 +382,7 @@ describe('transformSaveModelToScene', () => { describe('when creating variables objects', () => { it('should migrate custom variable', () => { - const variable = { + const variable: CustomVariableModel = { current: { selected: false, text: 'a', @@ -408,12 +416,12 @@ describe('transformSaveModelToScene', () => { ], query: 'a,b,c,d', skipUrlSync: false, - type: 'custom' as VariableType, + type: 'custom', rootStateKey: 'N4XLmH5Vz', id: 'query0', global: false, index: 0, - state: 'Done', + state: LoadingState.Done, error: null, description: null, allValue: null, @@ -442,7 +450,7 @@ describe('transformSaveModelToScene', () => { }); it('should migrate query variable', () => { - const variable = { + const variable: QueryVariableModel = { allValue: null, current: { text: 'America', @@ -486,15 +494,12 @@ describe('transformSaveModelToScene', () => { regex: '', skipUrlSync: false, sort: 0, - tagValuesQuery: null, - tagsQuery: null, - type: 'query' as VariableType, - useTags: false, + type: 'query', rootStateKey: '000000002', id: 'datacenter', global: false, index: 0, - state: 'Done', + state: LoadingState.Done, error: null, description: null, }; @@ -529,16 +534,16 @@ describe('transformSaveModelToScene', () => { }); it('should migrate datasource variable', () => { - const variable = { + const variable: DataSourceVariableModel = { id: 'query1', rootStateKey: 'N4XLmH5Vz', name: 'query1', - type: 'datasource' as VariableType, + type: 'datasource', global: false, index: 1, hide: 0, skipUrlSync: false, - state: 'Done', + state: LoadingState.Done, error: null, description: null, current: { @@ -595,12 +600,12 @@ describe('transformSaveModelToScene', () => { }); it('should migrate constant variable', () => { - const variable = { + const variable: ConstantVariableModel = { hide: 2, label: 'constant', name: 'constant', skipUrlSync: false, - type: 'constant' as VariableType, + type: 'constant', rootStateKey: 'N4XLmH5Vz', current: { selected: true, @@ -618,7 +623,7 @@ describe('transformSaveModelToScene', () => { id: 'constant', global: false, index: 3, - state: 'Done', + state: LoadingState.Done, error: null, description: null, }; @@ -638,10 +643,10 @@ describe('transformSaveModelToScene', () => { }); it('should migrate interval variable', () => { - const variable = { + const variable: IntervalVariableModel = { name: 'intervalVar', label: 'Interval Label', - type: 'interval' as VariableType, + type: 'interval', rootStateKey: 'N4XLmH5Vz', auto: false, refresh: 2, @@ -665,7 +670,7 @@ describe('transformSaveModelToScene', () => { index: 4, hide: 0, skipUrlSync: false, - state: 'Done', + state: LoadingState.Done, error: null, description: null, }; @@ -692,7 +697,7 @@ describe('transformSaveModelToScene', () => { type: type as VariableType, }; - expect(() => createSceneVariableFromVariableModel(variable)).toThrow(); + expect(() => createSceneVariableFromVariableModel(variable as TypedVariableModel)).toThrow(); }); }); diff --git a/public/app/features/dashboard-scene/serialization/transformSaveModelToScene.ts b/public/app/features/dashboard-scene/serialization/transformSaveModelToScene.ts index 68c86ce9083..dafb9bd2ad4 100644 --- a/public/app/features/dashboard-scene/serialization/transformSaveModelToScene.ts +++ b/public/app/features/dashboard-scene/serialization/transformSaveModelToScene.ts @@ -1,12 +1,4 @@ -import { - AdHocVariableModel, - ConstantVariableModel, - CustomVariableModel, - DataSourceVariableModel, - IntervalVariableModel, - QueryVariableModel, - VariableModel, -} from '@grafana/data'; +import { AdHocVariableModel, TypedVariableModel, VariableModel } from '@grafana/data'; import { VizPanel, SceneTimePicker, @@ -252,12 +244,12 @@ export function createDashboardSceneFromDashboardModel(oldModel: DashboardModel) }); } -export function createSceneVariableFromVariableModel(variable: VariableModel): SceneVariable { +export function createSceneVariableFromVariableModel(variable: TypedVariableModel): SceneVariable { const commonProperties = { name: variable.name, label: variable.label, }; - if (isCustomVariable(variable)) { + if (variable.type === 'custom') { return new CustomVariable({ ...commonProperties, value: variable.current.value, @@ -271,7 +263,7 @@ export function createSceneVariableFromVariableModel(variable: VariableModel): S skipUrlSync: variable.skipUrlSync, hide: variable.hide, }); - } else if (isQueryVariable(variable)) { + } else if (variable.type === 'query') { return new QueryVariable({ ...commonProperties, value: variable.current.value, @@ -289,7 +281,7 @@ export function createSceneVariableFromVariableModel(variable: VariableModel): S skipUrlSync: variable.skipUrlSync, hide: variable.hide, }); - } else if (isDataSourceVariable(variable)) { + } else if (variable.type === 'datasource') { return new DataSourceVariable({ ...commonProperties, value: variable.current.value, @@ -304,7 +296,7 @@ export function createSceneVariableFromVariableModel(variable: VariableModel): S isMulti: variable.multi, hide: variable.hide, }); - } else if (isIntervalVariable(variable)) { + } else if (variable.type === 'interval') { const intervals = getIntervalsFromOldIntervalModel(variable); const currentInterval = getCurrentValueForOldIntervalModel(variable, intervals); return new IntervalVariable({ @@ -319,7 +311,7 @@ export function createSceneVariableFromVariableModel(variable: VariableModel): S skipUrlSync: variable.skipUrlSync, hide: variable.hide, }); - } else if (isConstantVariable(variable)) { + } else if (variable.type === 'constant') { return new ConstantVariable({ ...commonProperties, description: variable.description, @@ -417,9 +409,4 @@ export function buildGridItemForPanel(panel: PanelModel): SceneGridItemLike { }); } -const isCustomVariable = (v: VariableModel): v is CustomVariableModel => v.type === 'custom'; -const isQueryVariable = (v: VariableModel): v is QueryVariableModel => v.type === 'query'; -const isDataSourceVariable = (v: VariableModel): v is DataSourceVariableModel => v.type === 'datasource'; -const isConstantVariable = (v: VariableModel): v is ConstantVariableModel => v.type === 'constant'; -const isIntervalVariable = (v: VariableModel): v is IntervalVariableModel => v.type === 'interval'; const isAdhocVariable = (v: VariableModel): v is AdHocVariableModel => v.type === 'adhoc'; diff --git a/public/app/features/dashboard/components/ShareModal/SharePublicDashboard/SharePublicDashboardUtils.test.tsx b/public/app/features/dashboard/components/ShareModal/SharePublicDashboard/SharePublicDashboardUtils.test.tsx index cdf09b0bcb8..7a14d0a4e45 100644 --- a/public/app/features/dashboard/components/ShareModal/SharePublicDashboard/SharePublicDashboardUtils.test.tsx +++ b/public/app/features/dashboard/components/ShareModal/SharePublicDashboard/SharePublicDashboardUtils.test.tsx @@ -1,9 +1,9 @@ +import { TypedVariableModel } from '@grafana/data'; import { DataSourceRef, DataQuery } from '@grafana/data/src/types/query'; import { DataSourceWithBackend } from '@grafana/runtime'; import { updateConfig } from 'app/core/config'; import { mockDataSource } from 'app/features/alerting/unified/mocks'; import { PanelModel } from 'app/features/dashboard/state/PanelModel'; -import { VariableModel } from 'app/features/variables/types'; import { PublicDashboard, @@ -38,13 +38,13 @@ jest.mock('@grafana/runtime/src/services/dataSourceSrv', () => { describe('dashboardHasTemplateVariables', () => { it('false', () => { - let variables: VariableModel[] = []; + let variables: TypedVariableModel[] = []; expect(dashboardHasTemplateVariables(variables)).toBe(false); }); it('true', () => { //@ts-ignore - let variables: VariableModel[] = ['a']; + let variables: TypedVariableModel[] = ['a']; expect(dashboardHasTemplateVariables(variables)).toBe(true); }); }); diff --git a/public/app/features/dashboard/components/ShareModal/SharePublicDashboard/SharePublicDashboardUtils.ts b/public/app/features/dashboard/components/ShareModal/SharePublicDashboard/SharePublicDashboardUtils.ts index 3ab5264791b..2e782b75e53 100644 --- a/public/app/features/dashboard/components/ShareModal/SharePublicDashboard/SharePublicDashboardUtils.ts +++ b/public/app/features/dashboard/components/ShareModal/SharePublicDashboard/SharePublicDashboardUtils.ts @@ -1,7 +1,7 @@ +import { TypedVariableModel } from '@grafana/data'; import { DataSourceWithBackend } from '@grafana/runtime'; import { getConfig } from 'app/core/config'; import { getDatasourceSrv } from 'app/features/plugins/datasource_srv'; -import { VariableModel } from 'app/features/variables/types'; import { PanelModel } from '../../../state'; import { shareDashboardType } from '../utils'; @@ -42,7 +42,7 @@ export interface SessionUser { } // Instance methods -export const dashboardHasTemplateVariables = (variables: VariableModel[]): boolean => { +export const dashboardHasTemplateVariables = (variables: TypedVariableModel[]): boolean => { return variables.length > 0; }; diff --git a/public/app/features/dashboard/components/SubMenu/SubMenu.tsx b/public/app/features/dashboard/components/SubMenu/SubMenu.tsx index fcc57a32a4f..f5e10bc9c78 100644 --- a/public/app/features/dashboard/components/SubMenu/SubMenu.tsx +++ b/public/app/features/dashboard/components/SubMenu/SubMenu.tsx @@ -2,12 +2,11 @@ import { css } from '@emotion/css'; import React, { PureComponent } from 'react'; import { connect, MapStateToProps } from 'react-redux'; -import { AnnotationQuery, DataQuery, GrafanaTheme2 } from '@grafana/data'; +import { AnnotationQuery, DataQuery, TypedVariableModel, GrafanaTheme2 } from '@grafana/data'; import { stylesFactory, Themeable2, withTheme2 } from '@grafana/ui'; import { StoreState } from '../../../../types'; import { getSubMenuVariables, getVariablesState } from '../../../variables/state/selectors'; -import { VariableModel } from '../../../variables/types'; import { DashboardModel } from '../../state'; import { DashboardLink } from '../../state/DashboardModel'; @@ -22,7 +21,7 @@ interface OwnProps extends Themeable2 { } interface ConnectedProps { - variables: VariableModel[]; + variables: TypedVariableModel[]; } interface DispatchProps {} diff --git a/public/app/features/dashboard/components/SubMenu/SubMenuItems.tsx b/public/app/features/dashboard/components/SubMenu/SubMenuItems.tsx index 5ddf27df919..5bce5144f9d 100644 --- a/public/app/features/dashboard/components/SubMenu/SubMenuItems.tsx +++ b/public/app/features/dashboard/components/SubMenu/SubMenuItems.tsx @@ -1,17 +1,17 @@ import React, { useEffect, useState } from 'react'; +import { TypedVariableModel, VariableHide } from '@grafana/data'; import { selectors } from '@grafana/e2e-selectors'; import { PickerRenderer } from '../../../variables/pickers/PickerRenderer'; -import { VariableHide, VariableModel } from '../../../variables/types'; interface Props { - variables: VariableModel[]; + variables: TypedVariableModel[]; readOnly?: boolean; } export const SubMenuItems = ({ variables, readOnly }: Props) => { - const [visibleVariables, setVisibleVariables] = useState([]); + const [visibleVariables, setVisibleVariables] = useState([]); useEffect(() => { setVisibleVariables(variables.filter((state) => state.hide !== VariableHide.hideVariable)); @@ -23,17 +23,15 @@ export const SubMenuItems = ({ variables, readOnly }: Props) => { return ( <> - {visibleVariables.map((variable) => { - return ( -
- -
- ); - })} + {visibleVariables.map((variable) => ( +
+ +
+ ))} ); }; diff --git a/public/app/features/templating/template_srv.test.ts b/public/app/features/templating/template_srv.test.ts index b822402f96e..3dfef81ed81 100644 --- a/public/app/features/templating/template_srv.test.ts +++ b/public/app/features/templating/template_srv.test.ts @@ -1,4 +1,4 @@ -import { dateTime, TimeRange } from '@grafana/data'; +import { dateTime, TimeRange, TypedVariableModel } from '@grafana/data'; import { setDataSourceSrv, VariableInterpolation } from '@grafana/runtime'; import { ConstantVariable, EmbeddedScene, SceneCanvasText, SceneVariableSet, TestVariable } from '@grafana/scenes'; import { VariableFormatID } from '@grafana/schema'; @@ -9,15 +9,14 @@ import { mockDataSource, MockDataSourceSrv } from '../alerting/unified/mocks'; import { VariableAdapter, variableAdapters } from '../variables/adapters'; import { createAdHocVariableAdapter } from '../variables/adhoc/adapter'; import { createQueryVariableAdapter } from '../variables/query/adapter'; -import { VariableModel } from '../variables/types'; import { TemplateSrv } from './template_srv'; const key = 'key'; variableAdapters.setInit(() => [ - createQueryVariableAdapter() as unknown as VariableAdapter, - createAdHocVariableAdapter() as unknown as VariableAdapter, + createQueryVariableAdapter() as unknown as VariableAdapter, + createAdHocVariableAdapter() as unknown as VariableAdapter, ]); const interpolateMock = jest.fn(); diff --git a/public/app/features/variables/adapters.ts b/public/app/features/variables/adapters.ts index 0f52ab42f4a..b3db44a70a3 100644 --- a/public/app/features/variables/adapters.ts +++ b/public/app/features/variables/adapters.ts @@ -1,14 +1,13 @@ import { ComponentType } from 'react'; import { Reducer } from 'redux'; -import { Registry, UrlQueryValue, VariableType } from '@grafana/data'; +import { Registry, TypedVariableModel, UrlQueryValue, VariableOption, VariableType } from '@grafana/data'; import { VariableEditorProps } from './editor/types'; import { VariablePickerProps } from './pickers/types'; import { VariablesState } from './state/types'; -import { VariableModel, VariableOption } from './types'; -export interface VariableAdapter { +export interface VariableAdapter { id: VariableType; description: string; name: string; diff --git a/public/app/features/variables/editor/VariableEditorList.tsx b/public/app/features/variables/editor/VariableEditorList.tsx index 6425a5b2c1c..32720af0ab6 100644 --- a/public/app/features/variables/editor/VariableEditorList.tsx +++ b/public/app/features/variables/editor/VariableEditorList.tsx @@ -2,6 +2,7 @@ import { css } from '@emotion/css'; import React, { ReactElement } from 'react'; import { DragDropContext, Droppable, DropResult } from 'react-beautiful-dnd'; +import { TypedVariableModel } from '@grafana/data'; import { selectors } from '@grafana/e2e-selectors'; import { reportInteraction } from '@grafana/runtime'; import { Button, useStyles2, Stack } from '@grafana/ui'; @@ -10,12 +11,11 @@ import EmptyListCTA from 'app/core/components/EmptyListCTA/EmptyListCTA'; import { VariablesDependenciesButton } from '../inspect/VariablesDependenciesButton'; import { UsagesToNetwork, VariableUsageTree } from '../inspect/utils'; import { KeyedVariableIdentifier } from '../state/types'; -import { VariableModel } from '../types'; import { VariableEditorListRow } from './VariableEditorListRow'; export interface Props { - variables: VariableModel[]; + variables: TypedVariableModel[]; usages: VariableUsageTree[]; usagesNetwork: UsagesToNetwork[]; onAdd: () => void; diff --git a/public/app/features/variables/editor/VariableEditorListRow.tsx b/public/app/features/variables/editor/VariableEditorListRow.tsx index 6c094b2a364..befc897d5a5 100644 --- a/public/app/features/variables/editor/VariableEditorListRow.tsx +++ b/public/app/features/variables/editor/VariableEditorListRow.tsx @@ -2,21 +2,20 @@ import { css } from '@emotion/css'; import React, { ReactElement } from 'react'; import { Draggable } from 'react-beautiful-dnd'; -import { GrafanaTheme2 } from '@grafana/data'; +import { GrafanaTheme2, TypedVariableModel } from '@grafana/data'; import { selectors } from '@grafana/e2e-selectors'; import { reportInteraction } from '@grafana/runtime'; import { Button, Icon, IconButton, useStyles2, useTheme2 } from '@grafana/ui'; -import { hasOptions, isAdHoc, isQuery } from '../guard'; +import { hasOptions } from '../guard'; import { VariableUsagesButton } from '../inspect/VariableUsagesButton'; import { getVariableUsages, UsagesToNetwork, VariableUsageTree } from '../inspect/utils'; import { KeyedVariableIdentifier } from '../state/types'; -import { VariableModel } from '../types'; import { toKeyedVariableIdentifier } from '../utils'; export interface VariableEditorListRowProps { index: number; - variable: VariableModel; + variable: TypedVariableModel; usageTree: VariableUsageTree[]; usagesNetwork: UsagesToNetwork[]; onEdit: (identifier: KeyedVariableIdentifier) => void; @@ -37,7 +36,7 @@ export function VariableEditorListRow({ const styles = useStyles2(getStyles); const definition = getDefinition(variable); const usages = getVariableUsages(variable.id, usageTree); - const passed = usages > 0 || isAdHoc(variable); + const passed = usages > 0 || variable.type === 'adhoc'; const identifier = toKeyedVariableIdentifier(variable); return ( @@ -81,7 +80,7 @@ export function VariableEditorListRow({
- + { event.preventDefault(); @@ -113,9 +112,9 @@ export function VariableEditorListRow({ ); } -function getDefinition(model: VariableModel): string { +function getDefinition(model: TypedVariableModel): string { let definition = ''; - if (isQuery(model)) { + if (model.type === 'query') { if (model.definition) { definition = model.definition; } else if (typeof model.query === 'string') { diff --git a/public/app/features/variables/editor/actions.ts b/public/app/features/variables/editor/actions.ts index 9af677aa6e5..9f99d411b8a 100644 --- a/public/app/features/variables/editor/actions.ts +++ b/public/app/features/variables/editor/actions.ts @@ -1,6 +1,6 @@ import { cloneDeep } from 'lodash'; -import { VariableType } from '@grafana/data'; +import { TypedVariableModel, VariableType } from '@grafana/data'; import { locationService } from '@grafana/runtime'; import { ThunkResult } from '../../../types'; @@ -11,7 +11,6 @@ import { toKeyedAction } from '../state/keyedVariablesReducer'; import { getEditorVariables, getNewVariableIndex, getVariable, getVariablesByKey } from '../state/selectors'; import { addVariable, removeVariable } from '../state/sharedReducer'; import { AddVariable, KeyedVariableIdentifier, VariableIdentifier } from '../state/types'; -import { VariableModel } from '../types'; import { toKeyedVariableIdentifier, toStateKey, toVariablePayload } from '../utils'; import { @@ -95,7 +94,7 @@ export const createNewVariable = const identifier: VariableIdentifier = { type, id }; const global = false; const index = getNewVariableIndex(rootStateKey, getState()); - const model: VariableModel = cloneDeep(variableAdapters.get(type).initialState); + const model: TypedVariableModel = cloneDeep(variableAdapters.get(type).initialState); model.id = id; model.name = id; model.rootStateKey = rootStateKey; @@ -119,7 +118,7 @@ export const initListMode = dispatch(toKeyedAction(rootStateKey, initInspect({ usages, usagesNetwork }))); }; -export function getNextAvailableId(type: VariableType, variables: VariableModel[]): string { +export function getNextAvailableId(type: VariableType, variables: TypedVariableModel[]): string { let counter = 0; let nextId = `${type}${counter}`; diff --git a/public/app/features/variables/pickers/PickerRenderer.tsx b/public/app/features/variables/pickers/PickerRenderer.tsx index 843e73d8077..f4a135ba8c5 100644 --- a/public/app/features/variables/pickers/PickerRenderer.tsx +++ b/public/app/features/variables/pickers/PickerRenderer.tsx @@ -1,14 +1,14 @@ import React, { PropsWithChildren, ReactElement, useMemo } from 'react'; +import { TypedVariableModel, VariableHide } from '@grafana/data'; import { selectors } from '@grafana/e2e-selectors'; import { Tooltip } from '@grafana/ui'; import { variableAdapters } from '../adapters'; import { VARIABLE_PREFIX } from '../constants'; -import { VariableHide, VariableModel } from '../types'; interface Props { - variable: VariableModel; + variable: TypedVariableModel; readOnly?: boolean; } diff --git a/public/app/features/variables/shared/formatVariable.ts b/public/app/features/variables/shared/formatVariable.ts index 34d798c68fa..680be374a1e 100644 --- a/public/app/features/variables/shared/formatVariable.ts +++ b/public/app/features/variables/shared/formatVariable.ts @@ -1,8 +1,6 @@ -import { VariableModel } from '@grafana/data'; +import { TypedVariableModel, VariableWithOptions } from '@grafana/data'; -import { VariableWithOptions } from '../types'; - -export const formatVariableLabel = (variable: VariableModel) => { +export const formatVariableLabel = (variable: VariableWithOptions | TypedVariableModel) => { if (!isVariableWithOptions(variable)) { return variable.name; } @@ -16,7 +14,7 @@ export const formatVariableLabel = (variable: VariableModel) => { return current.text; }; -const isVariableWithOptions = (variable: VariableModel): variable is VariableWithOptions => { +const isVariableWithOptions = (variable: unknown): variable is VariableWithOptions => { return ( Array.isArray((variable as VariableWithOptions)?.options) || typeof (variable as VariableWithOptions)?.current === 'object' diff --git a/public/app/features/variables/state/actions.ts b/public/app/features/variables/state/actions.ts index 53f0b96d5a1..f57567f5fd6 100644 --- a/public/app/features/variables/state/actions.ts +++ b/public/app/features/variables/state/actions.ts @@ -10,6 +10,14 @@ import { TypedVariableModel, UrlQueryMap, UrlQueryValue, + OrgVariableModel, + QueryVariableModel, + DashboardVariableModel, + UserVariableModel, + VariableHide, + VariableOption, + VariableRefresh, + VariableWithOptions, } from '@grafana/data'; import { config, locationService } from '@grafana/runtime'; import { notifyApp } from 'app/core/actions'; @@ -28,35 +36,17 @@ import { getTemplateSrv, TemplateSrv } from '../../templating/template_srv'; import { variableAdapters } from '../adapters'; import { ALL_VARIABLE_TEXT, ALL_VARIABLE_VALUE, VARIABLE_PREFIX } from '../constants'; import { cleanEditorState } from '../editor/reducer'; -import { - hasCurrent, - hasLegacyVariableSupport, - hasOptions, - hasStandardVariableSupport, - isAdHoc, - isConstant, - isMulti, - isQuery, -} from '../guard'; +import { hasCurrent, hasLegacyVariableSupport, hasOptions, hasStandardVariableSupport, isMulti } from '../guard'; import { getAllAffectedPanelIdsForVariableChange, getPanelVars } from '../inspect/utils'; import { cleanPickerState } from '../pickers/OptionsPicker/reducer'; import { alignCurrentWithMulti } from '../shared/multiOptions'; import { - DashboardVariableModel, initialVariableModelState, - OrgVariableModel, - QueryVariableModel, TransactionStatus, - UserVariableModel, - VariableHide, - VariableModel, - VariableOption, - VariableRefresh, VariablesChanged, VariablesChangedEvent, VariablesChangedInUrl, VariablesTimeRangeProcessDone, - VariableWithOptions, } from '../types'; import { ensureStringValues, @@ -145,7 +135,7 @@ export const initDashboardTemplating = (key: string, dashboard: DashboardModel): }; }; -export function fixSelectedInconsistency(model: VariableModel): VariableModel | VariableWithOptions { +export function fixSelectedInconsistency(model: TypedVariableModel): TypedVariableModel | VariableWithOptions { if (!hasOptions(model)) { return model; } @@ -275,7 +265,7 @@ export const changeVariableMultiValue = (identifier: KeyedVariableIdentifier, mu }; }; -export const processVariableDependencies = async (variable: VariableModel, state: StoreState) => { +export const processVariableDependencies = async (variable: TypedVariableModel, state: StoreState) => { if (!variable.rootStateKey) { throw new Error(`rootStateKey not found for variable with id:${variable.id}`); } @@ -305,7 +295,7 @@ export const processVariableDependencies = async (variable: VariableModel, state }; const isDependencyGraphCircular = ( - variable: VariableModel, + variable: TypedVariableModel, state: StoreState, encounteredDependencyIds: Set = new Set() ): boolean => { @@ -320,12 +310,12 @@ const isDependencyGraphCircular = ( }); }; -const getDirectDependencies = (variable: VariableModel, state: StoreState) => { +const getDirectDependencies = (variable: TypedVariableModel, state: StoreState) => { if (!variable.rootStateKey) { return []; } - const directDependencies: VariableModel[] = []; + const directDependencies: TypedVariableModel[] = []; for (const otherVariable of getVariablesByKey(variable.rootStateKey, state)) { if (variable === otherVariable) { @@ -342,7 +332,7 @@ const getDirectDependencies = (variable: VariableModel, state: StoreState) => { return directDependencies; }; -const isWaitingForDependencies = (key: string, dependencies: VariableModel[], state: StoreState): boolean => { +const isWaitingForDependencies = (key: string, dependencies: TypedVariableModel[], state: StoreState): boolean => { if (dependencies.length === 0) { return false; } @@ -395,8 +385,7 @@ export const processVariables = (key: string): ThunkResult> => { return async (dispatch, getState) => { const queryParams = locationService.getSearchObject(); const promises = getVariablesByKey(key, getState()).map( - async (variable: VariableModel) => - await dispatch(processVariable(toKeyedVariableIdentifier(variable), queryParams)) + async (variable) => await dispatch(processVariable(toKeyedVariableIdentifier(variable), queryParams)) ); await Promise.all(promises); @@ -571,7 +560,7 @@ export const setOptionAsCurrent = ( }; }; -export const createGraph = (variables: VariableModel[]) => { +export const createGraph = (variables: TypedVariableModel[]) => { const g = new Graph(); variables.forEach((v) => { @@ -618,13 +607,14 @@ export const variableUpdated = ( const panels = state.dashboard?.getModel()?.panels ?? []; const panelVars = getPanelVars(panels); - const event: VariablesChangedEvent = isAdHoc(variableInState) - ? { refreshAll: true, panelIds: [] } // for adhoc variables we don't know which panels that will be impacted - : { - refreshAll: false, - panelIds: Array.from(getAllAffectedPanelIdsForVariableChange([variableInState.id], g, panelVars)), - variable: getVariable(identifier, state), - }; + const event: VariablesChangedEvent = + variableInState.type === 'adhoc' + ? { refreshAll: true, panelIds: [] } // for adhoc variables we don't know which panels that will be impacted + : { + refreshAll: false, + panelIds: Array.from(getAllAffectedPanelIdsForVariableChange([variableInState.id], g, panelVars)), + variable: getVariable(identifier, state), + }; const node = g.getNode(variableInState.name); let promises: Array> = []; @@ -653,7 +643,12 @@ export interface OnTimeRangeUpdatedDependencies { events: typeof appEvents; } -const dfs = (node: Node, visited: string[], variables: VariableModel[], variablesRefreshTimeRange: VariableModel[]) => { +const dfs = ( + node: Node, + visited: string[], + variables: TypedVariableModel[], + variablesRefreshTimeRange: TypedVariableModel[] +) => { if (!visited.includes(node.name)) { visited.push(node.name); } @@ -858,7 +853,7 @@ export const templateVarsChangedInUrl = value = variableInModel.current.value; // revert value to the value stored in dashboard json } - if (variableInModel && isConstant(variableInModel)) { + if (variableInModel && variableInModel.type === 'constant') { value = variableInModel.query; // revert value to the value stored in dashboard json, constants don't store current values in dashboard json } } @@ -869,7 +864,9 @@ export const templateVarsChangedInUrl = const filteredVars = variables.filter((v) => { const key = VARIABLE_PREFIX + v.name; - return vars.hasOwnProperty(key) && isVariableUrlValueDifferentFromCurrent(v, vars[key].value) && !isAdHoc(v); + return ( + vars.hasOwnProperty(key) && isVariableUrlValueDifferentFromCurrent(v, vars[key].value) && v.type !== 'adhoc' + ); }); const varGraph = createGraph(variables); const panelVars = getPanelVars(dashboard?.panels ?? []); @@ -891,7 +888,7 @@ export const templateVarsChangedInUrl = } }; -export function isVariableUrlValueDifferentFromCurrent(variable: VariableModel, urlValue: any): boolean { +export function isVariableUrlValueDifferentFromCurrent(variable: TypedVariableModel, urlValue: any): boolean { const variableValue = variableAdapters.get(variable.type).getValueForUrl(variable); let stringUrlValue = ensureStringValues(urlValue); if (Array.isArray(variableValue) && !Array.isArray(stringUrlValue)) { @@ -963,7 +960,7 @@ export function migrateVariablesDatasourceNameToRef( return (dispatch, getState) => { const variables = getVariablesByKey(key, getState()); for (const variable of variables) { - if (!isAdHoc(variable) && !isQuery(variable)) { + if (variable.type !== 'adhoc' && variable.type !== 'query') { continue; } diff --git a/public/app/features/variables/state/helpers.ts b/public/app/features/variables/state/helpers.ts index 90f3057e093..9752d6ecf5a 100644 --- a/public/app/features/variables/state/helpers.ts +++ b/public/app/features/variables/state/helpers.ts @@ -1,20 +1,19 @@ import { combineReducers } from '@reduxjs/toolkit'; -import { TypedVariableModel } from '@grafana/data'; +import { + TypedVariableModel, + DashboardVariableModel, + OrgVariableModel, + UserVariableModel, + VariableHide, +} from '@grafana/data'; import { VariableRefresh } from '@grafana/schema'; import { dashboardReducer } from 'app/features/dashboard/state/reducers'; import { DashboardState, StoreState } from '../../../types'; import { VariableAdapter } from '../adapters'; import { NEW_VARIABLE_ID } from '../constants'; -import { - DashboardVariableModel, - initialVariableModelState, - OrgVariableModel, - UserVariableModel, - VariableHide, - VariableModel, -} from '../types'; +import { initialVariableModelState } from '../types'; import { createQueryVariable } from './__tests__/fixtures'; import { keyedVariablesReducer, KeyedVariablesState } from './keyedVariablesReducer'; @@ -112,7 +111,7 @@ export const getVariableTestContext = ( adapter: VariableAdapter, variableOverrides: Partial = {} ) => { - const defaults: Partial = { + const defaults: Partial = { id: '0', rootStateKey: 'key', index: 0, diff --git a/public/app/features/variables/state/sharedReducer.ts b/public/app/features/variables/state/sharedReducer.ts index ba4d6567a39..ec8b5ae093e 100644 --- a/public/app/features/variables/state/sharedReducer.ts +++ b/public/app/features/variables/state/sharedReducer.ts @@ -1,12 +1,11 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit'; import { cloneDeep, defaults as lodashDefaults } from 'lodash'; -import { LoadingState, VariableType } from '@grafana/data'; +import { LoadingState, VariableType, TypedVariableModel, VariableOption } from '@grafana/data'; import { variableAdapters } from '../adapters'; import { changeVariableNameSucceeded } from '../editor/reducer'; import { hasOptions } from '../guard'; -import { VariableModel, VariableOption } from '../types'; import { ensureStringValues } from '../utils'; import { getInstanceState, getNextVariableIndex } from './selectors'; @@ -77,7 +76,7 @@ const sharedReducerSlice = createSlice({ return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); } - const original = cloneDeep(state[action.payload.id]); + const original = cloneDeep(state[action.payload.id]); const copyRegex = new RegExp(`^copy_of_${escapeRegExp(original.name)}(_(\\d+))?$`); const copies = Object.values(state) diff --git a/public/app/features/variables/utils.ts b/public/app/features/variables/utils.ts index bc137c3c7df..8ab8906f7e2 100644 --- a/public/app/features/variables/utils.ts +++ b/public/app/features/variables/utils.ts @@ -1,6 +1,15 @@ import { isArray, isEqual } from 'lodash'; -import { LegacyMetricFindQueryOptions, ScopedVars, UrlQueryMap, UrlQueryValue, VariableType } from '@grafana/data'; +import { + LegacyMetricFindQueryOptions, + ScopedVars, + UrlQueryMap, + UrlQueryValue, + VariableType, + VariableRefresh, + VariableWithOptions, + QueryVariableModel, +} from '@grafana/data'; import { getTemplateSrv } from '@grafana/runtime'; import { safeStringifyValue } from 'app/core/utils/explore'; @@ -12,7 +21,7 @@ import { variableAdapters } from './adapters'; import { ALL_VARIABLE_TEXT, ALL_VARIABLE_VALUE, VARIABLE_PREFIX } from './constants'; import { getVariablesState } from './state/selectors'; import { KeyedVariableIdentifier, VariableIdentifier, VariablePayload } from './state/types'; -import { QueryVariableModel, TransactionStatus, VariableModel, VariableRefresh, VariableWithOptions } from './types'; +import { TransactionStatus, VariableModel } from './types'; /* * This regex matches 3 types of variable reference with an optional format specifier diff --git a/public/app/plugins/datasource/azuremonitor/azure_log_analytics/utils.ts b/public/app/plugins/datasource/azuremonitor/azure_log_analytics/utils.ts index 1e61ef898ca..e66afc46696 100644 --- a/public/app/plugins/datasource/azuremonitor/azure_log_analytics/utils.ts +++ b/public/app/plugins/datasource/azuremonitor/azure_log_analytics/utils.ts @@ -1,4 +1,4 @@ -import { VariableModel } from '@grafana/data'; +import { TypedVariableModel } from '@grafana/data'; import { EngineSchema } from '../types'; import { AzureLogAnalyticsMetadata } from '../types/logAnalyticsMetadata'; @@ -48,7 +48,7 @@ function transformMetadataFunction(sourceSchema: AzureLogAnalyticsMetadata) { export function transformMetadataToKustoSchema( sourceSchema: AzureLogAnalyticsMetadata, nameOrIdOrSomething: string, - templateVariables: VariableModel[] + templateVariables: TypedVariableModel[] ): EngineSchema { const database = { name: nameOrIdOrSomething,