fix(ui): adding times in script editor will default start and endtime for timerange queries (#16201)

fix(ui): adding times in script editor will default start and endtime for timerange queries, compute timeranges based on script and based on widest date range & fix dashboard so that cells that have been saved with timerange scripts are based on those timeranges
pull/15967/head
Ariel Salem 2019-12-12 10:29:09 -08:00 committed by GitHub
parent 48e854776e
commit eefb8dd525
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 109 additions and 81 deletions

View File

@ -25,6 +25,7 @@
1. [16175](https://github.com/influxdata/influxdb/pull/16175): Added delete functionality to note cells so that they can be deleted
1. [16204](https://github.com/influxdata/influxdb/pull/16204): Fix failure to create labels when creating telegraf configs
1. [16207](https://github.com/influxdata/influxdb/pull/16207): Fix crash when editing a Telegraf config
1. [16201](https://github.com/influxdata/influxdb/pull/16201): Updated start/endtime functionality so that custom script timeranges overwrite dropdown selections
### UI Improvements

View File

@ -16,12 +16,16 @@ import {DEFAULT_LINE_COLORS} from 'src/shared/constants/graphColorPalettes'
import {INVALID_DATA_COPY} from 'src/shared/copy/cell'
// Types
import {RemoteDataState, HeatmapViewProperties, TimeZone} from 'src/types'
import {
RemoteDataState,
HeatmapViewProperties,
TimeZone,
TimeRange,
} from 'src/types'
interface Props {
endTime: number
loading: RemoteDataState
startTime: number
timeRange: TimeRange | null
table: Table
timeZone: TimeZone
viewProperties: HeatmapViewProperties
@ -29,9 +33,8 @@ interface Props {
}
const HeatmapPlot: FunctionComponent<Props> = ({
endTime,
loading,
startTime,
timeRange,
table,
timeZone,
viewProperties: {
@ -56,8 +59,7 @@ const HeatmapPlot: FunctionComponent<Props> = ({
const [xDomain, onSetXDomain, onResetXDomain] = useVisDomainSettings(
storedXDomain,
table.getColumn(xColumn, 'number'),
startTime,
endTime
timeRange
)
const [yDomain, onSetYDomain, onResetYDomain] = useVisDomainSettings(

View File

@ -10,13 +10,12 @@ import ViewSwitcher from 'src/shared/components/ViewSwitcher'
// Utils
import {GlobalAutoRefresher} from 'src/utils/AutoRefresher'
import {getTimeRangeVars} from 'src/variables/utils/getTimeRangeVars'
import {getVariableAssignments} from 'src/variables/selectors'
import {getDashboardValuesStatus} from 'src/variables/selectors'
import {
getVariableAssignments,
getDashboardValuesStatus,
} from 'src/variables/selectors'
import {checkResultsLength} from 'src/shared/utils/vis'
// Selectors
import {getEndTime, getStartTime} from 'src/timeMachine/selectors/index'
import {getTimeRangeByDashboardID} from 'src/dashboards/selectors/index'
import {getActiveTimeRange} from 'src/timeMachine/selectors/index'
// Types
import {
@ -39,8 +38,7 @@ interface OwnProps {
}
interface StateProps {
endTime: number
startTime: number
ranges: TimeRange | null
timeZone: TimeZone
variableAssignments: VariableAssignment[]
variablesStatus: RemoteDataState
@ -73,14 +71,7 @@ class RefreshingView extends PureComponent<Props, State> {
}
public render() {
const {
check,
endTime,
properties,
manualRefresh,
startTime,
timeZone,
} = this.props
const {check, ranges, properties, manualRefresh, timeZone} = this.props
const {submitToken} = this.state
return (
@ -111,12 +102,11 @@ class RefreshingView extends PureComponent<Props, State> {
>
<ViewSwitcher
check={check}
endTime={endTime}
files={files}
giraffeResult={giraffeResult}
loading={loading}
properties={properties}
startTime={startTime}
timeRange={ranges}
statuses={statuses}
timeZone={timeZone}
/>
@ -168,15 +158,13 @@ const mstp = (state: AppState, ownProps: OwnProps): StateProps => {
state,
ownProps.dashboardID
)
const timeRange = getTimeRangeByDashboardID(state, ownProps.dashboardID)
const valuesStatus = getDashboardValuesStatus(state, ownProps.dashboardID)
const {properties} = ownProps
const timeRange = getActiveTimeRange(ownProps.timeRange, properties.queries)
const timeZone = state.app.persisted.timeZone
return {
endTime: getEndTime(timeRange),
startTime: getStartTime(timeRange),
ranges: timeRange,
timeZone,
variableAssignments,
variablesStatus: valuesStatus,

View File

@ -20,14 +20,18 @@ import {DEFAULT_LINE_COLORS} from 'src/shared/constants/graphColorPalettes'
import {INVALID_DATA_COPY} from 'src/shared/copy/cell'
// Types
import {RemoteDataState, ScatterViewProperties, TimeZone} from 'src/types'
import {
RemoteDataState,
ScatterViewProperties,
TimeZone,
TimeRange,
} from 'src/types'
interface Props {
children: (config: Config) => JSX.Element
endTime: number
fluxGroupKeyUnion?: string[]
loading: RemoteDataState
startTime: number
timeRange: TimeRange | null
table: Table
timeZone: TimeZone
viewProperties: ScatterViewProperties
@ -35,9 +39,8 @@ interface Props {
const ScatterPlot: FunctionComponent<Props> = ({
children,
endTime,
loading,
startTime,
timeRange,
timeZone,
table,
viewProperties: {
@ -68,8 +71,7 @@ const ScatterPlot: FunctionComponent<Props> = ({
const [xDomain, onSetXDomain, onResetXDomain] = useVisDomainSettings(
storedXDomain,
table.getColumn(xColumn, 'number'),
startTime,
endTime
timeRange
)
const [yDomain, onSetYDomain, onResetYDomain] = useVisDomainSettings(

View File

@ -24,6 +24,7 @@ import {
StatusRow,
TimeZone,
XYViewProperties,
TimeRange,
} from 'src/types'
interface Props {
@ -34,18 +35,16 @@ interface Props {
properties: QueryViewProperties | CheckViewProperties
timeZone: TimeZone
statuses: StatusRow[][]
endTime: number
startTime: number
timeRange: TimeRange | null
}
const ViewSwitcher: FunctionComponent<Props> = ({
properties,
check,
loading,
endTime,
timeRange,
files,
giraffeResult: {table, fluxGroupKeyUnion},
startTime,
timeZone,
statuses,
}) => {
@ -83,10 +82,9 @@ const ViewSwitcher: FunctionComponent<Props> = ({
case 'xy':
return (
<XYPlot
endTime={endTime}
timeRange={timeRange}
fluxGroupKeyUnion={fluxGroupKeyUnion}
loading={loading}
startTime={startTime}
table={table}
timeZone={timeZone}
viewProperties={properties}
@ -111,10 +109,9 @@ const ViewSwitcher: FunctionComponent<Props> = ({
return (
<XYPlot
endTime={endTime}
timeRange={timeRange}
fluxGroupKeyUnion={fluxGroupKeyUnion}
loading={loading}
startTime={startTime}
table={table}
timeZone={timeZone}
viewProperties={xyProperties}
@ -153,9 +150,8 @@ const ViewSwitcher: FunctionComponent<Props> = ({
case 'heatmap':
return (
<HeatmapPlot
endTime={endTime}
timeRange={timeRange}
loading={loading}
startTime={startTime}
table={table}
timeZone={timeZone}
viewProperties={properties}
@ -167,9 +163,8 @@ const ViewSwitcher: FunctionComponent<Props> = ({
case 'scatter':
return (
<ScatterPlot
endTime={endTime}
timeRange={timeRange}
loading={loading}
startTime={startTime}
table={table}
viewProperties={properties}
timeZone={timeZone}

View File

@ -23,14 +23,13 @@ import {DEFAULT_LINE_COLORS} from 'src/shared/constants/graphColorPalettes'
import {INVALID_DATA_COPY} from 'src/shared/copy/cell'
// Types
import {RemoteDataState, XYViewProperties, TimeZone} from 'src/types'
import {RemoteDataState, XYViewProperties, TimeZone, TimeRange} from 'src/types'
interface Props {
children: (config: Config) => JSX.Element
endTime: number
fluxGroupKeyUnion: string[]
loading: RemoteDataState
startTime: number
timeRange: TimeRange | null
table: Table
timeZone: TimeZone
viewProperties: XYViewProperties
@ -38,10 +37,9 @@ interface Props {
const XYPlot: FunctionComponent<Props> = ({
children,
endTime,
fluxGroupKeyUnion,
loading,
startTime,
timeRange,
table,
timeZone,
viewProperties: {
@ -81,8 +79,7 @@ const XYPlot: FunctionComponent<Props> = ({
const [xDomain, onSetXDomain, onResetXDomain] = useVisDomainSettings(
storedXDomain,
table.getColumn(xColumn, 'number'),
startTime,
endTime
timeRange
)
const [yDomain, onSetYDomain, onResetYDomain] = useVisDomainSettings(

View File

@ -3,29 +3,50 @@ import {getValidRange} from 'src/shared/utils/useVisDomainSettings'
// Types
import {numericColumnData as data} from 'mocks/dummyData'
import {CustomTimeRange} from 'src/types/queries'
describe('getValidRange', () => {
const startTime: number = 1573123611000
const endTime: number = 1574981211000
const startTime: string = 'Nov 07 2019 02:46:51 GMT-0800'
const unixStart: number = 1573123611000
const endTime: string = 'Nov 28 2019 14:46:51 GMT-0800'
const unixEnd: number = 1574981211000
it('should return null when no parameters are input', () => {
expect(getValidRange()).toEqual(null)
expect(getValidRange(undefined, undefined)).toEqual(null)
})
it('should return null when no data is passed', () => {
expect(getValidRange([], startTime, endTime)).toEqual(null)
const timeRange: CustomTimeRange = {
type: 'custom',
lower: startTime,
upper: endTime,
}
expect(getValidRange([], timeRange)).toEqual(null)
})
it("should return the startTime as startTime if it's before the first time in the data array", () => {
const [start] = getValidRange(data, startTime, endTime)
expect(start).toEqual(startTime)
const [beginning] = getValidRange(data, endTime, endTime)
const timeRange: CustomTimeRange = {
type: 'custom',
lower: startTime,
upper: endTime,
}
const [start] = getValidRange(data, timeRange)
expect(start).toEqual(unixStart)
timeRange.lower = endTime
const [beginning] = getValidRange(data, timeRange)
expect(beginning).toEqual(data[0])
})
it("should return the endTime as endTime if it's before the last time in the data array", () => {
const range = getValidRange(data, startTime, endTime)
expect(range[1]).toEqual(endTime)
const newRange = getValidRange(data, endTime, startTime)
const timeRange: CustomTimeRange = {
type: 'custom',
lower: startTime,
upper: endTime,
}
const range = getValidRange(data, timeRange)
expect(range[1]).toEqual(unixEnd)
timeRange.lower = endTime
timeRange.upper = startTime
const newRange = getValidRange(data, timeRange)
expect(newRange[1]).toEqual(data[data.length - 1])
})
it('should return the the start and end times based on the data array if no start / endTime are passed', () => {
expect(getValidRange(data)).toEqual([data[0], data[data.length - 1]])
expect(getValidRange(data, null)).toEqual([data[0], data[data.length - 1]])
})
})

View File

@ -5,7 +5,10 @@ import {NumericColumnData} from '@influxdata/giraffe'
// Utils
import {useOneWayState} from 'src/shared/utils/useOneWayState'
import {extent} from 'src/shared/utils/vis'
import {getStartTime, getEndTime} from 'src/timeMachine/selectors/index'
// Types
import {TimeRange} from 'src/types'
/*
This hook helps map the domain setting stored for line graph to the
appropriate settings on a @influxdata/giraffe `Config` object.
@ -16,11 +19,15 @@ import {extent} from 'src/shared/utils/vis'
*/
export const getValidRange = (
data: NumericColumnData = [],
startTime: number = Infinity,
endTime: number = -Infinity
timeRange: TimeRange | null
) => {
const range = extent((data as number[]) || [])
if (!timeRange) {
return range
}
if (range && range.length >= 2) {
const startTime = getStartTime(timeRange)
const endTime = getEndTime(timeRange)
const start = Math.min(startTime, range[0])
const end = Math.max(endTime, range[1])
return [start, end]
@ -31,15 +38,14 @@ export const getValidRange = (
export const useVisDomainSettings = (
storedDomain: number[],
data: NumericColumnData,
startTime: number = Infinity,
endTime: number = -Infinity
timeRange: TimeRange | null = null
) => {
const initialDomain = useMemo(() => {
if (storedDomain) {
return storedDomain
}
return getValidRange(data, startTime, endTime)
return getValidRange(data, timeRange)
}, [storedDomain, data])
const [domain, setDomain] = useOneWayState(initialDomain)

View File

@ -27,18 +27,18 @@ import {
AppState,
QueryViewProperties,
TimeZone,
TimeRange,
Check,
StatusRow,
} from 'src/types'
// Selectors
import {getEndTime, getStartTime} from 'src/timeMachine/selectors/index'
import {getActiveTimeRange} from 'src/timeMachine/selectors/index'
interface StateProps {
timeRange: TimeRange | null
loading: RemoteDataState
errorMessage: string
endTime: number
startTime: number
files: string[]
viewProperties: QueryViewProperties
isInitialFetch: boolean
@ -58,7 +58,7 @@ type Props = StateProps
const TimeMachineVis: SFC<Props> = ({
loading,
errorMessage,
endTime,
timeRange,
isInitialFetch,
isViewingRawData,
files,
@ -69,7 +69,6 @@ const TimeMachineVis: SFC<Props> = ({
yColumn,
fillColumns,
symbolColumns,
startTime,
timeZone,
statuses,
}) => {
@ -113,12 +112,11 @@ const TimeMachineVis: SFC<Props> = ({
) : (
<ViewSwitcher
giraffeResult={giraffeResult}
endTime={endTime}
timeRange={timeRange}
files={files}
loading={loading}
properties={resolvedViewProperties}
check={check}
startTime={startTime}
timeZone={timeZone}
statuses={statuses}
/>
@ -166,8 +164,7 @@ const mstp = (state: AppState): StateProps => {
fillColumns,
symbolColumns,
timeZone,
startTime: getStartTime(timeRange),
endTime: getEndTime(timeRange),
timeRange: getActiveTimeRange(timeRange, viewProperties.queries),
statuses,
}
}

View File

@ -24,6 +24,7 @@ import {
// Types
import {
DashboardQuery,
FluxTable,
QueryView,
AppState,
@ -290,3 +291,21 @@ export const getEndTime = (timeRange: TimeRange): number => {
}
return moment().valueOf()
}
export const getActiveTimeRange = (
timeRange: TimeRange,
queries: DashboardQuery[]
) => {
if (!queries) {
return timeRange
}
const hasVariableTimes = queries.some(
query =>
query.text.includes('v.timeRangeStart') ||
query.text.includes('v.timeRangeStop')
)
if (hasVariableTimes) {
return timeRange
}
return null
}