Hydrate in use variables before displaying the CEO
parent
69db8099d4
commit
83dd14bdbb
|
@ -1,11 +1,21 @@
|
|||
// Libraries
|
||||
import {get} from 'lodash'
|
||||
|
||||
// Actions
|
||||
import {loadBuckets} from 'src/timeMachine/actions/queryBuilder'
|
||||
import {refreshVariableValues} from 'src/variables/actions'
|
||||
|
||||
// Utils
|
||||
import {getActiveTimeMachine} from 'src/timeMachine/selectors'
|
||||
import {filterUnusedVars} from 'src/shared/utils/filterUnusedVars'
|
||||
import {getVariablesForOrg} from 'src/variables/selectors'
|
||||
import {getActiveOrg} from 'src/organizations/selectors'
|
||||
|
||||
// Types
|
||||
import {Dispatch} from 'redux-thunk'
|
||||
import {TimeMachineState} from 'src/timeMachine/reducers'
|
||||
import {Action as QueryBuilderAction} from 'src/timeMachine/actions/queryBuilder'
|
||||
import {TimeRange, ViewType} from 'src/types/v2'
|
||||
import {TimeRange, ViewType, GetState} from 'src/types/v2'
|
||||
import {
|
||||
Axes,
|
||||
DecimalPlaces,
|
||||
|
@ -541,3 +551,29 @@ export const setXAxisLabel = (xAxisLabel: string): SetXAxisLabelAction => ({
|
|||
type: 'SET_X_AXIS_LABEL',
|
||||
payload: {xAxisLabel},
|
||||
})
|
||||
|
||||
export const refreshTimeMachineVariableValues = () => async (
|
||||
dispatch,
|
||||
getState: GetState
|
||||
) => {
|
||||
const contextID = getState().timeMachines.activeTimeMachineID
|
||||
|
||||
// Find variables currently used by queries in the TimeMachine
|
||||
const view = getActiveTimeMachine(getState()).view
|
||||
const orgID = getActiveOrg(getState()).id
|
||||
const variables = getVariablesForOrg(getState(), orgID)
|
||||
const variablesInUse = filterUnusedVars(variables, [view])
|
||||
|
||||
// Find variables whose values have already been loaded by the TimeMachine
|
||||
// (regardless of whether these variables are currently being used)
|
||||
const existingVariableIDs = Object.keys(
|
||||
get(getState(), `variables.values.${contextID}.values`, {})
|
||||
)
|
||||
|
||||
// Refresh values for all variables with existing values and in use variables
|
||||
const variablesToRefresh = variables.filter(
|
||||
v => variablesInUse.includes(v) || existingVariableIDs.includes(v.id)
|
||||
)
|
||||
|
||||
await dispatch(refreshVariableValues(contextID, orgID, variablesToRefresh))
|
||||
}
|
||||
|
|
|
@ -5,19 +5,26 @@ import {get} from 'lodash'
|
|||
import classnames from 'classnames'
|
||||
|
||||
// Components
|
||||
import {SpinnerContainer, TechnoSpinner} from '@influxdata/clockface'
|
||||
import {DraggableResizer, Stack} from 'src/clockface'
|
||||
import TimeMachineBottom from 'src/timeMachine/components/TimeMachineBottom'
|
||||
import TimeMachineVis from 'src/timeMachine/components/Vis'
|
||||
import TimeSeries from 'src/shared/components/TimeSeries'
|
||||
import ViewOptions from 'src/timeMachine/components/view_options/ViewOptions'
|
||||
|
||||
// Actions
|
||||
import {refreshTimeMachineVariableValues} from 'src/timeMachine/actions'
|
||||
|
||||
// Utils
|
||||
import {getActiveTimeMachine} from 'src/timeMachine/selectors'
|
||||
import {getTimeRangeVars} from 'src/variables/utils/getTimeRangeVars'
|
||||
import {getVariableAssignments} from 'src/variables/selectors'
|
||||
|
||||
// Types
|
||||
import {TimeMachineTab} from 'src/types/v2/timeMachine'
|
||||
import {AppState, DashboardQuery, TimeRange} from 'src/types/v2'
|
||||
import {RemoteDataState} from 'src/types'
|
||||
import {VariableAssignment} from 'src/types/ast'
|
||||
|
||||
// Styles
|
||||
import 'src/timeMachine/components/TimeMachine.scss'
|
||||
|
@ -29,35 +36,54 @@ interface StateProps {
|
|||
submitToken: number
|
||||
timeRange: TimeRange
|
||||
activeTab: TimeMachineTab
|
||||
variableAssignments: VariableAssignment[]
|
||||
}
|
||||
|
||||
interface DispatchProps {
|
||||
onRefreshVariableValues: () => Promise<void>
|
||||
}
|
||||
|
||||
interface State {
|
||||
resizerHandlePosition: number[]
|
||||
initialLoadingStatus: RemoteDataState
|
||||
}
|
||||
|
||||
type Props = StateProps
|
||||
type Props = StateProps & DispatchProps
|
||||
|
||||
class TimeMachine extends Component<Props, State> {
|
||||
constructor(props: Props) {
|
||||
super(props)
|
||||
public state: State = {
|
||||
resizerHandlePosition: [INITIAL_RESIZER_HANDLE],
|
||||
initialLoadingStatus: RemoteDataState.Loading,
|
||||
}
|
||||
|
||||
this.state = {
|
||||
resizerHandlePosition: [INITIAL_RESIZER_HANDLE],
|
||||
public async componentDidMount() {
|
||||
try {
|
||||
await this.props.onRefreshVariableValues()
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
}
|
||||
|
||||
// Even if refreshing the variable values fails, most of the `TimeMachine`
|
||||
// can continue to function. So we set the status to `Done` whether or not
|
||||
// the refresh is successful
|
||||
this.setState({initialLoadingStatus: RemoteDataState.Done})
|
||||
}
|
||||
|
||||
public render() {
|
||||
const {queries, submitToken, timeRange} = this.props
|
||||
const {resizerHandlePosition} = this.state
|
||||
const {queries, submitToken} = this.props
|
||||
const {resizerHandlePosition, initialLoadingStatus} = this.state
|
||||
|
||||
return (
|
||||
<>
|
||||
<SpinnerContainer
|
||||
loading={initialLoadingStatus}
|
||||
spinnerComponent={<TechnoSpinner />}
|
||||
>
|
||||
<div className={this.containerClassName}>
|
||||
<TimeSeries
|
||||
queries={queries}
|
||||
submitToken={submitToken}
|
||||
implicitSubmit={false}
|
||||
variables={getTimeRangeVars(timeRange)}
|
||||
variables={this.variableAssignments}
|
||||
>
|
||||
{queriesState => (
|
||||
<DraggableResizer
|
||||
|
@ -78,7 +104,7 @@ class TimeMachine extends Component<Props, State> {
|
|||
</TimeSeries>
|
||||
</div>
|
||||
{this.viewOptions}
|
||||
</>
|
||||
</SpinnerContainer>
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -90,8 +116,10 @@ class TimeMachine extends Component<Props, State> {
|
|||
}
|
||||
}
|
||||
|
||||
private handleResizerChange = (resizerHandlePosition: number[]): void => {
|
||||
this.setState({resizerHandlePosition})
|
||||
private get variableAssignments(): VariableAssignment[] {
|
||||
const {variableAssignments, timeRange} = this.props
|
||||
|
||||
return [...variableAssignments, ...getTimeRangeVars(timeRange)]
|
||||
}
|
||||
|
||||
private get containerClassName(): string {
|
||||
|
@ -101,19 +129,27 @@ class TimeMachine extends Component<Props, State> {
|
|||
'time-machine--split': activeTab === TimeMachineTab.Visualization,
|
||||
})
|
||||
}
|
||||
|
||||
private handleResizerChange = (resizerHandlePosition: number[]): void => {
|
||||
this.setState({resizerHandlePosition})
|
||||
}
|
||||
}
|
||||
|
||||
const mstp = (state: AppState) => {
|
||||
const timeMachine = getActiveTimeMachine(state)
|
||||
const {activeTab} = getActiveTimeMachine(state)
|
||||
const {timeRange} = timeMachine
|
||||
const {activeTab, timeRange, submitToken} = timeMachine
|
||||
const queries = get(timeMachine, 'view.properties.queries', [])
|
||||
const submitToken = timeMachine.submitToken
|
||||
const {activeTimeMachineID} = state.timeMachines
|
||||
const variableAssignments = getVariableAssignments(state, activeTimeMachineID)
|
||||
|
||||
return {queries, submitToken, timeRange, activeTab}
|
||||
return {queries, submitToken, timeRange, activeTab, variableAssignments}
|
||||
}
|
||||
|
||||
export default connect<StateProps, {}, {}>(
|
||||
const mdtp = {
|
||||
onRefreshVariableValues: refreshTimeMachineVariableValues as any,
|
||||
}
|
||||
|
||||
export default connect<StateProps, DispatchProps, {}>(
|
||||
mstp,
|
||||
null
|
||||
mdtp
|
||||
)(TimeMachine)
|
||||
|
|
Loading…
Reference in New Issue