Typed variables pt3: Type VariableState with TypedVariableModel (#53015)
* wip * make diff easier to read * Update template_srv getVariables to return new TypedVariableModel * update VariableType to use the type from TypedVariableModel * tidy things up * Chore: Use type-accurate mock variables in tests * Chore: Type VariableState to use TypedVariableModel * fix typo * remove type assertion from template_srv.getVariables * undo whatever changes i did to swagger spec
This commit is contained in:
@@ -6229,9 +6229,6 @@ exports[`better eslint`] = {
|
|||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
|
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
|
||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
|
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
|
||||||
],
|
],
|
||||||
"public/app/features/variables/state/variablesReducer.ts:5381": [
|
|
||||||
[0, 0, 0, "Do not use any type assertions.", "0"]
|
|
||||||
],
|
|
||||||
"public/app/features/variables/system/adapter.ts:5381": [
|
"public/app/features/variables/system/adapter.ts:5381": [
|
||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
|
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
|
||||||
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
|
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
|
||||||
|
|||||||
@@ -63,9 +63,7 @@ export class TemplateSrv implements BaseTemplateSrv {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getVariables(): TypedVariableModel[] {
|
getVariables(): TypedVariableModel[] {
|
||||||
// TODO: we remove this type assertion in a later PR
|
return this.dependencies.getVariables();
|
||||||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
||||||
return this.dependencies.getVariables() as TypedVariableModel[];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
updateIndex() {
|
updateIndex() {
|
||||||
|
|||||||
@@ -1,14 +1,19 @@
|
|||||||
import memoizeOne from 'memoize-one';
|
import memoizeOne from 'memoize-one';
|
||||||
|
|
||||||
|
import { TypedVariableModel, VariableWithMultiSupport, VariableWithOptions } from '@grafana/data';
|
||||||
|
|
||||||
import { getState } from '../../../store/store';
|
import { getState } from '../../../store/store';
|
||||||
import { StoreState } from '../../../types';
|
import { StoreState } from '../../../types';
|
||||||
import { VariableModel } from '../types';
|
|
||||||
import { toStateKey } from '../utils';
|
import { toStateKey } from '../utils';
|
||||||
|
|
||||||
import { getInitialTemplatingState, TemplatingState } from './reducers';
|
import { getInitialTemplatingState, TemplatingState } from './reducers';
|
||||||
import { KeyedVariableIdentifier, VariablesState } from './types';
|
import { KeyedVariableIdentifier, VariablesState } from './types';
|
||||||
|
|
||||||
export const getVariable = <T extends VariableModel = VariableModel>(
|
// TODO: this is just a temporary type until we remove generics from getVariable and getInstanceState in a later PR
|
||||||
|
// we need to it satisfy the constraint of callers who specify VariableWithOptions or VariableWithMultiSupport
|
||||||
|
type GenericVariableModel = TypedVariableModel | VariableWithOptions | VariableWithMultiSupport;
|
||||||
|
|
||||||
|
export const getVariable = <T extends GenericVariableModel = GenericVariableModel>(
|
||||||
identifier: KeyedVariableIdentifier,
|
identifier: KeyedVariableIdentifier,
|
||||||
state: StoreState = getState(),
|
state: StoreState = getState(),
|
||||||
throwWhenMissing = true
|
throwWhenMissing = true
|
||||||
@@ -26,7 +31,7 @@ export const getVariable = <T extends VariableModel = VariableModel>(
|
|||||||
};
|
};
|
||||||
|
|
||||||
function getFilteredVariablesByKey(
|
function getFilteredVariablesByKey(
|
||||||
filter: (model: VariableModel) => boolean,
|
filter: (model: TypedVariableModel) => boolean,
|
||||||
key: string,
|
key: string,
|
||||||
state: StoreState = getState()
|
state: StoreState = getState()
|
||||||
) {
|
) {
|
||||||
@@ -39,21 +44,21 @@ export function getVariablesState(key: string, state: StoreState = getState()):
|
|||||||
return state.templating.keys[toStateKey(key)] ?? getInitialTemplatingState();
|
return state.templating.keys[toStateKey(key)] ?? getInitialTemplatingState();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getVariablesByKey(key: string, state: StoreState = getState()): VariableModel[] {
|
export function getVariablesByKey(key: string, state: StoreState = getState()): TypedVariableModel[] {
|
||||||
return getFilteredVariablesByKey(defaultVariablesFilter, key, state);
|
return getFilteredVariablesByKey(defaultVariablesFilter, key, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
function defaultVariablesFilter(variable: VariableModel): boolean {
|
function defaultVariablesFilter(variable: TypedVariableModel): boolean {
|
||||||
return variable.type !== 'system';
|
return variable.type !== 'system';
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getSubMenuVariables = memoizeOne(
|
export const getSubMenuVariables = memoizeOne(
|
||||||
(key: string, variables: Record<string, VariableModel>): VariableModel[] => {
|
(key: string, variables: Record<string, TypedVariableModel>): TypedVariableModel[] => {
|
||||||
return getVariablesByKey(key, getState());
|
return getVariablesByKey(key, getState());
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
export const getEditorVariables = (key: string, state: StoreState): VariableModel[] => {
|
export const getEditorVariables = (key: string, state: StoreState): TypedVariableModel[] => {
|
||||||
return getVariablesByKey(key, state);
|
return getVariablesByKey(key, state);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -63,7 +68,7 @@ export function getNewVariableIndex(key: string, state: StoreState = getState())
|
|||||||
return getNextVariableIndex(Object.values(getVariablesState(key, state).variables));
|
return getNextVariableIndex(Object.values(getVariablesState(key, state).variables));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getNextVariableIndex(variables: VariableModel[]): number {
|
export function getNextVariableIndex(variables: TypedVariableModel[]): number {
|
||||||
const sorted = variables.filter(defaultVariablesFilter).sort((v1, v2) => v1.index - v2.index);
|
const sorted = variables.filter(defaultVariablesFilter).sort((v1, v2) => v1.index - v2.index);
|
||||||
return sorted.length > 0 ? sorted[sorted.length - 1].index + 1 : 0;
|
return sorted.length > 0 ? sorted[sorted.length - 1].index + 1 : 0;
|
||||||
}
|
}
|
||||||
@@ -85,7 +90,7 @@ export function getLastKey(state: StoreState = getState()): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// selectors used by template srv, assumes that lastKey is in state. Needs to change when/if dashboard redux state becomes keyed too.
|
// selectors used by template srv, assumes that lastKey is in state. Needs to change when/if dashboard redux state becomes keyed too.
|
||||||
export function getFilteredVariables(filter: (model: VariableModel) => boolean, state: StoreState = getState()) {
|
export function getFilteredVariables(filter: (model: TypedVariableModel) => boolean, state: StoreState = getState()) {
|
||||||
const lastKey = getIfExistsLastKey(state);
|
const lastKey = getIfExistsLastKey(state);
|
||||||
if (!lastKey) {
|
if (!lastKey) {
|
||||||
return [];
|
return [];
|
||||||
@@ -109,6 +114,10 @@ export function getVariableWithName(name: string, state: StoreState = getState()
|
|||||||
return getVariable({ id: name, rootStateKey: lastKey, type: 'query' }, state, false);
|
return getVariable({ id: name, rootStateKey: lastKey, type: 'query' }, state, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getInstanceState<Model extends VariableModel = VariableModel>(state: VariablesState, id: string) {
|
// TODO: remove the generic and type assertion in a later PR
|
||||||
|
export function getInstanceState<Model extends GenericVariableModel = GenericVariableModel>(
|
||||||
|
state: VariablesState,
|
||||||
|
id: string
|
||||||
|
) {
|
||||||
return state[id] as Model;
|
return state[id] as Model;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { VariableType } from '@grafana/data';
|
import { VariableType, TypedVariableModel } from '@grafana/data';
|
||||||
|
|
||||||
import { VariableModel } from '../types';
|
import { VariableModel } from '../types';
|
||||||
|
|
||||||
export interface VariablesState extends Record<string, VariableModel> {}
|
export type VariablesState = Record<string, TypedVariableModel>;
|
||||||
|
|
||||||
export const initialVariablesState: VariablesState = {};
|
export const initialVariablesState: VariablesState = {};
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import { createAction } from '@reduxjs/toolkit';
|
|||||||
import { AnyAction } from 'redux';
|
import { AnyAction } from 'redux';
|
||||||
|
|
||||||
import { variableAdapters } from '../adapters';
|
import { variableAdapters } from '../adapters';
|
||||||
import { VariableModel } from '../types';
|
|
||||||
|
|
||||||
import { sharedReducer } from './sharedReducer';
|
import { sharedReducer } from './sharedReducer';
|
||||||
import { initialVariablesState, VariablesState } from './types';
|
import { initialVariablesState, VariablesState } from './types';
|
||||||
@@ -16,10 +15,10 @@ export const variablesReducer = (state: VariablesState = initialVariablesState,
|
|||||||
return initialVariablesState;
|
return initialVariablesState;
|
||||||
}
|
}
|
||||||
|
|
||||||
const variables = globalVariables.reduce((allVariables, state) => {
|
const variables = globalVariables.reduce<typeof state>((allVariables, state) => {
|
||||||
allVariables[state.id] = state;
|
allVariables[state.id] = state;
|
||||||
return allVariables;
|
return allVariables;
|
||||||
}, {} as Record<string, VariableModel>);
|
}, {});
|
||||||
|
|
||||||
return variables;
|
return variables;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user