Implement load on scroll
Co-authored-by: Deniz Kusefoglu <deniz@influxdata.com>pull/10616/head
parent
e94dc256b4
commit
1c19faa1f5
|
@ -1,3 +1,4 @@
|
||||||
|
import moment from 'moment'
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
import {Source, Namespace, TimeRange, QueryConfig} from 'src/types'
|
import {Source, Namespace, TimeRange, QueryConfig} from 'src/types'
|
||||||
import {getSource} from 'src/shared/apis'
|
import {getSource} from 'src/shared/apis'
|
||||||
|
@ -10,14 +11,9 @@ import {
|
||||||
import {getDeep} from 'src/utils/wrappers'
|
import {getDeep} from 'src/utils/wrappers'
|
||||||
import buildQuery from 'src/utils/influxql'
|
import buildQuery from 'src/utils/influxql'
|
||||||
import {executeQueryAsync} from 'src/logs/api'
|
import {executeQueryAsync} from 'src/logs/api'
|
||||||
import {LogsState, Filter} from 'src/types/logs'
|
import {LogsState, Filter, TableData} from 'src/types/logs'
|
||||||
|
|
||||||
interface TableData {
|
const defaultTableData: TableData = {
|
||||||
columns: string[]
|
|
||||||
values: string[]
|
|
||||||
}
|
|
||||||
|
|
||||||
const defaultTableData = {
|
|
||||||
columns: [
|
columns: [
|
||||||
'time',
|
'time',
|
||||||
'severity',
|
'severity',
|
||||||
|
@ -54,6 +50,14 @@ export enum ActionTypes {
|
||||||
ChangeFilter = 'LOGS_CHANGE_FILTER',
|
ChangeFilter = 'LOGS_CHANGE_FILTER',
|
||||||
IncrementQueryCount = 'LOGS_INCREMENT_QUERY_COUNT',
|
IncrementQueryCount = 'LOGS_INCREMENT_QUERY_COUNT',
|
||||||
DecrementQueryCount = 'LOGS_DECREMENT_QUERY_COUNT',
|
DecrementQueryCount = 'LOGS_DECREMENT_QUERY_COUNT',
|
||||||
|
ConcatMoreLogs = 'LOGS_CONCAT_MORE_LOGS',
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ConcatMoreLogsAction {
|
||||||
|
type: ActionTypes.ConcatMoreLogs
|
||||||
|
payload: {
|
||||||
|
series: TableData
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IncrementQueryCountAction {
|
export interface IncrementQueryCountAction {
|
||||||
|
@ -173,6 +177,7 @@ export type Action =
|
||||||
| ChangeFilterAction
|
| ChangeFilterAction
|
||||||
| DecrementQueryCountAction
|
| DecrementQueryCountAction
|
||||||
| IncrementQueryCountAction
|
| IncrementQueryCountAction
|
||||||
|
| ConcatMoreLogsAction
|
||||||
|
|
||||||
const getTimeRange = (state: State): TimeRange | null =>
|
const getTimeRange = (state: State): TimeRange | null =>
|
||||||
getDeep<TimeRange | null>(state, 'logs.timeRange', null)
|
getDeep<TimeRange | null>(state, 'logs.timeRange', null)
|
||||||
|
@ -243,7 +248,7 @@ export const executeHistogramQueryAsync = () => async (
|
||||||
|
|
||||||
const setTableData = (series: TableData): SetTableData => ({
|
const setTableData = (series: TableData): SetTableData => ({
|
||||||
type: ActionTypes.SetTableData,
|
type: ActionTypes.SetTableData,
|
||||||
payload: {data: {columns: series.columns, values: _.reverse(series.values)}},
|
payload: {data: {columns: series.columns, values: series.values}},
|
||||||
})
|
})
|
||||||
|
|
||||||
export const executeTableQueryAsync = () => async (
|
export const executeTableQueryAsync = () => async (
|
||||||
|
@ -261,7 +266,11 @@ export const executeTableQueryAsync = () => async (
|
||||||
|
|
||||||
if (_.every([queryConfig, timeRange, namespace, proxyLink])) {
|
if (_.every([queryConfig, timeRange, namespace, proxyLink])) {
|
||||||
const query = buildLogQuery(timeRange, queryConfig, filters, searchTerm)
|
const query = buildLogQuery(timeRange, queryConfig, filters, searchTerm)
|
||||||
const response = await executeQueryAsync(proxyLink, namespace, query)
|
const response = await executeQueryAsync(
|
||||||
|
proxyLink,
|
||||||
|
namespace,
|
||||||
|
`${query} ORDER BY time DESC LIMIT 1000`
|
||||||
|
)
|
||||||
|
|
||||||
const series = getDeep(response, 'results.0.series.0', defaultTableData)
|
const series = getDeep(response, 'results.0.series.0', defaultTableData)
|
||||||
|
|
||||||
|
@ -348,6 +357,42 @@ export const setTableQueryConfigAsync = () => async (
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const fetchMoreAsync = (
|
||||||
|
queryTimeEnd: string,
|
||||||
|
lastTime: number
|
||||||
|
) => async (dispatch, getState): Promise<void> => {
|
||||||
|
const state = getState()
|
||||||
|
const tableQueryConfig = getTableQueryConfig(state)
|
||||||
|
const time = moment(lastTime).toISOString()
|
||||||
|
const timeRange = {lower: queryTimeEnd, upper: time}
|
||||||
|
const newQueryConfig = {
|
||||||
|
...tableQueryConfig,
|
||||||
|
range: timeRange,
|
||||||
|
}
|
||||||
|
const namespace = getNamespace(state)
|
||||||
|
const proxyLink = getProxyLink(state)
|
||||||
|
const searchTerm = getSearchTerm(state)
|
||||||
|
const filters = getFilters(state)
|
||||||
|
const params = [namespace, proxyLink, tableQueryConfig]
|
||||||
|
|
||||||
|
if (_.every(params)) {
|
||||||
|
const query = buildLogQuery(timeRange, newQueryConfig, filters, searchTerm)
|
||||||
|
const response = await executeQueryAsync(
|
||||||
|
proxyLink,
|
||||||
|
namespace,
|
||||||
|
`${query} ORDER BY time DESC LIMIT 1000`
|
||||||
|
)
|
||||||
|
|
||||||
|
const series = getDeep(response, 'results.0.series.0', defaultTableData)
|
||||||
|
await dispatch(ConcatMoreLogs(series))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ConcatMoreLogs = (series: TableData): ConcatMoreLogsAction => ({
|
||||||
|
type: ActionTypes.ConcatMoreLogs,
|
||||||
|
payload: {series},
|
||||||
|
})
|
||||||
|
|
||||||
export const setNamespaceAsync = (namespace: Namespace) => async (
|
export const setNamespaceAsync = (namespace: Namespace) => async (
|
||||||
dispatch
|
dispatch
|
||||||
): Promise<void> => {
|
): Promise<void> => {
|
||||||
|
|
|
@ -125,13 +125,17 @@ class LogsFilter extends PureComponent<Props, State> {
|
||||||
|
|
||||||
private stopEditing(): void {
|
private stopEditing(): void {
|
||||||
const id = getDeep(this.props, 'filter.id', '')
|
const id = getDeep(this.props, 'filter.id', '')
|
||||||
const {operator, value} = this.state
|
const {operator, value, editing} = this.state
|
||||||
|
const {filter} = this.props
|
||||||
|
|
||||||
|
if (!editing || (filter.operator === operator && filter.value === value)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
let state = {}
|
let state = {}
|
||||||
if (['!=', '==', '=~'].includes(operator) && value !== '') {
|
if (['!=', '==', '=~'].includes(operator) && value !== '') {
|
||||||
this.props.onChangeFilter(id, operator, value)
|
this.props.onChangeFilter(id, operator, value)
|
||||||
} else {
|
} else {
|
||||||
const {filter} = this.props
|
|
||||||
state = {operator: filter.operator, value: filter.value}
|
state = {operator: filter.operator, value: filter.value}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
|
import moment from 'moment'
|
||||||
import classnames from 'classnames'
|
import classnames from 'classnames'
|
||||||
import React, {Component, MouseEvent} from 'react'
|
import React, {Component, MouseEvent} from 'react'
|
||||||
import {Grid, AutoSizer} from 'react-virtualized'
|
import {Grid, AutoSizer, InfiniteLoader} from 'react-virtualized'
|
||||||
import FancyScrollbar from 'src/shared/components/FancyScrollbar'
|
import FancyScrollbar from 'src/shared/components/FancyScrollbar'
|
||||||
|
import {getDeep} from 'src/utils/wrappers'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
getColumnFromData,
|
getColumnFromData,
|
||||||
|
@ -16,6 +18,10 @@ import {
|
||||||
getColumnsFromData,
|
getColumnsFromData,
|
||||||
} from 'src/logs/utils/table'
|
} from 'src/logs/utils/table'
|
||||||
|
|
||||||
|
import timeRanges from 'src/logs/data/timeRanges'
|
||||||
|
|
||||||
|
import {TimeRange} from 'src/types'
|
||||||
|
|
||||||
const ROW_HEIGHT = 26
|
const ROW_HEIGHT = 26
|
||||||
const CHAR_WIDTH = 9
|
const CHAR_WIDTH = 9
|
||||||
interface Props {
|
interface Props {
|
||||||
|
@ -27,7 +33,9 @@ interface Props {
|
||||||
onScrollVertical: () => void
|
onScrollVertical: () => void
|
||||||
onScrolledToTop: () => void
|
onScrolledToTop: () => void
|
||||||
onTagSelection: (selection: {tag: string; key: string}) => void
|
onTagSelection: (selection: {tag: string; key: string}) => void
|
||||||
|
fetchMore: (queryTimeEnd: string, time: number) => Promise<void>
|
||||||
count: number
|
count: number
|
||||||
|
timeRange: TimeRange
|
||||||
}
|
}
|
||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
|
@ -35,20 +43,26 @@ interface State {
|
||||||
scrollTop: number
|
scrollTop: number
|
||||||
currentRow: number
|
currentRow: number
|
||||||
currentMessageWidth: number
|
currentMessageWidth: number
|
||||||
|
lastQueryTime: number
|
||||||
}
|
}
|
||||||
|
|
||||||
class LogsTable extends Component<Props, State> {
|
class LogsTable extends Component<Props, State> {
|
||||||
public static getDerivedStateFromProps(props, state): State {
|
public static getDerivedStateFromProps(props, state): State {
|
||||||
const {isScrolledToTop} = props
|
const {isScrolledToTop} = props
|
||||||
|
|
||||||
|
let lastQueryTime = _.get(state, 'lastQueryTime', null)
|
||||||
let scrollTop = _.get(state, 'scrollTop', 0)
|
let scrollTop = _.get(state, 'scrollTop', 0)
|
||||||
if (isScrolledToTop) {
|
if (isScrolledToTop) {
|
||||||
|
lastQueryTime = null
|
||||||
scrollTop = 0
|
scrollTop = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
const scrollLeft = _.get(state, 'scrollLeft', 0)
|
const scrollLeft = _.get(state, 'scrollLeft', 0)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
...state,
|
||||||
|
isQuerying: false,
|
||||||
|
lastQueryTime,
|
||||||
scrollTop,
|
scrollTop,
|
||||||
scrollLeft,
|
scrollLeft,
|
||||||
currentRow: -1,
|
currentRow: -1,
|
||||||
|
@ -56,13 +70,13 @@ class LogsTable extends Component<Props, State> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private grid: React.RefObject<Grid>
|
private grid: Grid | null
|
||||||
private headerGrid: React.RefObject<Grid>
|
private headerGrid: React.RefObject<Grid>
|
||||||
|
|
||||||
constructor(props: Props) {
|
constructor(props: Props) {
|
||||||
super(props)
|
super(props)
|
||||||
|
|
||||||
this.grid = React.createRef()
|
this.grid = null
|
||||||
this.headerGrid = React.createRef()
|
this.headerGrid = React.createRef()
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
|
@ -70,17 +84,22 @@ class LogsTable extends Component<Props, State> {
|
||||||
scrollLeft: 0,
|
scrollLeft: 0,
|
||||||
currentRow: -1,
|
currentRow: -1,
|
||||||
currentMessageWidth: 0,
|
currentMessageWidth: 0,
|
||||||
|
lastQueryTime: null,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public componentDidUpdate() {
|
public componentDidUpdate() {
|
||||||
this.grid.current.recomputeGridSize()
|
if (this.grid) {
|
||||||
|
this.grid.recomputeGridSize()
|
||||||
|
}
|
||||||
this.headerGrid.current.recomputeGridSize()
|
this.headerGrid.current.recomputeGridSize()
|
||||||
}
|
}
|
||||||
|
|
||||||
public componentDidMount() {
|
public componentDidMount() {
|
||||||
window.addEventListener('resize', this.handleWindowResize)
|
window.addEventListener('resize', this.handleWindowResize)
|
||||||
this.grid.current.recomputeGridSize()
|
if (this.grid) {
|
||||||
|
this.grid.recomputeGridSize()
|
||||||
|
}
|
||||||
this.headerGrid.current.recomputeGridSize()
|
this.headerGrid.current.recomputeGridSize()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,39 +134,89 @@ class LogsTable extends Component<Props, State> {
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</AutoSizer>
|
</AutoSizer>
|
||||||
<AutoSizer>
|
<InfiniteLoader
|
||||||
{({width, height}) => (
|
isRowLoaded={this.isRowLoaded}
|
||||||
<FancyScrollbar
|
loadMoreRows={this.loadMoreRows}
|
||||||
style={{
|
rowCount={this.props.count}
|
||||||
width,
|
>
|
||||||
height,
|
{({registerChild, onRowsRendered}) => (
|
||||||
marginTop: `${ROW_HEIGHT}px`,
|
<AutoSizer>
|
||||||
}}
|
{({width, height}) => (
|
||||||
setScrollTop={this.handleScrollbarScroll}
|
<FancyScrollbar
|
||||||
scrollTop={this.state.scrollTop}
|
style={{
|
||||||
autoHide={false}
|
width,
|
||||||
>
|
height,
|
||||||
<Grid
|
marginTop: `${ROW_HEIGHT}px`,
|
||||||
height={height}
|
}}
|
||||||
rowHeight={this.calculateRowHeight}
|
setScrollTop={this.handleScrollbarScroll}
|
||||||
rowCount={getValuesFromData(this.props.data).length}
|
scrollTop={this.state.scrollTop}
|
||||||
width={width}
|
autoHide={false}
|
||||||
scrollLeft={this.state.scrollLeft}
|
>
|
||||||
scrollTop={this.state.scrollTop}
|
<Grid
|
||||||
onScroll={this.handleScroll}
|
height={height}
|
||||||
cellRenderer={this.cellRenderer}
|
rowHeight={this.calculateRowHeight}
|
||||||
columnCount={columnCount}
|
rowCount={getValuesFromData(this.props.data).length}
|
||||||
columnWidth={this.getColumnWidth}
|
width={width}
|
||||||
ref={this.grid}
|
scrollLeft={this.state.scrollLeft}
|
||||||
style={{height: this.calculateTotalHeight()}}
|
scrollTop={this.state.scrollTop}
|
||||||
/>
|
onScroll={this.handleScroll}
|
||||||
</FancyScrollbar>
|
cellRenderer={this.cellRenderer}
|
||||||
|
onSectionRendered={this.handleRowRender(onRowsRendered)}
|
||||||
|
columnCount={columnCount}
|
||||||
|
columnWidth={this.getColumnWidth}
|
||||||
|
ref={(ref: Grid) => {
|
||||||
|
registerChild(ref)
|
||||||
|
this.grid = ref
|
||||||
|
}}
|
||||||
|
style={{height: this.calculateTotalHeight()}}
|
||||||
|
/>
|
||||||
|
</FancyScrollbar>
|
||||||
|
)}
|
||||||
|
</AutoSizer>
|
||||||
)}
|
)}
|
||||||
</AutoSizer>
|
</InfiniteLoader>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private handleRowRender = onRowsRendered => ({
|
||||||
|
rowStartIndex,
|
||||||
|
rowStopIndex,
|
||||||
|
}) => {
|
||||||
|
onRowsRendered({startIndex: rowStartIndex, stopIndex: rowStopIndex})
|
||||||
|
}
|
||||||
|
|
||||||
|
private loadMoreRows = async () => {
|
||||||
|
const data = getValuesFromData(this.props.data)
|
||||||
|
const {timeRange} = this.props
|
||||||
|
const lastTime = getDeep(
|
||||||
|
data,
|
||||||
|
`${data.length - 1}.0`,
|
||||||
|
new Date().getTime() / 1000
|
||||||
|
)
|
||||||
|
const upper = getDeep<string>(timeRange, 'upper', null)
|
||||||
|
const lower = getDeep<string>(timeRange, 'lower', null)
|
||||||
|
|
||||||
|
if (this.state.lastQueryTime && this.state.lastQueryTime <= lastTime) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const firstQueryTime = getDeep<number>(data, '0.0', null)
|
||||||
|
let queryTimeEnd = lower
|
||||||
|
if (!upper) {
|
||||||
|
const foundTimeRange = timeRanges.find(range => range.lower === lower)
|
||||||
|
queryTimeEnd = moment(firstQueryTime)
|
||||||
|
.subtract(foundTimeRange.seconds, 'seconds')
|
||||||
|
.toISOString()
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.setState({lastQueryTime: lastTime})
|
||||||
|
await this.props.fetchMore(queryTimeEnd, lastTime)
|
||||||
|
}
|
||||||
|
|
||||||
|
private isRowLoaded = ({index}) => {
|
||||||
|
return !!getValuesFromData(this.props.data)[index]
|
||||||
|
}
|
||||||
|
|
||||||
private handleWindowResize = () => {
|
private handleWindowResize = () => {
|
||||||
this.setState({currentMessageWidth: getMessageWidth(this.props.data)})
|
this.setState({currentMessageWidth: getMessageWidth(this.props.data)})
|
||||||
}
|
}
|
||||||
|
@ -178,8 +247,9 @@ class LogsTable extends Component<Props, State> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private calculateTotalHeight = (): number => {
|
private calculateTotalHeight = (): number => {
|
||||||
|
const data = getValuesFromData(this.props.data)
|
||||||
return _.reduce(
|
return _.reduce(
|
||||||
getValuesFromData(this.props.data),
|
data,
|
||||||
(acc, __, index) => {
|
(acc, __, index) => {
|
||||||
return acc + this.calculateMessageHeight(index)
|
return acc + this.calculateMessageHeight(index)
|
||||||
},
|
},
|
||||||
|
|
|
@ -11,6 +11,7 @@ import {
|
||||||
addFilter,
|
addFilter,
|
||||||
removeFilter,
|
removeFilter,
|
||||||
changeFilter,
|
changeFilter,
|
||||||
|
fetchMoreAsync,
|
||||||
} from 'src/logs/actions'
|
} from 'src/logs/actions'
|
||||||
import {getSourcesAsync} from 'src/shared/actions/sources'
|
import {getSourcesAsync} from 'src/shared/actions/sources'
|
||||||
import LogViewerHeader from 'src/logs/components/LogViewerHeader'
|
import LogViewerHeader from 'src/logs/components/LogViewerHeader'
|
||||||
|
@ -36,6 +37,7 @@ interface Props {
|
||||||
changeZoomAsync: (timeRange: TimeRange) => void
|
changeZoomAsync: (timeRange: TimeRange) => void
|
||||||
executeQueriesAsync: () => void
|
executeQueriesAsync: () => void
|
||||||
setSearchTermAsync: (searchTerm: string) => void
|
setSearchTermAsync: (searchTerm: string) => void
|
||||||
|
fetchMoreAsync: (queryTimeEnd: string, lastTime: number) => Promise<void>
|
||||||
addFilter: (filter: Filter) => void
|
addFilter: (filter: Filter) => void
|
||||||
removeFilter: (id: string) => void
|
removeFilter: (id: string) => void
|
||||||
changeFilter: (id: string, operator: string, value: string) => void
|
changeFilter: (id: string, operator: string, value: string) => void
|
||||||
|
@ -77,7 +79,7 @@ class LogsPage extends PureComponent<Props, State> {
|
||||||
this.props.getSources()
|
this.props.getSources()
|
||||||
|
|
||||||
if (this.props.currentNamespace) {
|
if (this.props.currentNamespace) {
|
||||||
this.props.executeQueriesAsync()
|
this.fetchNewDataset()
|
||||||
}
|
}
|
||||||
|
|
||||||
this.startUpdating()
|
this.startUpdating()
|
||||||
|
@ -89,9 +91,7 @@ class LogsPage extends PureComponent<Props, State> {
|
||||||
|
|
||||||
public render() {
|
public render() {
|
||||||
const {liveUpdating} = this.state
|
const {liveUpdating} = this.state
|
||||||
const {searchTerm, filters, queryCount} = this.props
|
const {searchTerm, filters, queryCount, timeRange} = this.props
|
||||||
|
|
||||||
const count = getDeep(this.props, 'tableData.values.length', 0)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="page">
|
<div className="page">
|
||||||
|
@ -103,7 +103,7 @@ class LogsPage extends PureComponent<Props, State> {
|
||||||
onSearch={this.handleSubmitSearch}
|
onSearch={this.handleSubmitSearch}
|
||||||
/>
|
/>
|
||||||
<FilterBar
|
<FilterBar
|
||||||
numResults={count}
|
numResults={this.histogramTotal}
|
||||||
filters={filters || []}
|
filters={filters || []}
|
||||||
onDelete={this.handleFilterDelete}
|
onDelete={this.handleFilterDelete}
|
||||||
onFilterChange={this.handleFilterChange}
|
onFilterChange={this.handleFilterChange}
|
||||||
|
@ -116,6 +116,8 @@ class LogsPage extends PureComponent<Props, State> {
|
||||||
onScrolledToTop={this.handleScrollToTop}
|
onScrolledToTop={this.handleScrollToTop}
|
||||||
isScrolledToTop={liveUpdating}
|
isScrolledToTop={liveUpdating}
|
||||||
onTagSelection={this.handleTagSelection}
|
onTagSelection={this.handleTagSelection}
|
||||||
|
fetchMore={this.props.fetchMoreAsync}
|
||||||
|
timeRange={timeRange}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -158,11 +160,11 @@ class LogsPage extends PureComponent<Props, State> {
|
||||||
value: selection.tag,
|
value: selection.tag,
|
||||||
operator: '==',
|
operator: '==',
|
||||||
})
|
})
|
||||||
this.props.executeQueriesAsync()
|
this.fetchNewDataset()
|
||||||
}
|
}
|
||||||
|
|
||||||
private handleInterval = () => {
|
private handleInterval = () => {
|
||||||
this.props.executeQueriesAsync()
|
this.fetchNewDataset()
|
||||||
}
|
}
|
||||||
|
|
||||||
private get histogramTotal(): number {
|
private get histogramTotal(): number {
|
||||||
|
@ -233,7 +235,7 @@ class LogsPage extends PureComponent<Props, State> {
|
||||||
|
|
||||||
private handleFilterDelete = (id: string): void => {
|
private handleFilterDelete = (id: string): void => {
|
||||||
this.props.removeFilter(id)
|
this.props.removeFilter(id)
|
||||||
this.props.executeQueriesAsync()
|
this.fetchNewDataset()
|
||||||
}
|
}
|
||||||
|
|
||||||
private handleFilterChange = (
|
private handleFilterChange = (
|
||||||
|
@ -242,12 +244,13 @@ class LogsPage extends PureComponent<Props, State> {
|
||||||
value: string
|
value: string
|
||||||
) => {
|
) => {
|
||||||
this.props.changeFilter(id, operator, value)
|
this.props.changeFilter(id, operator, value)
|
||||||
|
this.fetchNewDataset()
|
||||||
this.props.executeQueriesAsync()
|
this.props.executeQueriesAsync()
|
||||||
}
|
}
|
||||||
|
|
||||||
private handleChooseTimerange = (timeRange: TimeRange) => {
|
private handleChooseTimerange = (timeRange: TimeRange) => {
|
||||||
this.props.setTimeRangeAsync(timeRange)
|
this.props.setTimeRangeAsync(timeRange)
|
||||||
this.props.executeQueriesAsync()
|
this.fetchNewDataset()
|
||||||
}
|
}
|
||||||
|
|
||||||
private handleChooseSource = (sourceID: string) => {
|
private handleChooseSource = (sourceID: string) => {
|
||||||
|
@ -261,8 +264,14 @@ class LogsPage extends PureComponent<Props, State> {
|
||||||
private handleChartZoom = (lower, upper) => {
|
private handleChartZoom = (lower, upper) => {
|
||||||
if (lower) {
|
if (lower) {
|
||||||
this.props.changeZoomAsync({lower, upper})
|
this.props.changeZoomAsync({lower, upper})
|
||||||
|
this.setState({liveUpdating: true})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fetchNewDataset() {
|
||||||
|
this.props.executeQueriesAsync()
|
||||||
|
this.setState({liveUpdating: true})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapStateToProps = ({
|
const mapStateToProps = ({
|
||||||
|
@ -302,6 +311,7 @@ const mapDispatchToProps = {
|
||||||
addFilter,
|
addFilter,
|
||||||
removeFilter,
|
removeFilter,
|
||||||
changeFilter,
|
changeFilter,
|
||||||
|
fetchMoreAsync,
|
||||||
}
|
}
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(LogsPage)
|
export default connect(mapStateToProps, mapDispatchToProps)(LogsPage)
|
||||||
|
|
|
@ -7,6 +7,7 @@ import {
|
||||||
ChangeFilterAction,
|
ChangeFilterAction,
|
||||||
DecrementQueryCountAction,
|
DecrementQueryCountAction,
|
||||||
IncrementQueryCountAction,
|
IncrementQueryCountAction,
|
||||||
|
ConcatMoreLogsAction,
|
||||||
} from 'src/logs/actions'
|
} from 'src/logs/actions'
|
||||||
import {LogsState} from 'src/types/logs'
|
import {LogsState} from 'src/types/logs'
|
||||||
|
|
||||||
|
@ -17,9 +18,9 @@ const defaultState: LogsState = {
|
||||||
currentNamespace: null,
|
currentNamespace: null,
|
||||||
histogramQueryConfig: null,
|
histogramQueryConfig: null,
|
||||||
tableQueryConfig: null,
|
tableQueryConfig: null,
|
||||||
tableData: [],
|
tableData: {columns: [], values: []},
|
||||||
histogramData: [],
|
histogramData: [],
|
||||||
searchTerm: null,
|
searchTerm: '',
|
||||||
filters: [],
|
filters: [],
|
||||||
queryCount: 0,
|
queryCount: 0,
|
||||||
}
|
}
|
||||||
|
@ -75,6 +76,24 @@ const incrementQueryCount = (
|
||||||
return {...state, queryCount: queryCount + 1}
|
return {...state, queryCount: queryCount + 1}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const concatMoreLogs = (
|
||||||
|
state: LogsState,
|
||||||
|
action: ConcatMoreLogsAction
|
||||||
|
): LogsState => {
|
||||||
|
const {
|
||||||
|
series: {values},
|
||||||
|
} = action.payload
|
||||||
|
const {tableData} = state
|
||||||
|
const vals = [...tableData.values, ...values]
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
tableData: {
|
||||||
|
columns: tableData.columns,
|
||||||
|
values: vals,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export default (state: LogsState = defaultState, action: Action) => {
|
export default (state: LogsState = defaultState, action: Action) => {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case ActionTypes.SetSource:
|
case ActionTypes.SetSource:
|
||||||
|
@ -109,6 +128,8 @@ export default (state: LogsState = defaultState, action: Action) => {
|
||||||
return incrementQueryCount(state, action)
|
return incrementQueryCount(state, action)
|
||||||
case ActionTypes.DecrementQueryCount:
|
case ActionTypes.DecrementQueryCount:
|
||||||
return decrementQueryCount(state, action)
|
return decrementQueryCount(state, action)
|
||||||
|
case ActionTypes.ConcatMoreLogs:
|
||||||
|
return concatMoreLogs(state, action)
|
||||||
default:
|
default:
|
||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,11 @@ export interface Filter {
|
||||||
operator: string
|
operator: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface TableData {
|
||||||
|
columns: string[]
|
||||||
|
values: object[]
|
||||||
|
}
|
||||||
|
|
||||||
export interface LogsState {
|
export interface LogsState {
|
||||||
currentSource: Source | null
|
currentSource: Source | null
|
||||||
currentNamespaces: Namespace[]
|
currentNamespaces: Namespace[]
|
||||||
|
@ -15,7 +20,7 @@ export interface LogsState {
|
||||||
histogramQueryConfig: QueryConfig | null
|
histogramQueryConfig: QueryConfig | null
|
||||||
histogramData: object[]
|
histogramData: object[]
|
||||||
tableQueryConfig: QueryConfig | null
|
tableQueryConfig: QueryConfig | null
|
||||||
tableData: object[]
|
tableData: TableData
|
||||||
searchTerm: string | null
|
searchTerm: string | null
|
||||||
filters: Filter[]
|
filters: Filter[]
|
||||||
queryCount: number
|
queryCount: number
|
||||||
|
|
Loading…
Reference in New Issue