Support custom sources in TimeSeries component

pull/10616/head
Christopher Henn 2018-11-26 15:10:07 -08:00 committed by Chris Henn
parent cb48fda0c3
commit 2b38b550af
6 changed files with 66 additions and 48 deletions

View File

@ -1,7 +1,7 @@
import Deferred from 'src/utils/Deferred' import Deferred from 'src/utils/Deferred'
import {InfluxLanguage} from 'src/types/v2/dashboards' import {InfluxLanguage} from 'src/types/v2/dashboards'
import {DashboardQuery} from 'src/types/v2/dashboards' import {URLQuery} from 'src/types/v2/dashboards'
const CHECK_LIMIT_INTERVAL = 200 const CHECK_LIMIT_INTERVAL = 200
const MAX_ROWS = 50000 const MAX_ROWS = 50000
@ -133,10 +133,11 @@ export const executeQuery = async (
} }
export const executeQueries = async ( export const executeQueries = async (
url: string, queries: URLQuery[]
queries: DashboardQuery[]
): Promise<ExecuteFluxQueryResult[]> => { ): Promise<ExecuteFluxQueryResult[]> => {
return Promise.all( const promise = Promise.all(
queries.map(({type, text}) => executeQuery(url, text, type)) queries.map(({url, text, type}) => executeQuery(url, text, type))
) )
return promise
} }

View File

