Add timeRangeStart variable to queries as preamble

pull/10616/head
Brandon Farmer 2019-01-03 16:33:34 -08:00
parent 3660cfc34a
commit e7c33d5c8e
7 changed files with 69 additions and 20 deletions

View File

@ -1,3 +1,5 @@
import _ from 'lodash'
import Deferred from 'src/utils/Deferred'
import {InfluxLanguage} from 'src/types/v2/dashboards'
@ -19,8 +21,21 @@ interface XHRError extends Error {
export const executeQuery = async (
url: string,
query: string,
language: InfluxLanguage = InfluxLanguage.Flux
language: InfluxLanguage = InfluxLanguage.Flux,
variables?: {[key: string]: string}
): Promise<ExecuteFluxQueryResult> => {
let preamble = ''
if (variables && language === InfluxLanguage.Flux) {
preamble = _.reduce(
variables,
(result, value, name) => `${result}${name} = ${value}\n`,
''
)
}
query = `${preamble}${query}`
// We're using `XMLHttpRequest` directly here rather than through `axios` so
// that we can poll the response size as it comes back. If the response size
// is greater than a predefined limit, we close the HTTP connection and
@ -133,10 +148,11 @@ export const executeQuery = async (
}
export const executeQueries = async (
queries: URLQuery[]
queries: URLQuery[],
variables?: {[key: string]: string}
): Promise<ExecuteFluxQueryResult[]> => {
const promise = Promise.all(
queries.map(({url, text, type}) => executeQuery(url, text, type))
queries.map(({url, text, type}) => executeQuery(url, text, type, variables))
)
return promise

View File

@ -0,0 +1,15 @@
const Conditional = ({
isRendered,
children,
}: {
isRendered: boolean
children: JSX.Element
}): JSX.Element => {
if (isRendered) {
return children
}
return null
}
export default Conditional

View File

@ -9,6 +9,7 @@ import QueryViewSwitcher from 'src/shared/components/QueryViewSwitcher'
// Utils
import {GlobalAutoRefresher} from 'src/utils/AutoRefresher'
import {timeRangeVariables} from 'src/shared/utils/queryBuilder'
// Types
import {TimeRange} from 'src/types'
@ -65,6 +66,7 @@ class RefreshingView extends PureComponent<Props, State> {
submitToken={submitToken}
queries={this.queries}
key={manualRefresh}
variables={{...timeRangeVariables(timeRange)}}
>
{({tables, loading, error, isInitialFetch}) => {
return (

View File

@ -15,9 +15,10 @@ const INITIAL_RESIZER_HANDLE = 0.6
// Utils
import {getActiveTimeMachine} from 'src/shared/selectors/timeMachines'
import {timeRangeVariables} from 'src/shared/utils/queryBuilder'
// Types
import {AppState, DashboardQuery} from 'src/types/v2'
import {AppState, DashboardQuery, TimeRange} from 'src/types/v2'
// Styles
import './TimeMachine.scss'
@ -25,6 +26,7 @@ import './TimeMachine.scss'
interface StateProps {
queries: DashboardQuery[]
submitToken: number
timeRange: TimeRange
}
interface State {
@ -43,7 +45,7 @@ class TimeMachine extends Component<Props, State> {
}
public render() {
const {queries, submitToken} = this.props
const {queries, submitToken, timeRange} = this.props
const {resizerHandlePosition} = this.state
return (
@ -52,6 +54,7 @@ class TimeMachine extends Component<Props, State> {
queries={queries}
submitToken={submitToken}
implicitSubmit={false}
variables={{...timeRangeVariables(timeRange)}}
>
{queriesState => (
<DraggableResizer
@ -82,10 +85,11 @@ class TimeMachine extends Component<Props, State> {
const mstp = (state: AppState) => {
const timeMachine = getActiveTimeMachine(state)
const {timeRange} = timeMachine
const queries = get(timeMachine, 'view.properties.queries', [])
const submitToken = timeMachine.submitToken
return {queries, submitToken}
return {queries, submitToken, timeRange}
}
export default connect<StateProps, {}, {}>(

View File

@ -33,6 +33,7 @@ interface StateProps {
interface OwnProps {
queries: DashboardQuery[]
variables?: {[key: string]: string}
submitToken: number
implicitSubmit?: boolean
inView?: boolean
@ -121,7 +122,7 @@ class TimeSeries extends Component<Props, State> {
})
try {
const results = await this.executeQueries(queries)
const results = await this.executeQueries(queries, this.props.variables)
const tables = flatten(results.map(r => parseResponse(r.csv)))
const files = results.map(r => r.csv)

View File

@ -8,6 +8,7 @@ import CellHeader from 'src/shared/components/cells/CellHeader'
import CellContext from 'src/shared/components/cells/CellContext'
import ViewComponent from 'src/shared/components/cells/View'
import {ErrorHandling} from 'src/shared/decorators/errors'
import Conditional from 'src/shared/components/Conditional'
// Actions
import {readView} from 'src/dashboards/actions/v2/views'
@ -111,19 +112,17 @@ class CellComponent extends Component<Props> {
onEditCell,
} = this.props
if (viewStatus !== RemoteDataState.Done) {
return null
}
return (
<ViewComponent
view={view}
onZoom={onZoom}
timeRange={timeRange}
autoRefresh={autoRefresh}
manualRefresh={manualRefresh}
onEditCell={onEditCell}
/>
<Conditional isRendered={viewStatus !== RemoteDataState.Done}>
<ViewComponent
view={view}
onZoom={onZoom}
timeRange={timeRange}
autoRefresh={autoRefresh}
manualRefresh={manualRefresh}
onEditCell={onEditCell}
/>
</Conditional>
)
}

View File

@ -1,4 +1,4 @@
import {BuilderConfig} from 'src/types/v2'
import {BuilderConfig, TimeRange} from 'src/types/v2'
import {FUNCTIONS} from 'src/shared/constants/queryBuilder'
const DEFAULT_WINDOW_INTERVAL = '10s'
@ -15,6 +15,18 @@ const WINDOW_INTERVALS = {
'30d': '6h',
}
export const timeRangeVariables = (
timeRange: TimeRange
): {[key: string]: string} => {
const result: {[key: string]: string} = {}
result.timeRangeStart = timeRange.lower
.replace('now()', '')
.replace(/\s/g, '')
return result
}
export function isConfigValid(builderConfig: BuilderConfig): boolean {
const {buckets, measurements} = builderConfig
const isConfigValid = buckets.length >= 1 && measurements.length >= 1