fix(variable_hydration): limiting variable hydration to changing variables (#18071)
parent
0360d0d5c0
commit
0c44328419
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
1. [18066](https://github.com/influxdata/influxdb/pull/18066): Fixed bug that wasn't persisting timeFormat for Graph + Single Stat selections
|
||||
1. [17959](https://github.com/influxdata/influxdb/pull/17959): Authorizer now exposes full permission set
|
||||
1. [18071](https://github.com/influxdata/influxdb/pull/18071): Fixed issue that was causing variable selections to hydrate all variable values
|
||||
|
||||
### UI Improvements
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ const GraphTips: FC = () => (
|
|||
color={ComponentColor.Primary}
|
||||
testID="graphtips-question-mark"
|
||||
tooltipContents={
|
||||
<span>
|
||||
<>
|
||||
<h1>Graph Tips:</h1>
|
||||
<p>
|
||||
<code>Click + Drag</code> Zoom in (X or Y)
|
||||
|
|
@ -22,11 +22,11 @@ const GraphTips: FC = () => (
|
|||
</p>
|
||||
<h1>Static Legend Tips:</h1>
|
||||
<p>
|
||||
<code>Click</code>Focus on single Series
|
||||
<code>Click</code> Focus on single Series
|
||||
<br />
|
||||
<code>Shift + Click</code> Show/Hide single Series
|
||||
</p>
|
||||
</span>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
</>
|
||||
|
|
|
|||
|
|
@ -147,6 +147,34 @@ export const hydrateVariables = (skipCache?: boolean) => async (
|
|||
await hydration.promise
|
||||
}
|
||||
|
||||
export const hydrateChangedVariable = (variableID: string) => async (
|
||||
dispatch: Dispatch<Action>,
|
||||
getState: GetState
|
||||
) => {
|
||||
const state = getState()
|
||||
const org = getOrg(state)
|
||||
const variable = getVariableFromState(state, variableID)
|
||||
const hydration = hydrateVars([variable], getAllVariablesFromState(state), {
|
||||
orgID: org.id,
|
||||
url: state.links.query.self,
|
||||
skipCache: true,
|
||||
})
|
||||
hydration.on('status', (variable, status) => {
|
||||
if (status === RemoteDataState.Loading) {
|
||||
dispatch(setVariable(variable.id, status))
|
||||
return
|
||||
}
|
||||
if (status === RemoteDataState.Done) {
|
||||
const _variable = normalize<Variable, VariableEntities, string>(
|
||||
variable,
|
||||
variableSchema
|
||||
)
|
||||
dispatch(setVariable(variable.id, RemoteDataState.Done, _variable))
|
||||
}
|
||||
})
|
||||
await hydration.promise
|
||||
}
|
||||
|
||||
export const getVariable = (id: string) => async (
|
||||
dispatch: Dispatch<Action>
|
||||
) => {
|
||||
|
|
@ -397,7 +425,6 @@ export const selectValue = (variableID: string, selected: string) => async (
|
|||
const state = getState()
|
||||
const contextID = currentContext(state)
|
||||
const variable = getVariableFromState(state, variableID)
|
||||
|
||||
// Validate that we can make this selection
|
||||
const vals = normalizeValues(variable)
|
||||
if (!vals.includes(selected)) {
|
||||
|
|
@ -405,7 +432,7 @@ export const selectValue = (variableID: string, selected: string) => async (
|
|||
}
|
||||
|
||||
await dispatch(selectValueInState(contextID, variableID, selected))
|
||||
|
||||
dispatch(hydrateVariables(true))
|
||||
// only hydrate the changedVariable
|
||||
dispatch(hydrateChangedVariable(variableID))
|
||||
dispatch(updateQueryVars({[variable.name]: selected}))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -97,9 +97,16 @@ class VariableDropdown extends PureComponent<Props> {
|
|||
}
|
||||
|
||||
private handleSelect = (selectedValue: string) => {
|
||||
const {variableID, onSelectValue, onSelect} = this.props
|
||||
const {
|
||||
variableID,
|
||||
onSelectValue,
|
||||
onSelect,
|
||||
selectedValue: prevSelectedValue,
|
||||
} = this.props
|
||||
|
||||
onSelectValue(variableID, selectedValue)
|
||||
if (prevSelectedValue !== selectedValue) {
|
||||
onSelectValue(variableID, selectedValue)
|
||||
}
|
||||
|
||||
if (onSelect) {
|
||||
onSelect()
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// Types
|
||||
import {Variable, RemoteDataState} from 'src/types'
|
||||
import {VariableAssignment} from 'src/types/ast'
|
||||
import {VariableNode} from 'src/variables/utils/hydrateVars'
|
||||
|
||||
export const defaultVariableAssignments: VariableAssignment[] = [
|
||||
{
|
||||
|
|
@ -78,3 +79,652 @@ export const createMapVariable = (
|
|||
},
|
||||
status: RemoteDataState.Done,
|
||||
})
|
||||
|
||||
export const defaultSubGraph: VariableNode[] = [
|
||||
{
|
||||
variable: {
|
||||
id: '05b740973c68e000',
|
||||
orgID: '05b740945a91b000',
|
||||
name: 'static',
|
||||
description: '',
|
||||
selected: ['defbuck'],
|
||||
arguments: {
|
||||
type: 'constant',
|
||||
values: ['beans', 'defbuck'],
|
||||
},
|
||||
createdAt: '2020-05-19T06:00:00.113169-07:00',
|
||||
updatedAt: '2020-05-19T06:00:00.113169-07:00',
|
||||
labels: [],
|
||||
links: {
|
||||
self: '/api/v2/variables/05b740973c68e000',
|
||||
labels: '/api/v2/variables/05b740973c68e000/labels',
|
||||
org: '/api/v2/orgs/05b740945a91b000',
|
||||
},
|
||||
status: RemoteDataState.Done,
|
||||
},
|
||||
values: null,
|
||||
parents: [
|
||||
{
|
||||
variable: {
|
||||
id: '05b740974228e000',
|
||||
orgID: '05b740945a91b000',
|
||||
name: 'dependent',
|
||||
description: '',
|
||||
selected: [],
|
||||
arguments: {
|
||||
type: 'query',
|
||||
values: {
|
||||
query:
|
||||
'from(bucket: v.static)\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r["_measurement"] == "test")\n |> keep(columns: ["container_name"])\n |> rename(columns: {"container_name": "_value"})\n |> last()\n |> group()',
|
||||
language: 'flux',
|
||||
results: [],
|
||||
},
|
||||
},
|
||||
createdAt: '2020-05-19T06:00:00.136597-07:00',
|
||||
updatedAt: '2020-05-19T06:00:00.136597-07:00',
|
||||
labels: [],
|
||||
links: {
|
||||
self: '/api/v2/variables/05b740974228e000',
|
||||
labels: '/api/v2/variables/05b740974228e000/labels',
|
||||
org: '/api/v2/orgs/05b740945a91b000',
|
||||
},
|
||||
status: RemoteDataState.Loading,
|
||||
},
|
||||
cancel: () => {},
|
||||
values: null,
|
||||
parents: [],
|
||||
children: [
|
||||
{
|
||||
variable: {
|
||||
orgID: '',
|
||||
id: 'timeRangeStart',
|
||||
name: 'timeRangeStart',
|
||||
arguments: {
|
||||
type: 'system',
|
||||
values: [
|
||||
[
|
||||
{
|
||||
magnitude: 1,
|
||||
unit: 'h',
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
status: RemoteDataState.Done,
|
||||
labels: [],
|
||||
selected: [],
|
||||
},
|
||||
values: null,
|
||||
parents: [null],
|
||||
children: [],
|
||||
status: RemoteDataState.Done,
|
||||
cancel: () => {},
|
||||
},
|
||||
{
|
||||
variable: {
|
||||
orgID: '',
|
||||
id: 'timeRangeStop',
|
||||
name: 'timeRangeStop',
|
||||
arguments: {
|
||||
type: 'system',
|
||||
values: ['now()'],
|
||||
},
|
||||
status: RemoteDataState.Done,
|
||||
labels: [],
|
||||
selected: [],
|
||||
},
|
||||
values: null,
|
||||
parents: [null],
|
||||
children: [],
|
||||
status: RemoteDataState.Done,
|
||||
cancel: () => {},
|
||||
},
|
||||
],
|
||||
status: RemoteDataState.NotStarted,
|
||||
},
|
||||
],
|
||||
children: [],
|
||||
status: RemoteDataState.Done,
|
||||
cancel: () => {},
|
||||
},
|
||||
]
|
||||
|
||||
export const defaultGraph: VariableNode[] = [
|
||||
{
|
||||
variable: {
|
||||
id: '05b740973c68e000',
|
||||
orgID: '05b740945a91b000',
|
||||
name: 'static',
|
||||
description: '',
|
||||
selected: ['defbuck'],
|
||||
arguments: {
|
||||
type: 'constant',
|
||||
values: ['beans', 'defbuck'],
|
||||
},
|
||||
createdAt: '2020-05-19T06:00:00.113169-07:00',
|
||||
updatedAt: '2020-05-19T06:00:00.113169-07:00',
|
||||
labels: [],
|
||||
links: {
|
||||
self: '/api/v2/variables/05b740973c68e000',
|
||||
labels: '/api/v2/variables/05b740973c68e000/labels',
|
||||
org: '/api/v2/orgs/05b740945a91b000',
|
||||
},
|
||||
status: RemoteDataState.Done,
|
||||
},
|
||||
values: null,
|
||||
parents: [
|
||||
{
|
||||
cancel: () => {},
|
||||
variable: {
|
||||
id: '05b740974228e000',
|
||||
orgID: '05b740945a91b000',
|
||||
name: 'dependent',
|
||||
description: '',
|
||||
selected: [],
|
||||
arguments: {
|
||||
type: 'query',
|
||||
values: {
|
||||
query:
|
||||
'from(bucket: v.static)\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r["_measurement"] == "test")\n |> keep(columns: ["container_name"])\n |> rename(columns: {"container_name": "_value"})\n |> last()\n |> group()',
|
||||
language: 'flux',
|
||||
results: [],
|
||||
},
|
||||
},
|
||||
createdAt: '2020-05-19T06:00:00.136597-07:00',
|
||||
updatedAt: '2020-05-19T06:00:00.136597-07:00',
|
||||
labels: [],
|
||||
links: {
|
||||
self: '/api/v2/variables/05b740974228e000',
|
||||
labels: '/api/v2/variables/05b740974228e000/labels',
|
||||
org: '/api/v2/orgs/05b740945a91b000',
|
||||
},
|
||||
status: RemoteDataState.Loading,
|
||||
},
|
||||
values: null,
|
||||
parents: [],
|
||||
children: [
|
||||
{
|
||||
variable: {
|
||||
orgID: '',
|
||||
id: 'timeRangeStart',
|
||||
name: 'timeRangeStart',
|
||||
arguments: {
|
||||
type: 'system',
|
||||
values: [
|
||||
[
|
||||
{
|
||||
magnitude: 1,
|
||||
unit: 'h',
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
status: RemoteDataState.Done,
|
||||
labels: [],
|
||||
selected: [],
|
||||
},
|
||||
values: null,
|
||||
parents: [null],
|
||||
children: [],
|
||||
status: RemoteDataState.Done,
|
||||
cancel: () => {},
|
||||
},
|
||||
{
|
||||
variable: {
|
||||
orgID: '',
|
||||
id: 'timeRangeStop',
|
||||
name: 'timeRangeStop',
|
||||
arguments: {
|
||||
type: 'system',
|
||||
values: ['now()'],
|
||||
},
|
||||
status: RemoteDataState.Done,
|
||||
labels: [],
|
||||
selected: [],
|
||||
},
|
||||
values: null,
|
||||
parents: [null],
|
||||
children: [],
|
||||
status: RemoteDataState.Done,
|
||||
cancel: () => {},
|
||||
},
|
||||
],
|
||||
status: RemoteDataState.NotStarted,
|
||||
},
|
||||
],
|
||||
children: [],
|
||||
status: RemoteDataState.Done,
|
||||
cancel: () => {},
|
||||
},
|
||||
{
|
||||
variable: {
|
||||
id: '05b740974228e000',
|
||||
orgID: '05b740945a91b000',
|
||||
name: 'dependent',
|
||||
description: '',
|
||||
selected: [],
|
||||
arguments: {
|
||||
type: 'query',
|
||||
values: {
|
||||
query:
|
||||
'from(bucket: v.static)\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r["_measurement"] == "test")\n |> keep(columns: ["container_name"])\n |> rename(columns: {"container_name": "_value"})\n |> last()\n |> group()',
|
||||
language: 'flux',
|
||||
results: [],
|
||||
},
|
||||
},
|
||||
createdAt: '2020-05-19T06:00:00.136597-07:00',
|
||||
updatedAt: '2020-05-19T06:00:00.136597-07:00',
|
||||
labels: [],
|
||||
links: {
|
||||
self: '/api/v2/variables/05b740974228e000',
|
||||
labels: '/api/v2/variables/05b740974228e000/labels',
|
||||
org: '/api/v2/orgs/05b740945a91b000',
|
||||
},
|
||||
status: RemoteDataState.Loading,
|
||||
},
|
||||
values: null,
|
||||
parents: [],
|
||||
children: [
|
||||
{
|
||||
variable: {
|
||||
id: '05b740973c68e000',
|
||||
orgID: '05b740945a91b000',
|
||||
name: 'static',
|
||||
description: '',
|
||||
selected: ['defbuck'],
|
||||
arguments: {
|
||||
type: 'constant',
|
||||
values: ['beans', 'defbuck'],
|
||||
},
|
||||
createdAt: '2020-05-19T06:00:00.113169-07:00',
|
||||
updatedAt: '2020-05-19T06:00:00.113169-07:00',
|
||||
labels: [],
|
||||
links: {
|
||||
self: '/api/v2/variables/05b740973c68e000',
|
||||
labels: '/api/v2/variables/05b740973c68e000/labels',
|
||||
org: '/api/v2/orgs/05b740945a91b000',
|
||||
},
|
||||
status: RemoteDataState.Done,
|
||||
},
|
||||
values: null,
|
||||
parents: [null],
|
||||
children: [],
|
||||
status: RemoteDataState.Done,
|
||||
cancel: () => {},
|
||||
},
|
||||
{
|
||||
variable: {
|
||||
orgID: '',
|
||||
id: 'timeRangeStart',
|
||||
name: 'timeRangeStart',
|
||||
arguments: {
|
||||
type: 'system',
|
||||
values: [
|
||||
[
|
||||
{
|
||||
magnitude: 1,
|
||||
unit: 'h',
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
status: RemoteDataState.Done,
|
||||
labels: [],
|
||||
selected: [],
|
||||
},
|
||||
values: null,
|
||||
parents: [null],
|
||||
children: [],
|
||||
status: RemoteDataState.Done,
|
||||
cancel: () => {},
|
||||
},
|
||||
{
|
||||
variable: {
|
||||
orgID: '',
|
||||
id: 'timeRangeStop',
|
||||
name: 'timeRangeStop',
|
||||
arguments: {
|
||||
type: 'system',
|
||||
values: ['now()'],
|
||||
},
|
||||
status: RemoteDataState.Done,
|
||||
labels: [],
|
||||
selected: [],
|
||||
},
|
||||
values: null,
|
||||
parents: [null],
|
||||
children: [],
|
||||
status: RemoteDataState.Done,
|
||||
cancel: () => {},
|
||||
},
|
||||
],
|
||||
status: RemoteDataState.NotStarted,
|
||||
cancel: () => {},
|
||||
},
|
||||
{
|
||||
variable: {
|
||||
orgID: '',
|
||||
id: 'timeRangeStart',
|
||||
name: 'timeRangeStart',
|
||||
arguments: {
|
||||
type: 'system',
|
||||
values: [
|
||||
[
|
||||
{
|
||||
magnitude: 1,
|
||||
unit: 'h',
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
status: RemoteDataState.Done,
|
||||
labels: [],
|
||||
selected: [],
|
||||
},
|
||||
values: null,
|
||||
parents: [
|
||||
{
|
||||
variable: {
|
||||
id: '05b740974228e000',
|
||||
orgID: '05b740945a91b000',
|
||||
name: 'dependent',
|
||||
description: '',
|
||||
selected: [],
|
||||
arguments: {
|
||||
type: 'query',
|
||||
values: {
|
||||
query:
|
||||
'from(bucket: v.static)\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r["_measurement"] == "test")\n |> keep(columns: ["container_name"])\n |> rename(columns: {"container_name": "_value"})\n |> last()\n |> group()',
|
||||
language: 'flux',
|
||||
results: [],
|
||||
},
|
||||
},
|
||||
createdAt: '2020-05-19T06:00:00.136597-07:00',
|
||||
updatedAt: '2020-05-19T06:00:00.136597-07:00',
|
||||
labels: [],
|
||||
links: {
|
||||
self: '/api/v2/variables/05b740974228e000',
|
||||
labels: '/api/v2/variables/05b740974228e000/labels',
|
||||
org: '/api/v2/orgs/05b740945a91b000',
|
||||
},
|
||||
status: RemoteDataState.Loading,
|
||||
},
|
||||
values: null,
|
||||
parents: [],
|
||||
children: [
|
||||
{
|
||||
variable: {
|
||||
id: '05b740973c68e000',
|
||||
orgID: '05b740945a91b000',
|
||||
name: 'static',
|
||||
description: '',
|
||||
selected: ['defbuck'],
|
||||
arguments: {
|
||||
type: 'constant',
|
||||
values: ['beans', 'defbuck'],
|
||||
},
|
||||
createdAt: '2020-05-19T06:00:00.113169-07:00',
|
||||
updatedAt: '2020-05-19T06:00:00.113169-07:00',
|
||||
labels: [],
|
||||
links: {
|
||||
self: '/api/v2/variables/05b740973c68e000',
|
||||
labels: '/api/v2/variables/05b740973c68e000/labels',
|
||||
org: '/api/v2/orgs/05b740945a91b000',
|
||||
},
|
||||
status: RemoteDataState.Done,
|
||||
},
|
||||
values: null,
|
||||
parents: [null],
|
||||
children: [],
|
||||
status: RemoteDataState.Done,
|
||||
cancel: () => {},
|
||||
},
|
||||
{
|
||||
variable: {
|
||||
orgID: '',
|
||||
id: 'timeRangeStop',
|
||||
name: 'timeRangeStop',
|
||||
arguments: {
|
||||
type: 'system',
|
||||
values: ['now()'],
|
||||
},
|
||||
status: RemoteDataState.Done,
|
||||
labels: [],
|
||||
selected: [],
|
||||
},
|
||||
values: null,
|
||||
parents: [null],
|
||||
children: [],
|
||||
status: RemoteDataState.Done,
|
||||
cancel: () => {},
|
||||
},
|
||||
],
|
||||
status: RemoteDataState.NotStarted,
|
||||
cancel: () => {},
|
||||
},
|
||||
],
|
||||
children: [],
|
||||
status: RemoteDataState.Done,
|
||||
cancel: () => {},
|
||||
},
|
||||
{
|
||||
variable: {
|
||||
orgID: '',
|
||||
id: 'timeRangeStop',
|
||||
name: 'timeRangeStop',
|
||||
arguments: {
|
||||
type: 'system',
|
||||
values: ['now()'],
|
||||
},
|
||||
status: RemoteDataState.Done,
|
||||
labels: [],
|
||||
selected: [],
|
||||
},
|
||||
values: null,
|
||||
parents: [
|
||||
{
|
||||
variable: {
|
||||
id: '05b740974228e000',
|
||||
orgID: '05b740945a91b000',
|
||||
name: 'dependent',
|
||||
description: '',
|
||||
selected: [],
|
||||
arguments: {
|
||||
type: 'query',
|
||||
values: {
|
||||
query:
|
||||
'from(bucket: v.static)\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r["_measurement"] == "test")\n |> keep(columns: ["container_name"])\n |> rename(columns: {"container_name": "_value"})\n |> last()\n |> group()',
|
||||
language: 'flux',
|
||||
results: [],
|
||||
},
|
||||
},
|
||||
createdAt: '2020-05-19T06:00:00.136597-07:00',
|
||||
updatedAt: '2020-05-19T06:00:00.136597-07:00',
|
||||
labels: [],
|
||||
links: {
|
||||
self: '/api/v2/variables/05b740974228e000',
|
||||
labels: '/api/v2/variables/05b740974228e000/labels',
|
||||
org: '/api/v2/orgs/05b740945a91b000',
|
||||
},
|
||||
status: RemoteDataState.Loading,
|
||||
},
|
||||
values: null,
|
||||
parents: [],
|
||||
children: [
|
||||
{
|
||||
variable: {
|
||||
id: '05b740973c68e000',
|
||||
orgID: '05b740945a91b000',
|
||||
name: 'static',
|
||||
description: '',
|
||||
selected: ['defbuck'],
|
||||
arguments: {
|
||||
type: 'constant',
|
||||
values: ['beans', 'defbuck'],
|
||||
},
|
||||
createdAt: '2020-05-19T06:00:00.113169-07:00',
|
||||
updatedAt: '2020-05-19T06:00:00.113169-07:00',
|
||||
labels: [],
|
||||
links: {
|
||||
self: '/api/v2/variables/05b740973c68e000',
|
||||
labels: '/api/v2/variables/05b740973c68e000/labels',
|
||||
org: '/api/v2/orgs/05b740945a91b000',
|
||||
},
|
||||
status: RemoteDataState.Done,
|
||||
},
|
||||
values: null,
|
||||
parents: [null],
|
||||
children: [],
|
||||
status: RemoteDataState.Done,
|
||||
cancel: () => {},
|
||||
},
|
||||
{
|
||||
variable: {
|
||||
orgID: '',
|
||||
id: 'timeRangeStart',
|
||||
name: 'timeRangeStart',
|
||||
arguments: {
|
||||
type: 'system',
|
||||
values: [
|
||||
[
|
||||
{
|
||||
magnitude: 1,
|
||||
unit: 'h',
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
status: RemoteDataState.Done,
|
||||
labels: [],
|
||||
selected: [],
|
||||
},
|
||||
values: null,
|
||||
parents: [null],
|
||||
children: [],
|
||||
status: RemoteDataState.Done,
|
||||
cancel: () => {},
|
||||
},
|
||||
null,
|
||||
],
|
||||
status: RemoteDataState.NotStarted,
|
||||
cancel: () => {},
|
||||
},
|
||||
],
|
||||
children: [],
|
||||
status: RemoteDataState.Done,
|
||||
cancel: () => {},
|
||||
},
|
||||
{
|
||||
variable: {
|
||||
orgID: '',
|
||||
id: 'windowPeriod',
|
||||
name: 'windowPeriod',
|
||||
arguments: {
|
||||
type: 'system',
|
||||
values: [10000],
|
||||
},
|
||||
status: RemoteDataState.Done,
|
||||
labels: [],
|
||||
selected: [],
|
||||
},
|
||||
values: null,
|
||||
parents: [],
|
||||
children: [],
|
||||
status: RemoteDataState.Done,
|
||||
cancel: () => {},
|
||||
},
|
||||
]
|
||||
|
||||
export const defaultVariable: Variable = {
|
||||
id: '05b73f4bffe8e000',
|
||||
orgID: '05b73f49a1d1b000',
|
||||
name: 'static',
|
||||
description: '',
|
||||
selected: ['defbuck'],
|
||||
arguments: {type: 'constant', values: ['beans', 'defbuck']},
|
||||
createdAt: '2020-05-19T05:54:20.927477-07:00',
|
||||
updatedAt: '2020-05-19T05:54:20.927477-07:00',
|
||||
labels: [],
|
||||
links: {
|
||||
self: '/api/v2/variables/05b73f4bffe8e000',
|
||||
labels: '/api/v2/variables/05b73f4bffe8e000/labels',
|
||||
org: '/api/v2/orgs/05b73f49a1d1b000',
|
||||
},
|
||||
status: RemoteDataState.Done,
|
||||
}
|
||||
|
||||
export const associatedVariable: Variable = {
|
||||
id: '05b740974228e000',
|
||||
orgID: '05b740945a91b000',
|
||||
name: 'dependent',
|
||||
description: '',
|
||||
selected: [],
|
||||
arguments: {
|
||||
type: 'query',
|
||||
values: {
|
||||
query:
|
||||
'from(bucket: v.static)\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r["_measurement"] == "test")\n |> keep(columns: ["container_name"])\n |> rename(columns: {"container_name": "_value"})\n |> last()\n |> group()',
|
||||
language: 'flux',
|
||||
results: [],
|
||||
},
|
||||
},
|
||||
createdAt: '2020-05-19T06:00:00.136597-07:00',
|
||||
updatedAt: '2020-05-19T06:00:00.136597-07:00',
|
||||
labels: [],
|
||||
links: {
|
||||
self: '/api/v2/variables/05b740974228e000',
|
||||
labels: '/api/v2/variables/05b740974228e000/labels',
|
||||
org: '/api/v2/orgs/05b740945a91b000',
|
||||
},
|
||||
status: RemoteDataState.Loading,
|
||||
}
|
||||
|
||||
export const timeRangeStartVariable: Variable = {
|
||||
orgID: '',
|
||||
id: 'timeRangeStart',
|
||||
name: 'timeRangeStart',
|
||||
arguments: {
|
||||
type: 'system',
|
||||
values: [
|
||||
[
|
||||
{
|
||||
magnitude: 1,
|
||||
unit: 'h',
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
status: RemoteDataState.Done,
|
||||
labels: [],
|
||||
selected: [],
|
||||
}
|
||||
|
||||
export const defaultVariables: Variable[] = [
|
||||
defaultVariable,
|
||||
associatedVariable,
|
||||
timeRangeStartVariable,
|
||||
{
|
||||
orgID: '',
|
||||
id: 'timeRangeStop',
|
||||
name: 'timeRangeStop',
|
||||
arguments: {
|
||||
type: 'system',
|
||||
values: ['now()'],
|
||||
},
|
||||
status: RemoteDataState.Done,
|
||||
labels: [],
|
||||
selected: [],
|
||||
},
|
||||
{
|
||||
orgID: '',
|
||||
id: 'windowPeriod',
|
||||
name: 'windowPeriod',
|
||||
arguments: {
|
||||
type: 'system',
|
||||
values: [10000],
|
||||
},
|
||||
status: RemoteDataState.Done,
|
||||
labels: [],
|
||||
selected: [],
|
||||
},
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,9 +1,19 @@
|
|||
// Utils
|
||||
import {ValueFetcher} from 'src/variables/utils/ValueFetcher'
|
||||
import {hydrateVars} from 'src/variables/utils/hydrateVars'
|
||||
import {
|
||||
hydrateVars,
|
||||
createVariableGraph,
|
||||
findSubgraph,
|
||||
} from 'src/variables/utils/hydrateVars'
|
||||
|
||||
// Mocks
|
||||
import {createVariable} from 'src/variables/mocks'
|
||||
import {
|
||||
createVariable,
|
||||
associatedVariable,
|
||||
defaultVariable,
|
||||
defaultVariables,
|
||||
timeRangeStartVariable,
|
||||
} from 'src/variables/mocks'
|
||||
|
||||
// Types
|
||||
import {Variable, CancellationError, RemoteDataState} from 'src/types'
|
||||
|
|
@ -109,21 +119,18 @@ describe('hydrate vars', () => {
|
|||
// f [fontcolor = "green"]
|
||||
// g [fontcolor = "green"]
|
||||
// }
|
||||
//
|
||||
// NOTE: these return falsy and not an empty array, because they are skipped
|
||||
// within hydrateVars as not belonging to the graph
|
||||
expect(
|
||||
actual.filter(v => v.id === 'a')[0].arguments.values.results
|
||||
).toBeFalsy()
|
||||
).toEqual([])
|
||||
expect(
|
||||
actual.filter(v => v.id === 'b')[0].arguments.values.results
|
||||
).toBeFalsy()
|
||||
).toEqual([])
|
||||
expect(
|
||||
actual.filter(v => v.id === 'c')[0].arguments.values.results
|
||||
).toBeFalsy()
|
||||
).toEqual([])
|
||||
expect(
|
||||
actual.filter(v => v.id === 'd')[0].arguments.values.results
|
||||
).toBeFalsy()
|
||||
).toEqual([])
|
||||
|
||||
expect(
|
||||
actual.filter(v => v.id === 'e')[0].arguments.values.results
|
||||
|
|
@ -241,11 +248,9 @@ describe('hydrate vars', () => {
|
|||
actual.filter(v => v.id === 'a')[0].arguments.values.results
|
||||
).toEqual(['aVal'])
|
||||
expect(actual.filter(v => v.id === 'a')[0].selected).toEqual(['aVal'])
|
||||
|
||||
expect(actual.filter(v => v.id === 'b')[0].arguments.values).toEqual({
|
||||
k: 'v',
|
||||
})
|
||||
expect(actual.filter(v => v.id === 'b')[0].selected).toEqual(['k'])
|
||||
})
|
||||
|
||||
// This ensures that the update of a dependant variable updates the
|
||||
|
|
@ -319,3 +324,38 @@ describe('hydrate vars', () => {
|
|||
cancel()
|
||||
})
|
||||
})
|
||||
|
||||
describe('findSubgraph', () => {
|
||||
test('should return the update variable with all associated parents', async () => {
|
||||
const variableGraph = await createVariableGraph(defaultVariables)
|
||||
const actual = await findSubgraph(variableGraph, [defaultVariable])
|
||||
// returns the single subgraph result
|
||||
expect(actual.length).toEqual(1)
|
||||
const [subgraph] = actual
|
||||
// expect the subgraph to return the passed in variable
|
||||
expect(subgraph.variable).toEqual(defaultVariable)
|
||||
// expect the parent to be returned with the returning variable
|
||||
expect(subgraph.parents[0].variable).toEqual(associatedVariable)
|
||||
})
|
||||
test('should return the variable with no parents when no association exists', async () => {
|
||||
const a = createVariable('a', 'f(x: v.b)')
|
||||
const variableGraph = await createVariableGraph([...defaultVariables, a])
|
||||
const actual = await findSubgraph(variableGraph, [a])
|
||||
expect(actual.length).toEqual(1)
|
||||
const [subgraph] = actual
|
||||
// expect the subgraph to return the passed in variable
|
||||
expect(subgraph.variable).toEqual(a)
|
||||
// expect the parent to be returned with the returning variable
|
||||
expect(subgraph.parents).toEqual([])
|
||||
})
|
||||
test('should return the update default (timeRange) variable with associated parents', async () => {
|
||||
const variableGraph = await createVariableGraph(defaultVariables)
|
||||
const actual = await findSubgraph(variableGraph, [timeRangeStartVariable])
|
||||
expect(actual.length).toEqual(1)
|
||||
const [subgraph] = actual
|
||||
// expect the subgraph to return the passed in variable
|
||||
expect(subgraph.variable).toEqual(timeRangeStartVariable)
|
||||
// expect the parent to be returned with the returning variable
|
||||
expect(subgraph.parents[0].variable).toEqual(associatedVariable)
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -121,14 +121,15 @@ const collectAncestors = (
|
|||
- The node for one of the passed variables depends on this node
|
||||
|
||||
*/
|
||||
const findSubgraph = (
|
||||
export const findSubgraph = (
|
||||
graph: VariableNode[],
|
||||
variables: Variable[]
|
||||
): VariableNode[] => {
|
||||
const subgraph: Set<VariableNode> = new Set()
|
||||
|
||||
// use an ID array to reduce the chance of reference errors
|
||||
const varIDs = variables.map(v => v.id)
|
||||
// create an array of IDs to reference later
|
||||
const graphIDs = []
|
||||
for (const node of graph) {
|
||||
const shouldKeep =
|
||||
varIDs.includes(node.variable.id) ||
|
||||
|
|
@ -138,12 +139,18 @@ const findSubgraph = (
|
|||
|
||||
if (shouldKeep) {
|
||||
subgraph.add(node)
|
||||
graphIDs.push(node.variable.id)
|
||||
}
|
||||
}
|
||||
|
||||
const removeDupAncestors = (n: VariableNode) => {
|
||||
const {id} = n.variable
|
||||
return !graphIDs.includes(id)
|
||||
}
|
||||
|
||||
for (const node of subgraph) {
|
||||
node.parents = node.parents.filter(node => subgraph.has(node))
|
||||
node.children = node.children.filter(node => subgraph.has(node))
|
||||
node.parents = node.parents.filter(removeDupAncestors)
|
||||
node.children = node.children.filter(removeDupAncestors)
|
||||
}
|
||||
|
||||
return [...subgraph]
|
||||
|
|
@ -223,7 +230,6 @@ const hydrateVarsHelper = async (
|
|||
if (node.status !== RemoteDataState.Loading) {
|
||||
node.status = RemoteDataState.Loading
|
||||
on.fire('status', node.variable, node.status)
|
||||
|
||||
collectAncestors(node)
|
||||
.filter(parent => parent.variable.arguments.type === 'query')
|
||||
.forEach(parent => {
|
||||
|
|
@ -487,9 +493,7 @@ export const hydrateVars = (
|
|||
// from the main execution thread, allowing external services to
|
||||
// register listeners for the loading state changes
|
||||
Promise.resolve()
|
||||
.then(() => {
|
||||
return Promise.all(findLeaves(graph).map(resolve))
|
||||
})
|
||||
.then(() => Promise.all(findLeaves(graph).map(resolve)))
|
||||
.then(() => {
|
||||
deferred.resolve(extractResult(graph))
|
||||
})
|
||||
|
|
|
|||
Loading…
Reference in New Issue