Chore: Change VariableModel to TypedVariableModel in most places (#76690)

This commit is contained in:
kay delaney 2023-11-08 22:15:29 +00:00 committed by GitHub
parent 3559cb4e81
commit 375dcc3813
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 134 additions and 147 deletions

View File

@ -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();
});
});

View File

@ -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';

View File

@ -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);
});
});

View File

@ -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;
};

View File

@ -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 {}

View File

@ -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<VariableModel[]>([]);
const [visibleVariables, setVisibleVariables] = useState<TypedVariableModel[]>([]);
useEffect(() => {
setVisibleVariables(variables.filter((state) => state.hide !== VariableHide.hideVariable));
@ -23,17 +23,15 @@ export const SubMenuItems = ({ variables, readOnly }: Props) => {
return (
<>
{visibleVariables.map((variable) => {
return (
<div
key={variable.id}
className="submenu-item gf-form-inline"
data-testid={selectors.pages.Dashboard.SubMenu.submenuItem}
>
<PickerRenderer variable={variable} readOnly={readOnly} />
</div>
);
})}
{visibleVariables.map((variable) => (
<div
key={variable.id}
className="submenu-item gf-form-inline"
data-testid={selectors.pages.Dashboard.SubMenu.submenuItem}
>
<PickerRenderer variable={variable} readOnly={readOnly} />
</div>
))}
</>
);
};

View File

@ -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<VariableModel>,
createAdHocVariableAdapter() as unknown as VariableAdapter<VariableModel>,
createQueryVariableAdapter() as unknown as VariableAdapter<TypedVariableModel>,
createAdHocVariableAdapter() as unknown as VariableAdapter<TypedVariableModel>,
]);
const interpolateMock = jest.fn();

View File

@ -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<Model extends VariableModel> {
export interface VariableAdapter<Model extends TypedVariableModel> {
id: VariableType;
description: string;
name: string;

View File

@ -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;

View File

@ -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({
<td role="gridcell" className={styles.column}>
<div className={styles.icons}>
<VariableCheckIndicator passed={passed} />
<VariableUsagesButton id={variable.id} isAdhoc={isAdHoc(variable)} usages={usagesNetwork} />
<VariableUsagesButton id={variable.id} isAdhoc={variable.type === 'adhoc'} usages={usagesNetwork} />
<IconButton
onClick={(event) => {
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') {

View File

@ -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}`;

View File

@ -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;
}

View File

@ -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'

View File

@ -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<string> = 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<Promise<void>> => {
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<Promise<any>> = [];
@ -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;
}

View File

@ -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 = <Model extends TypedVariableModel>(
adapter: VariableAdapter<Model>,
variableOverrides: Partial<Model> = {}
) => {
const defaults: Partial<VariableModel> = {
const defaults: Partial<TypedVariableModel> = {
id: '0',
rootStateKey: 'key',
index: 0,

View File

@ -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<VariableModel>(state[action.payload.id]);
const original = cloneDeep<TypedVariableModel>(state[action.payload.id]);
const copyRegex = new RegExp(`^copy_of_${escapeRegExp(original.name)}(_(\\d+))?$`);
const copies = Object.values(state)

View File

@ -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

View File

@ -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,