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
parent
3c6445cbaf
commit
1b9fd1bcda
|
@ -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}`} />
|
||||
}
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue