Hoist TimeSeries component to root of TimeMachine

This enables us to use the data provided by the `TimeSeries` component
outside of the `TimeMachine` visualization without breaking one-way data
flow.
pull/10616/head
Christopher Henn 2018-11-15 14:58:52 -08:00 committed by Chris Henn
parent 3c6445cbaf
commit 1b9fd1bcda
6 changed files with 133 additions and 65 deletions

View File

@ -1,17 +1,32 @@
// Libraries
import React, {PureComponent} from 'react'
// Components
import EmptyGraphMessage from 'src/shared/components/EmptyGraphMessage'
// Constants
import {emptyGraphCopy} from 'src/shared/copy/cell'
// Types
import {RemoteDataState, FluxTable} from 'src/types'
import {DashboardQuery} from 'src/types/v2'
interface Props {
error: Error
isInitialFetch: boolean
loading: RemoteDataState
tables: FluxTable[]
queries: DashboardQuery[]
}
export default class EmptyRefreshingView extends PureComponent<Props> {
public render() {
const {error, isInitialFetch, loading, tables} = this.props
const {error, isInitialFetch, loading, tables, queries} = this.props
if (!queries.length) {
return <EmptyGraphMessage message={emptyGraphCopy} />
}
if (error) {
return <EmptyGraphMessage message={`Error: ${error.message}`} />
}

View File

@ -5,13 +5,9 @@ import _ from 'lodash'
// Components
import TimeSeries from 'src/shared/components/TimeSeries'
import EmptyGraphMessage from 'src/shared/components/EmptyGraphMessage'
import EmptyRefreshingView from 'src/shared/components/EmptyRefreshingView'
import RefreshingViewSwitcher from 'src/shared/components/RefreshingViewSwitcher'
// Constants
import {emptyGraphCopy} from 'src/shared/copy/cell'
// Utils
import {getActiveSource} from 'src/sources/selectors'
@ -55,10 +51,6 @@ class RefreshingView extends PureComponent<Props> {
manualRefresh,
} = this.props
if (!properties.queries.length) {
return <EmptyGraphMessage message={emptyGraphCopy} />
}
return (
<TimeSeries
link={link}
@ -73,6 +65,7 @@ class RefreshingView extends PureComponent<Props> {
tables={tables}
loading={loading}
isInitialFetch={isInitialFetch}
queries={this.queries}
>
<RefreshingViewSwitcher
tables={tables}

View File

@ -24,11 +24,15 @@ interface Props {
tables: FluxTable[]
loading: RemoteDataState
timeRange: TimeRange
onZoom: (range: TimeRange) => void
onZoom?: (range: TimeRange) => void
properties: RefreshingViewProperties
}
export default class RefreshingViewSwitcher extends PureComponent<Props> {
public static defaultProps: Partial<Props> = {
onZoom: () => {},
}
public render() {
const {properties, loading, viewID, tables, onZoom, timeRange} = this.props

View File

@ -1,56 +1,93 @@
// Libraries
import React, {PureComponent} from 'react'
import {connect} from 'react-redux'
import {get} from 'lodash'
// Components
import TimeMachineControls from 'src/shared/components/TimeMachineControls'
import Threesizer from 'src/shared/components/threesizer/Threesizer'
import TimeMachineBottom from 'src/shared/components/TimeMachineBottom'
import TimeMachineVis from 'src/shared/components/TimeMachineVis'
import TimeSeries from 'src/shared/components/TimeSeries'
// Utils
import {getActiveSource} from 'src/sources/selectors'
// Constants
import {HANDLE_HORIZONTAL} from 'src/shared/constants'
// Types
import {TimeMachineTab} from 'src/types/v2/timeMachine'
import {AppState, DashboardQuery} from 'src/types/v2'
interface Props {
interface StateProps {
queryLink: string
queries: DashboardQuery[]
}
interface OwnProps {
activeTab: TimeMachineTab
}
type Props = OwnProps & StateProps
class TimeMachine extends PureComponent<Props> {
public render() {
const {activeTab} = this.props
const divisions = [
{
name: '',
handleDisplay: 'none',
headerButtons: [],
menuOptions: [],
render: () => <TimeMachineVis />,
headerOrientation: HANDLE_HORIZONTAL,
size: 0.33,
},
{
name: '',
handlePixels: 8,
headerButtons: [],
menuOptions: [],
render: () => <TimeMachineBottom activeTab={activeTab} />,
headerOrientation: HANDLE_HORIZONTAL,
size: 0.67,
},
]
const {activeTab, queryLink, queries} = this.props
return (
<div className="time-machine">
<TimeMachineControls />
<div className="time-machine-container">
<Threesizer orientation={HANDLE_HORIZONTAL} divisions={divisions} />
</div>
<TimeSeries link={queryLink} queries={queries}>
{queriesState => {
const divisions = [
{
name: '',
handleDisplay: 'none',
headerButtons: [],
menuOptions: [],
render: () => <TimeMachineVis queriesState={queriesState} />,
headerOrientation: HANDLE_HORIZONTAL,
size: 0.33,
},
{
name: '',
handlePixels: 8,
headerButtons: [],
menuOptions: [],
render: () => <TimeMachineBottom activeTab={activeTab} />,
headerOrientation: HANDLE_HORIZONTAL,
size: 0.67,
},
]
return (
<>
<TimeMachineControls />
<div className="time-machine-container">
<Threesizer
orientation={HANDLE_HORIZONTAL}
divisions={divisions}
/>
</div>
</>
)
}}
</TimeSeries>
</div>
)
}
}
export default TimeMachine
const mstp = (state: AppState) => {
const {activeTimeMachineID, timeMachines} = state.timeMachines
const timeMachine = timeMachines[activeTimeMachineID]
const queries = get(timeMachine, 'view.properties.queries', [])
const queryLink = getActiveSource(state).links.query
return {queryLink, queries}
}
export default connect<StateProps, {}, OwnProps>(
mstp,
null
)(TimeMachine)

View File

@ -1,46 +1,59 @@
// Libraries
import React, {SFC} from 'react'
import {connect} from 'react-redux'
import {get} from 'lodash'
// Components
import ViewComponent from 'src/shared/components/cells/View'
import EmptyRefreshingView from 'src/shared/components/EmptyRefreshingView'
import RefreshingViewSwitcher from 'src/shared/components/RefreshingViewSwitcher'
// Actions
import {setType} from 'src/shared/actions/v2/timeMachines'
// Types
import {AppState} from 'src/types/v2'
import {View, NewView, TimeRange} from 'src/types/v2'
import {View, NewView, TimeRange, DashboardQuery, AppState} from 'src/types/v2'
import {RefreshingViewProperties} from 'src/types/v2/dashboards'
import {QueriesState} from 'src/shared/components/TimeSeries'
interface StateProps {
view: View | NewView
timeRange: TimeRange
queries: DashboardQuery[]
}
interface DispatchProps {
onUpdateType: typeof setType
}
interface OwnProps {}
interface OwnProps {
queriesState: QueriesState
}
type Props = StateProps & DispatchProps & OwnProps
const TimeMachineVis: SFC<Props> = props => {
const {view, timeRange} = props
const noop = () => {}
const {view, timeRange, queries} = props
const {tables, loading, error, isInitialFetch} = props.queriesState
return (
<div className="time-machine-top">
<div className="time-machine-vis">
<div className="graph-container">
<ViewComponent
view={view as View}
onZoom={noop}
timeRange={timeRange}
autoRefresh={0}
manualRefresh={0}
onEditCell={noop}
/>
<EmptyRefreshingView
error={error}
tables={tables}
loading={loading}
isInitialFetch={isInitialFetch}
queries={queries}
>
<RefreshingViewSwitcher
tables={tables}
viewID="time-machine-view"
loading={loading}
timeRange={timeRange}
properties={view.properties as RefreshingViewProperties}
/>
</EmptyRefreshingView>
</div>
</div>
</div>
@ -50,10 +63,12 @@ const TimeMachineVis: SFC<Props> = props => {
const mstp = (state: AppState) => {
const {activeTimeMachineID, timeMachines} = state.timeMachines
const timeMachine = timeMachines[activeTimeMachineID]
const queries = get(timeMachine, 'view.properties.queries', [])
return {
view: timeMachine.view,
timeRange: timeMachine.timeRange,
queries,
}
}

View File

@ -16,7 +16,7 @@ import {restartable, CancellationError} from 'src/utils/restartable'
export const DEFAULT_TIME_SERIES = [{response: {results: []}}]
interface RenderProps {
export interface QueriesState {
tables: FluxTable[]
loading: RemoteDataState
error: Error | null
@ -27,7 +27,7 @@ interface Props {
link: string
queries: DashboardQuery[]
inView?: boolean
children: (r: RenderProps) => JSX.Element
children: (r: QueriesState) => JSX.Element
}
interface State {
@ -37,24 +37,22 @@ interface State {
fetchCount: number
}
const defaultState = (): State => ({
loading: RemoteDataState.NotStarted,
tables: [],
fetchCount: 0,
error: null,
})
class TimeSeries extends Component<Props, State> {
public static defaultProps = {
inView: true,
}
public state: State = defaultState()
private executeQueries = restartable(executeQueries)
constructor(props: Props) {
super(props)
this.state = {
loading: RemoteDataState.NotStarted,
tables: [],
fetchCount: 0,
error: null,
}
}
public async componentDidMount() {
this.reload()
@ -89,6 +87,12 @@ class TimeSeries extends Component<Props, State> {
return
}
if (!queries.length) {
this.setState(defaultState())
return
}
this.setState({
loading: RemoteDataState.Loading,
fetchCount: this.state.fetchCount + 1,