diff --git a/public/app/features/dashboard-scene/settings/variables/VariableEditorList.tsx b/public/app/features/dashboard-scene/settings/variables/VariableEditorList.tsx index f04e8e7b9ea..cc2fcb41ef6 100644 --- a/public/app/features/dashboard-scene/settings/variables/VariableEditorList.tsx +++ b/public/app/features/dashboard-scene/settings/variables/VariableEditorList.tsx @@ -8,6 +8,8 @@ import { SceneVariable, SceneVariableState } from '@grafana/scenes'; import { useStyles2, Stack, Button, EmptyState, TextLink } from '@grafana/ui'; import { t, Trans } from 'app/core/internationalization'; +import { VariablesDependenciesButton } from '../../variables/VariablesDependenciesButton'; + import { VariableEditorListRow } from './VariableEditorListRow'; export interface Props { @@ -81,6 +83,7 @@ export function VariableEditorList({ + + ); + }} + + ); +}; diff --git a/public/app/features/dashboard-scene/variables/utils.test.ts b/public/app/features/dashboard-scene/variables/utils.test.ts new file mode 100644 index 00000000000..9d5d99e4b88 --- /dev/null +++ b/public/app/features/dashboard-scene/variables/utils.test.ts @@ -0,0 +1,40 @@ +import { TestVariable } from '@grafana/scenes'; +import { variableAdapters } from 'app/features/variables/adapters'; +import { createCustomVariableAdapter } from 'app/features/variables/custom/adapter'; +import { createDataSourceVariableAdapter } from 'app/features/variables/datasource/adapter'; +import { createQueryVariableAdapter } from 'app/features/variables/query/adapter'; + +import { createDependencyEdges, createDependencyNodes } from './utils'; + +variableAdapters.setInit(() => [ + createDataSourceVariableAdapter(), + createCustomVariableAdapter(), + createQueryVariableAdapter(), +]); + +describe('createDependencyNodes', () => { + it('should create node for each variable', () => { + const variables = [ + new TestVariable({ name: 'A', query: 'A.*', value: '', text: '', options: [] }), + new TestVariable({ name: 'B', query: 'B.*', value: '', text: '', options: [] }), + new TestVariable({ name: 'C', query: 'C.*', value: '', text: '', options: [] }), + ]; + const graphNodes = createDependencyNodes(variables); + expect(graphNodes[0].id).toBe('A'); + expect(graphNodes[1].id).toBe('B'); + expect(graphNodes[2].id).toBe('C'); + }); +}); + +describe('createDependencyEdges', () => { + it('should create edges for variable dependencies', () => { + const variables = [ + new TestVariable({ name: 'A', query: 'A.*', value: '', text: '', options: [] }), + new TestVariable({ name: 'B', query: '${A}.*', value: '', text: '', options: [] }), + new TestVariable({ name: 'C', query: '${B}.*', value: '', text: '', options: [] }), + ]; + const graphEdges = createDependencyEdges(variables); + expect(graphEdges).toContainEqual({ from: 'B', to: 'A' }); + expect(graphEdges).toContainEqual({ from: 'C', to: 'B' }); + }); +}); diff --git a/public/app/features/dashboard-scene/variables/utils.ts b/public/app/features/dashboard-scene/variables/utils.ts new file mode 100644 index 00000000000..d5bc99e401c --- /dev/null +++ b/public/app/features/dashboard-scene/variables/utils.ts @@ -0,0 +1,28 @@ +import { SceneVariable, SceneVariableState } from '@grafana/scenes'; +import { GraphEdge, GraphNode } from 'app/features/variables/inspect/utils'; + +export function createDependencyNodes(variables: Array>): GraphNode[] { + return variables.map((variable) => ({ id: variable.state.name, label: `${variable.state.name}` })); +} + +export function filterNodesWithDependencies(nodes: GraphNode[], edges: GraphEdge[]): GraphNode[] { + return nodes.filter((node) => edges.some((edge) => edge.from === node.id || edge.to === node.id)); +} + +export const createDependencyEdges = (variables: Array>): GraphEdge[] => { + const edges: GraphEdge[] = []; + for (const variable of variables) { + for (const other of variables) { + if (variable === other) { + continue; + } + + const dependsOn = variable.variableDependency?.hasDependencyOn(other.state.name); + if (dependsOn) { + edges.push({ from: variable.state.name, to: other.state.name }); + } + } + } + + return edges; +}; diff --git a/public/app/features/variables/inspect/VariablesDependenciesButton.tsx b/public/app/features/variables/inspect/VariablesDependenciesButton.tsx index 2386a890b03..f57527a86be 100644 --- a/public/app/features/variables/inspect/VariablesDependenciesButton.tsx +++ b/public/app/features/variables/inspect/VariablesDependenciesButton.tsx @@ -1,26 +1,17 @@ import React, { useMemo } from 'react'; -import { Provider } from 'react-redux'; +import { TypedVariableModel } from '@grafana/data'; import { reportInteraction } from '@grafana/runtime'; import { Button } from '@grafana/ui'; -import { store } from '../../../store/store'; -import { VariableModel } from '../types'; - import { NetworkGraphModal } from './NetworkGraphModal'; import { createDependencyEdges, createDependencyNodes, filterNodesWithDependencies } from './utils'; -interface OwnProps { - variables: VariableModel[]; +interface Props { + variables: TypedVariableModel[]; } -interface ConnectedProps {} - -interface DispatchProps {} - -type Props = OwnProps & ConnectedProps & DispatchProps; - -export const UnProvidedVariablesDependenciesButton = ({ variables }: Props) => { +export const VariablesDependenciesButton = ({ variables }: Props) => { const nodes = useMemo(() => createDependencyNodes(variables), [variables]); const edges = useMemo(() => createDependencyEdges(variables), [variables]); @@ -52,9 +43,3 @@ export const UnProvidedVariablesDependenciesButton = ({ variables }: Props) => { ); }; - -export const VariablesDependenciesButton = (props: Props) => ( - - - -); diff --git a/public/locales/en-US/grafana.json b/public/locales/en-US/grafana.json index 66793ded596..8d9fd95fbf6 100644 --- a/public/locales/en-US/grafana.json +++ b/public/locales/en-US/grafana.json @@ -453,6 +453,16 @@ "title": "Versions" } }, + "dashboards": { + "settings": { + "variables": { + "dependencies": { + "button": "Show dependencies", + "title": "Dependencies" + } + } + } + }, "data-source-list": { "empty-state": { "button-title": "Add data source", diff --git a/public/locales/pseudo-LOCALE/grafana.json b/public/locales/pseudo-LOCALE/grafana.json index f0455ab7fb1..c9b676d7374 100644 --- a/public/locales/pseudo-LOCALE/grafana.json +++ b/public/locales/pseudo-LOCALE/grafana.json @@ -453,6 +453,16 @@ "title": "Vęřşįőʼnş" } }, + "dashboards": { + "settings": { + "variables": { + "dependencies": { + "button": "Ŝĥőŵ đępęʼnđęʼnčįęş", + "title": "Đępęʼnđęʼnčįęş" + } + } + } + }, "data-source-list": { "empty-state": { "button-title": "Åđđ đäŧä şőūřčę",