@ -1,6 +1,5 @@
// Libraries // Libraries
import React, {PureComponent} from 'react' import React, {PureComponent} from 'react'
import {connect} from 'react-redux'
import _ from 'lodash' import _ from 'lodash'
// Components // Components
@ -9,16 +8,14 @@ import EmptyRefreshingView from 'src/shared/components/EmptyRefreshingView'
import RefreshingViewSwitcher from 'src/shared/components/RefreshingViewSwitcher' import RefreshingViewSwitcher from 'src/shared/components/RefreshingViewSwitcher'
// Utils // Utils
import {getActiveSource} from 'src/sources/selectors'
import {GlobalAutoRefresher} from 'src/utils/AutoRefresher' import {GlobalAutoRefresher} from 'src/utils/AutoRefresher'
// Types // Types
import {TimeRange} from 'src/types' import {TimeRange} from 'src/types'
import {AppState} from 'src/types/v2'
import {DashboardQuery} from 'src/types/v2/dashboards' import {DashboardQuery} from 'src/types/v2/dashboards'
import {RefreshingViewProperties, ViewType} from 'src/types/v2/dashboards' import {RefreshingViewProperties, ViewType} from 'src/types/v2/dashboards'
interface OwnProps { interface Props {
timeRange: TimeRange timeRange: TimeRange
viewID: string viewID: string
inView: boolean inView: boolean
@ -27,14 +24,6 @@ interface OwnProps {
properties: RefreshingViewProperties properties: RefreshingViewProperties
} }
interface StateProps {
link: string
}
interface DispatchProps {}
type Props = OwnProps & StateProps & DispatchProps
class RefreshingView extends PureComponent<Props> { class RefreshingView extends PureComponent<Props> {
public static defaultProps: Partial<Props> = { public static defaultProps: Partial<Props> = {
inView: true, inView: true,
@ -43,7 +32,6 @@ class RefreshingView extends PureComponent<Props> {
public render() { public render() {
const { const {
link,
inView, inView,
onZoom, onZoom,
viewID, viewID,
@ -54,7 +42,6 @@ class RefreshingView extends PureComponent<Props> {
return ( return (
<TimeSeries <TimeSeries
link={link}
inView={inView} inView={inView}
autoRefresher={GlobalAutoRefresher} autoRefresher={GlobalAutoRefresher}
queries={this.queries} queries={this.queries}
@ -100,15 +87,4 @@ class RefreshingView extends PureComponent<Props> {
} }
} }
const mstp = (state: AppState): StateProps => { export default RefreshingView
const link = getActiveSource(state).links.query
return {link}
}
const mdtp = {}
export default connect<StateProps, DispatchProps, OwnProps>(
mstp,
mdtp
)(RefreshingView)

View File

@ -13,7 +13,6 @@ import TimeMachineVis from 'src/shared/components/TimeMachineVis'
import TimeSeries from 'src/shared/components/TimeSeries' import TimeSeries from 'src/shared/components/TimeSeries'
// Utils // Utils
import {getActiveSource} from 'src/sources/selectors'
import {getActiveTimeMachine} from 'src/shared/selectors/timeMachines' import {getActiveTimeMachine} from 'src/shared/selectors/timeMachines'
// Constants // Constants
@ -23,16 +22,15 @@ import {HANDLE_HORIZONTAL} from 'src/shared/constants'
import {AppState, DashboardQuery} from 'src/types/v2' import {AppState, DashboardQuery} from 'src/types/v2'
interface StateProps { interface StateProps {
queryLink: string
queries: DashboardQuery[] queries: DashboardQuery[]
} }
const TimeMachine: SFC<StateProps> = props => { const TimeMachine: SFC<StateProps> = props => {
const {queryLink, queries} = props const {queries} = props
return ( return (
<div className="time-machine"> <div className="time-machine">
<TimeSeries link={queryLink} queries={queries}> <TimeSeries queries={queries}>
{queriesState => { {queriesState => {
const divisions: DivisionProps[] = [ const divisions: DivisionProps[] = [
{ {
@ -71,9 +69,8 @@ const TimeMachine: SFC<StateProps> = props => {
const mstp = (state: AppState) => { const mstp = (state: AppState) => {
const timeMachine = getActiveTimeMachine(state) const timeMachine = getActiveTimeMachine(state)
const queries = get(timeMachine, 'view.properties.queries', []) const queries = get(timeMachine, 'view.properties.queries', [])
const queryLink = getActiveSource(state).links.query
return {queryLink, queries} return {queries}
} }
export default connect<StateProps, {}, {}>( export default connect<StateProps, {}, {}>(

View File

@ -1,18 +1,21 @@
// Library // Library
import {Component} from 'react' import {Component} from 'react'
import {isEqual, flatten} from 'lodash' import {isEqual, flatten} from 'lodash'
import {connect} from 'react-redux'
// API // API
import {executeQueries} from 'src/shared/apis/v2/query' import {executeQueries} from 'src/shared/apis/v2/query'
// Types // Types
import {RemoteDataState, FluxTable} from 'src/types' import {RemoteDataState, FluxTable} from 'src/types'
import {DashboardQuery} from 'src/types/v2/dashboards' import {DashboardQuery, URLQuery} from 'src/types/v2/dashboards'
import {AppState, Source} from 'src/types/v2'
// Utils // Utils
import {AutoRefresher} from 'src/utils/AutoRefresher' import {AutoRefresher} from 'src/utils/AutoRefresher'
import {parseResponse} from 'src/shared/parsing/flux/response' import {parseResponse} from 'src/shared/parsing/flux/response'
import {restartable, CancellationError} from 'src/utils/restartable' import {restartable, CancellationError} from 'src/utils/restartable'
import {getSources, getActiveSource} from 'src/sources/selectors'
export const DEFAULT_TIME_SERIES = [{response: {results: []}}] export const DEFAULT_TIME_SERIES = [{response: {results: []}}]
@ -24,14 +27,20 @@ export interface QueriesState {
isInitialFetch: boolean isInitialFetch: boolean
} }
interface Props { interface StateProps {
link: string dynamicSourceURL: string
sources: Source[]
}
interface OwnProps {
queries: DashboardQuery[] queries: DashboardQuery[]
autoRefresher?: AutoRefresher autoRefresher?: AutoRefresher
inView?: boolean inView?: boolean
children: (r: QueriesState) => JSX.Element children: (r: QueriesState) => JSX.Element
} }
type Props = StateProps & OwnProps
interface State { interface State {
loading: RemoteDataState loading: RemoteDataState
tables: FluxTable[] tables: FluxTable[]
@ -93,8 +102,20 @@ class TimeSeries extends Component<Props, State> {
}) })
} }
private get queries(): URLQuery[] {
const {sources, queries, dynamicSourceURL} = this.props
return queries.filter(query => !!query.text).map(query => {
const source = sources.find(source => source.id === query.source)
const url: string = source ? source.links.query : dynamicSourceURL
return {url, text: query.text, type: query.type}
})
}
private reload = async () => { private reload = async () => {
const {link, inView, queries} = this.props const {inView} = this.props
const queries = this.queries
if (!inView) { if (!inView) {
return return
@ -112,7 +133,7 @@ class TimeSeries extends Component<Props, State> {
}) })
try { try {
const results = await this.executeQueries(link, queries) const results = await this.executeQueries(queries)
const tables = flatten(results.map(r => parseResponse(r.csv))) const tables = flatten(results.map(r => parseResponse(r.csv)))
const files = results.map(r => r.csv) const files = results.map(r => r.csv)
@ -134,11 +155,11 @@ class TimeSeries extends Component<Props, State> {
} }
private shouldReload(prevProps: Props) { private shouldReload(prevProps: Props) {
if (prevProps.link !== this.props.link) { if (!isEqual(prevProps.queries, this.props.queries)) {
return true return true
} }
if (!isEqual(prevProps.queries, this.props.queries)) { if (prevProps.dynamicSourceURL !== this.props.dynamicSourceURL) {
return true return true
} }
@ -146,4 +167,14 @@ class TimeSeries extends Component<Props, State> {
} }
} }
export default TimeSeries const mstp = (state: AppState) => {
const sources = getSources(state)
const dynamicSourceURL = getActiveSource(state).links.query
return {sources, dynamicSourceURL}
}
export default connect<StateProps, {}, OwnProps>(
mstp,
null
)(TimeSeries)

View File

@ -12,6 +12,7 @@ import {
NewView, NewView,
ViewProperties, ViewProperties,
DashboardQuery, DashboardQuery,
InfluxLanguage,
} from 'src/types/v2/dashboards' } from 'src/types/v2/dashboards'
function defaultView() { function defaultView() {
@ -20,8 +21,14 @@ function defaultView() {
} }
} }
function defaultViewQueries() { function defaultViewQueries(): DashboardQuery[] {
return [] return [
{
text: '',
type: InfluxLanguage.Flux,
source: '',
},
]
} }
function defaultLineViewProperties() { function defaultLineViewProperties() {

View File

@ -43,7 +43,13 @@ export enum InfluxLanguage {
export interface DashboardQuery { export interface DashboardQuery {
text: string text: string
type: InfluxLanguage type: InfluxLanguage
source: string source: string // ID of source to use when running the query; may be empty, which means “use the dynamic source”
}
export interface URLQuery {
text: string
type: InfluxLanguage
url: string
} }
export interface Legend { export interface Legend {