Support custom sources in TimeSeries component
parent
cb48fda0c3
commit
2b38b550af
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
|
||||||
|
|
|
@ -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, {}, {}>(
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
Loading…
Reference in New Issue