diff --git a/x-pack/plugins/infra/public/components/logging/log_minimap/log_minimap.tsx b/x-pack/plugins/infra/public/components/logging/log_minimap/log_minimap.tsx index 12f8b14bfb614..85f47cd4eb1e1 100644 --- a/x-pack/plugins/infra/public/components/logging/log_minimap/log_minimap.tsx +++ b/x-pack/plugins/infra/public/components/logging/log_minimap/log_minimap.tsx @@ -36,7 +36,7 @@ interface LogMinimapProps { intervalSize: number; summaryBuckets: SummaryBucket[]; // searchSummaryBuckets?: SearchSummaryBucket[]; - target: number; + target: number | null; width: number; } @@ -55,8 +55,10 @@ export class LogMinimap extends React.Component { public getYScale = () => { const { height, intervalSize, target } = this.props; + const domainStart = target ? target - intervalSize / 2 : 0; + const domainEnd = target ? target + intervalSize / 2 : 0; return scaleLinear() - .domain([target - intervalSize / 2, target + intervalSize / 2]) + .domain([domainStart, domainEnd]) .range([0, height]); }; diff --git a/x-pack/plugins/infra/public/components/logging/log_text_stream/loading_item_view.tsx b/x-pack/plugins/infra/public/components/logging/log_text_stream/loading_item_view.tsx index dd2364a536277..973b35d449817 100644 --- a/x-pack/plugins/infra/public/components/logging/log_text_stream/loading_item_view.tsx +++ b/x-pack/plugins/infra/public/components/logging/log_text_stream/loading_item_view.tsx @@ -8,19 +8,15 @@ import { EuiProgress, EuiText } from '@elastic/eui'; import * as React from 'react'; import styled from 'styled-components'; -import { - getTimeOrDefault, - isExhaustedLoadingResult, - isIntervalLoadingPolicy, - isRunningLoadingProgress, - LoadingState, -} from '../../../utils/loading_state'; import { RelativeTime } from './relative_time'; interface LogTextStreamLoadingItemViewProps { alignment: 'top' | 'bottom'; className?: string; - loadingState: LoadingState; + hasMore: boolean; + isLoading: boolean; + isStreaming: boolean; + lastStreamingUpdate: number | null; } export class LogTextStreamLoadingItemView extends React.PureComponent< @@ -28,21 +24,24 @@ export class LogTextStreamLoadingItemView extends React.PureComponent< {} > { public render() { - const { alignment, className, loadingState } = this.props; - - const isLoading = isRunningLoadingProgress(loadingState.current); - const isExhausted = isExhaustedLoadingResult(loadingState.last); - const lastLoadedTime = getTimeOrDefault(loadingState.last); - const isStreaming = isIntervalLoadingPolicy(loadingState.policy); + const { + alignment, + className, + hasMore, + isLoading, + isStreaming, + lastStreamingUpdate, + } = this.props; if (isStreaming) { return ( Streaming new entries - {lastLoadedTime ? ( + {lastStreamingUpdate ? ( <> - : last updated ago + : last updated {' '} + ago ) : null} @@ -54,7 +53,7 @@ export class LogTextStreamLoadingItemView extends React.PureComponent< Loading additional entries ); - } else if (isExhausted) { + } else if (!hasMore) { return ( ; - endLoadingState: LoadingState; - target: TimeKey; + isReloading: boolean; + isLoadingMore: boolean; + hasMoreBeforeStart: boolean; + hasMoreAfterEnd: boolean; + isStreaming: boolean; + lastLoadedTime: number | null; + target: TimeKey | null; jumpToTarget: (target: TimeKey) => any; reportVisibleInterval: ( params: { @@ -44,8 +43,8 @@ interface ScrollableLogTextStreamViewProps { } interface ScrollableLogTextStreamViewState { - target: TimeKey | undefined; - targetId: string | undefined; + target: TimeKey | null; + targetId: string | null; } export class ScrollableLogTextStreamView extends React.PureComponent< @@ -58,9 +57,8 @@ export class ScrollableLogTextStreamView extends React.PureComponent< ): Partial | null { const hasNewTarget = nextProps.target && nextProps.target !== prevState.target; const hasItems = nextProps.items.length > 0; - const isEndStreaming = isIntervalLoadingPolicy(nextProps.endLoadingState.policy); - if (isEndStreaming && hasItems) { + if (nextProps.isStreaming && hasItems) { return { target: nextProps.target, targetId: getStreamItemId(nextProps.items[nextProps.items.length - 1]), @@ -68,12 +66,12 @@ export class ScrollableLogTextStreamView extends React.PureComponent< } else if (hasNewTarget && hasItems) { return { target: nextProps.target, - targetId: getStreamItemId(getStreamItemBeforeTimeKey(nextProps.items, nextProps.target)), + targetId: getStreamItemId(getStreamItemBeforeTimeKey(nextProps.items, nextProps.target!)), }; } else if (!nextProps.target || !hasItems) { return { - target: undefined, - targetId: undefined, + target: null, + targetId: null, }; } @@ -81,20 +79,29 @@ export class ScrollableLogTextStreamView extends React.PureComponent< } public readonly state = { - target: undefined, - targetId: undefined, + target: null, + targetId: null, }; public render() { - const { items, height, width, scale, wrap, startLoadingState, endLoadingState } = this.props; + const { + items, + height, + width, + scale, + wrap, + isReloading, + isLoadingMore, + hasMoreBeforeStart, + hasMoreAfterEnd, + isStreaming, + lastLoadedTime, + } = this.props; const { targetId } = this.state; const hasItems = items.length > 0; - const isStartLoading = isRunningLoadingProgress(startLoadingState.current); - const isEndLoading = isRunningLoadingProgress(endLoadingState.current); - const isLoading = isStartLoading || isEndLoading; - if (isLoading && !hasItems) { + if (isReloading && !hasItems) { return ; } else if (!hasItems) { return ; @@ -109,7 +116,13 @@ export class ScrollableLogTextStreamView extends React.PureComponent< > {registerChild => ( <> - + {items.map(item => ( ))} - + )} @@ -130,7 +149,11 @@ export class ScrollableLogTextStreamView extends React.PureComponent< } private handleReload = () => { - this.props.jumpToTarget(this.props.target); + const { jumpToTarget, target } = this.props; + + if (target) { + jumpToTarget(target); + } }; // this is actually a method but not recognized as such diff --git a/x-pack/plugins/infra/public/components/logging/log_time_controls.tsx b/x-pack/plugins/infra/public/components/logging/log_time_controls.tsx index 93b3b0e10c7a7..9d719168bcb39 100644 --- a/x-pack/plugins/infra/public/components/logging/log_time_controls.tsx +++ b/x-pack/plugins/infra/public/components/logging/log_time_controls.tsx @@ -12,18 +12,18 @@ import styled from 'styled-components'; const noop = () => undefined; interface LogTimeControlsProps { - currentTime: number; - disableLiveStreaming: () => any; - enableLiveStreaming: () => any; + currentTime: number | null; + startLiveStreaming: (interval: number) => any; + stopLiveStreaming: () => any; isLiveStreaming: boolean; jumpToTime: (time: number) => any; } export class LogTimeControls extends React.PureComponent { public render() { - const { currentTime, disableLiveStreaming, enableLiveStreaming, isLiveStreaming } = this.props; + const { currentTime, isLiveStreaming } = this.props; - const currentMoment = moment(currentTime); + const currentMoment = currentTime ? moment(currentTime) : null; if (isLiveStreaming) { return ( @@ -35,7 +35,7 @@ export class LogTimeControls extends React.PureComponent { color="primary" iconType="pause" iconSide="left" - onClick={disableLiveStreaming} + onClick={this.stopLiveStreaming} > Stop streaming @@ -53,10 +53,10 @@ export class LogTimeControls extends React.PureComponent { shouldCloseOnSelect showTimeSelect timeFormat="LTS" - injectTimes={[currentMoment]} + injectTimes={currentMoment ? [currentMoment] : []} /> - + Stream live @@ -69,6 +69,14 @@ export class LogTimeControls extends React.PureComponent { this.props.jumpToTime(date.valueOf()); } }; + + private startLiveStreaming = () => { + this.props.startLiveStreaming(5000); + }; + + private stopLiveStreaming = () => { + this.props.stopLiveStreaming(); + }; } const InlineWrapper = styled.div` diff --git a/x-pack/plugins/infra/public/containers/logging_legacy/state/actions.ts b/x-pack/plugins/infra/public/containers/logging_legacy/state/actions.ts index 39fb84516a4e2..9ade8f2252462 100644 --- a/x-pack/plugins/infra/public/containers/logging_legacy/state/actions.ts +++ b/x-pack/plugins/infra/public/containers/logging_legacy/state/actions.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -export { targetActions } from './target'; +export { logPositionActions } from './log_position'; export { entriesActions } from './entries'; export { textviewActions } from './textview'; export { summaryActions } from './summary'; diff --git a/x-pack/plugins/infra/public/containers/logging_legacy/state/entries/epics.ts b/x-pack/plugins/infra/public/containers/logging_legacy/state/entries/epics.ts index 5f971e78ea4bd..40e6820883912 100644 --- a/x-pack/plugins/infra/public/containers/logging_legacy/state/entries/epics.ts +++ b/x-pack/plugins/infra/public/containers/logging_legacy/state/entries/epics.ts @@ -6,18 +6,12 @@ import { Action } from 'redux'; import { combineEpics, Epic, EpicWithState } from 'redux-observable'; -import { /*interval,*/ merge } from 'rxjs'; +import { merge } from 'rxjs'; import { exhaustMap, filter, map, withLatestFrom } from 'rxjs/operators'; import { pickTimeKey, TimeKey, timeKeyIsBetween } from '../../../../../common/time'; -import { targetActions } from '../target'; -import { - loadEntries, - loadMoreEntries, - reportVisibleEntries, - // startLiveStreaming, - // stopLiveStreaming, -} from './actions'; +import { logPositionActions } from '../log_position'; +import { loadEntries, loadMoreEntries, reportVisibleEntries } from './actions'; import { loadMoreEntriesEpic } from './load_more_operation'; import { loadEntriesEpic } from './load_operation'; @@ -29,6 +23,7 @@ interface ManageEntriesDependencies { selectEntriesEnd: (state: State) => TimeKey | null; selectHasMoreBeforeStart: (state: State) => boolean; selectHasMoreAfterEnd: (state: State) => boolean; + selectIsAutoReloading: (state: State) => boolean; selectIsLoadingEntries: (state: State) => boolean; } @@ -52,11 +47,12 @@ export const createEntriesEffectsEpic = (): Epic< selectEntriesEnd, selectHasMoreBeforeStart, selectHasMoreAfterEnd, + selectIsAutoReloading, selectIsLoadingEntries, } ) => { const shouldLoadAround$ = action$.pipe( - filter(targetActions.jumpToTarget.match), + filter(logPositionActions.jumpToTargetPosition.match), withLatestFrom(state$), filter(([{ payload }, state]) => { const entriesStart = selectEntriesStart(state); @@ -73,6 +69,7 @@ export const createEntriesEffectsEpic = (): Epic< filter(reportVisibleEntries.match), filter(({ payload: { pagesBeforeStart } }) => pagesBeforeStart < DESIRED_BUFFER_PAGES), withLatestFrom(state$), + filter(([action, state]) => !selectIsAutoReloading(state)), filter(([action, state]) => !selectIsLoadingEntries(state)), filter(([action, state]) => selectHasMoreBeforeStart(state)), map(([action, state]) => selectEntriesStart(state)), @@ -84,6 +81,7 @@ export const createEntriesEffectsEpic = (): Epic< filter(reportVisibleEntries.match), filter(({ payload: { pagesAfterEnd } }) => pagesAfterEnd < DESIRED_BUFFER_PAGES), withLatestFrom(state$), + filter(([action, state]) => !selectIsAutoReloading(state)), filter(([action, state]) => !selectIsLoadingEntries(state)), filter(([action, state]) => selectHasMoreAfterEnd(state)), map(([action, state]) => selectEntriesEnd(state)), diff --git a/x-pack/plugins/infra/public/containers/logging_legacy/state/entries/selectors.ts b/x-pack/plugins/infra/public/containers/logging_legacy/state/entries/selectors.ts index 65905974a38a9..17668af38e815 100644 --- a/x-pack/plugins/infra/public/containers/logging_legacy/state/entries/selectors.ts +++ b/x-pack/plugins/infra/public/containers/logging_legacy/state/entries/selectors.ts @@ -62,6 +62,8 @@ export const selectHasMoreAfterEnd = createSelector( data => (data ? data.hasMoreAfter : true) ); +export const selectEntriesLastLoadedTime = entriesGraphlStateSelectors.selectLoadingResultTime; + export const selectEntriesStartLoadingState = entriesGraphlStateSelectors.selectLoadingState; export const selectEntriesEndLoadingState = entriesGraphlStateSelectors.selectLoadingState; diff --git a/x-pack/plugins/infra/public/containers/logging_legacy/state/epics.ts b/x-pack/plugins/infra/public/containers/logging_legacy/state/epics.ts index e585669757dc8..f2ce1be67b75b 100644 --- a/x-pack/plugins/infra/public/containers/logging_legacy/state/epics.ts +++ b/x-pack/plugins/infra/public/containers/logging_legacy/state/epics.ts @@ -7,6 +7,7 @@ import { combineEpics } from 'redux-observable'; import { entriesEpics } from './entries'; +import { logPositionEpics } from './log_position'; // import { searchResultsEpics } from './search_results'; // import { searchSummaryEpics } from './search_summary'; import { summaryEpics } from './summary'; @@ -14,7 +15,8 @@ import { summaryEpics } from './summary'; export const createRootEpic = () => combineEpics( summaryEpics.createSummaryEpic(), - entriesEpics.createEntriesEpic() + entriesEpics.createEntriesEpic(), + logPositionEpics.createLogPositionEpic() // searchResultsEpics.createSearchResultsEpic(), // searchSummaryEpics.createSearchSummaryEpic() ); diff --git a/x-pack/plugins/infra/public/containers/logging_legacy/state/log_position/actions.ts b/x-pack/plugins/infra/public/containers/logging_legacy/state/log_position/actions.ts new file mode 100644 index 0000000000000..e8d11701710b1 --- /dev/null +++ b/x-pack/plugins/infra/public/containers/logging_legacy/state/log_position/actions.ts @@ -0,0 +1,23 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import actionCreatorFactory from 'typescript-fsa'; + +import { TimeKey } from '../../../../../common/time'; + +const actionCreator = actionCreatorFactory('kibana/logging/log_position'); + +export const jumpToTargetPosition = actionCreator('JUMP_TO_TARGET_POSITION'); + +export const jumpToTargetPositionTime = (time: number) => + jumpToTargetPosition({ + tiebreaker: 0, + time, + }); + +export const startAutoReload = actionCreator('START_AUTO_RELOAD'); + +export const stopAutoReload = actionCreator('STOP_AUTO_RELOAD'); diff --git a/x-pack/plugins/infra/public/containers/logging_legacy/state/log_position/epics.ts b/x-pack/plugins/infra/public/containers/logging_legacy/state/log_position/epics.ts new file mode 100644 index 0000000000000..01b9b6eb0bb42 --- /dev/null +++ b/x-pack/plugins/infra/public/containers/logging_legacy/state/log_position/epics.ts @@ -0,0 +1,23 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { Action } from 'redux'; +import { Epic } from 'redux-observable'; +import { timer } from 'rxjs'; +import { exhaustMap, filter, map, takeUntil } from 'rxjs/operators'; + +import { jumpToTargetPositionTime, startAutoReload, stopAutoReload } from './actions'; + +export const createLogPositionEpic = (): Epic => action$ => + action$.pipe( + filter(startAutoReload.match), + exhaustMap(({ payload }) => + timer(0, payload).pipe( + map(() => jumpToTargetPositionTime(Date.now())), + takeUntil(action$.pipe(filter(stopAutoReload.match))) + ) + ) + ); diff --git a/x-pack/plugins/infra/public/containers/logging_legacy/state/target/index.ts b/x-pack/plugins/infra/public/containers/logging_legacy/state/log_position/index.ts similarity index 55% rename from x-pack/plugins/infra/public/containers/logging_legacy/state/target/index.ts rename to x-pack/plugins/infra/public/containers/logging_legacy/state/log_position/index.ts index 527d32b4d1236..ddb0e5907cf96 100644 --- a/x-pack/plugins/infra/public/containers/logging_legacy/state/target/index.ts +++ b/x-pack/plugins/infra/public/containers/logging_legacy/state/log_position/index.ts @@ -4,8 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import * as targetActions from './actions'; -import * as targetSelectors from './selectors'; +import * as logPositionActions from './actions'; +import * as logPositionEpics from './epics'; +import * as logPositionSelectors from './selectors'; -export { targetActions, targetSelectors }; +export { logPositionActions, logPositionEpics, logPositionSelectors }; export * from './reducer'; diff --git a/x-pack/plugins/infra/public/containers/logging_legacy/state/log_position/reducer.ts b/x-pack/plugins/infra/public/containers/logging_legacy/state/log_position/reducer.ts new file mode 100644 index 0000000000000..d27990d778c23 --- /dev/null +++ b/x-pack/plugins/infra/public/containers/logging_legacy/state/log_position/reducer.ts @@ -0,0 +1,57 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { combineReducers } from 'redux'; +import { reducerWithInitialState } from 'typescript-fsa-reducers'; + +import { TimeKey } from '../../../../../common/time'; +import { jumpToTargetPosition, startAutoReload, stopAutoReload } from './actions'; + +interface ManualTargetPositionUpdatePolicy { + policy: 'manual'; +} + +interface IntervalTargetPositionUpdatePolicy { + policy: 'interval'; + interval: number; +} + +type TargetPositionUpdatePolicy = + | ManualTargetPositionUpdatePolicy + | IntervalTargetPositionUpdatePolicy; + +export interface LogPositionState { + targetPosition: TimeKey | null; + updatePolicy: TargetPositionUpdatePolicy; +} + +export const initialLogPositionState: LogPositionState = { + targetPosition: null, + updatePolicy: { + policy: 'manual', + }, +}; + +const targetPositionReducer = reducerWithInitialState(initialLogPositionState.targetPosition).case( + jumpToTargetPosition, + (state, target) => target +); + +const targetPositionUpdatePolicyReducer = reducerWithInitialState( + initialLogPositionState.updatePolicy +) + .case(startAutoReload, (state, interval) => ({ + policy: 'interval', + interval, + })) + .case(stopAutoReload, () => ({ + policy: 'manual', + })); + +export const logPositionReducer = combineReducers({ + targetPosition: targetPositionReducer, + updatePolicy: targetPositionUpdatePolicyReducer, +}); diff --git a/x-pack/plugins/infra/public/containers/logging_legacy/state/target/selectors.ts b/x-pack/plugins/infra/public/containers/logging_legacy/state/log_position/selectors.ts similarity index 50% rename from x-pack/plugins/infra/public/containers/logging_legacy/state/target/selectors.ts rename to x-pack/plugins/infra/public/containers/logging_legacy/state/log_position/selectors.ts index 48a92183b00cf..76460afcbecae 100644 --- a/x-pack/plugins/infra/public/containers/logging_legacy/state/target/selectors.ts +++ b/x-pack/plugins/infra/public/containers/logging_legacy/state/log_position/selectors.ts @@ -4,6 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import { TargetState } from './reducer'; +import { LogPositionState } from './reducer'; -export const selectTarget = (state: TargetState) => state; +export const selectTargetPosition = (state: LogPositionState) => state.targetPosition; + +export const selectIsAutoReloading = (state: LogPositionState) => + state.updatePolicy.policy === 'interval'; diff --git a/x-pack/plugins/infra/public/containers/logging_legacy/state/reducer.ts b/x-pack/plugins/infra/public/containers/logging_legacy/state/reducer.ts index 4ffb37affaee5..07b7bc1d65427 100644 --- a/x-pack/plugins/infra/public/containers/logging_legacy/state/reducer.ts +++ b/x-pack/plugins/infra/public/containers/logging_legacy/state/reducer.ts @@ -12,6 +12,7 @@ import { initialConfigurationState, } from './configuration'; import { entriesReducer, EntriesState, initialEntriesState } from './entries'; +import { initialLogPositionState, logPositionReducer, LogPositionState } from './log_position'; import { initialMinimapState, minimapReducer, MinimapState } from './minimap'; // import { initialSearchState, searchReducer, SearchState } from './search'; // import { @@ -26,13 +27,12 @@ import { initialMinimapState, minimapReducer, MinimapState } from './minimap'; // } from './search_summary'; import { initialSourceState, sourceReducer, SourceState } from './source'; import { initialSummaryState, summaryReducer, SummaryState } from './summary'; -import { initialTargetState, targetReducer, TargetState } from './target'; import { initialTextviewState, textviewReducer, TextviewState } from './textview'; export interface State { configuration: ConfigurationState; source: SourceState; - target: TargetState; + logPosition: LogPositionState; entries: EntriesState; textview: TextviewState; summary: SummaryState; @@ -51,7 +51,7 @@ export const initialState: State = { // searchSummary: initialSearchSummaryState, source: initialSourceState, summary: initialSummaryState, - target: initialTargetState, + logPosition: initialLogPositionState, textview: initialTextviewState, }; @@ -64,6 +64,6 @@ export const reducer = combineReducers({ // searchSummary: searchSummaryReducer, source: sourceReducer, summary: summaryReducer, - target: targetReducer, + logPosition: logPositionReducer, textview: textviewReducer, }); diff --git a/x-pack/plugins/infra/public/containers/logging_legacy/state/selectors.ts b/x-pack/plugins/infra/public/containers/logging_legacy/state/selectors.ts index d044ce749805a..ca1ba1ad9573c 100644 --- a/x-pack/plugins/infra/public/containers/logging_legacy/state/selectors.ts +++ b/x-pack/plugins/infra/public/containers/logging_legacy/state/selectors.ts @@ -15,6 +15,7 @@ import { createSelector } from 'reselect'; import { globalizeSelectors } from '../../../utils/typed_redux'; import { configurationSelectors as localConfigurationSelectors } from './configuration'; import { entriesSelectors as localEntriesSelectors } from './entries'; +import { logPositionSelectors as localLogPositionSelectors } from './log_position'; import { minimapSelectors as localMinimapSelectors } from './minimap'; import { State } from './reducer'; // import { searchSelectors as localSearchSelectors } from './search'; @@ -22,7 +23,6 @@ import { State } from './reducer'; // import { searchSummarySelectors as localSearchSummarySelectors } from './search_summary'; import { sourceSelectors as localSourceSelectors } from './source'; import { summarySelectors as localSummarySelectors } from './summary'; -import { targetSelectors as localTargetSelectors } from './target'; import { textviewSelectors as localTextviewSelectors } from './textview'; export const configurationSelectors = globalizeSelectors( @@ -35,9 +35,9 @@ export const sourceSelectors = globalizeSelectors( localSourceSelectors ); -export const targetSelectors = globalizeSelectors( - (state: State) => state.target, - localTargetSelectors +export const logPositionSelectors = globalizeSelectors( + (state: State) => state.logPosition, + localLogPositionSelectors ); export const entriesSelectors = globalizeSelectors( @@ -117,7 +117,7 @@ export const sharedSelectors = { selectVisibleMidpointOrTargetTime: createSelector( entriesSelectors.selectFirstVisibleEntry, entriesSelectors.selectLastVisibleEntry, - targetSelectors.selectTarget, + logPositionSelectors.selectTargetPosition, (firstVisibleEntry, lastVisibleEntry, target) => { if (firstVisibleEntry && lastVisibleEntry) { return (firstVisibleEntry.key.time + lastVisibleEntry.key.time) / 2; @@ -125,8 +125,10 @@ export const sharedSelectors = { return firstVisibleEntry.key.time; } else if (lastVisibleEntry) { return lastVisibleEntry.key.time; - } else { + } else if (target) { return target.time; + } else { + return null; } } ), diff --git a/x-pack/plugins/infra/public/containers/logging_legacy/state/target/actions.ts b/x-pack/plugins/infra/public/containers/logging_legacy/state/target/actions.ts deleted file mode 100644 index 203c56984a00f..0000000000000 --- a/x-pack/plugins/infra/public/containers/logging_legacy/state/target/actions.ts +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import actionCreatorFactory from 'typescript-fsa'; - -import { LogEntryTime } from '../../../../../common/log_entry'; - -const actionCreator = actionCreatorFactory('kibana/logging/target'); - -export const jumpToTarget = actionCreator('JUMP_TO_TARGET'); - -export const jumpToTime = (time: number) => - jumpToTarget({ - tiebreaker: 0, - time, - }); diff --git a/x-pack/plugins/infra/public/containers/logging_legacy/state/target/reducer.ts b/x-pack/plugins/infra/public/containers/logging_legacy/state/target/reducer.ts deleted file mode 100644 index 75d4900f3d675..0000000000000 --- a/x-pack/plugins/infra/public/containers/logging_legacy/state/target/reducer.ts +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { reducerWithInitialState } from 'typescript-fsa-reducers'; - -import { LogEntryTime } from '../../../../../common/log_entry'; -import { jumpToTarget } from './actions'; - -export type TargetState = LogEntryTime; - -export const initialTargetState: TargetState = { - tiebreaker: 0, - time: 0, -}; - -export const targetReducer = reducerWithInitialState(initialTargetState).case( - jumpToTarget, - (state, target) => target -); diff --git a/x-pack/plugins/infra/public/containers/logging_legacy/with_log_search_controls_props.ts b/x-pack/plugins/infra/public/containers/logging_legacy/with_log_search_controls_props.ts index 52b9962ce41de..094239aa57a1a 100644 --- a/x-pack/plugins/infra/public/containers/logging_legacy/with_log_search_controls_props.ts +++ b/x-pack/plugins/infra/public/containers/logging_legacy/with_log_search_controls_props.ts @@ -17,8 +17,8 @@ import { // searchActions, // searchResultsSelectors, // sharedSelectors, + logPositionActions, State, - targetActions, } from './state'; export const withLogSearchControlsProps = connect( @@ -29,7 +29,7 @@ export const withLogSearchControlsProps = connect( }), bindPlainActionCreators({ // clearSearch: searchActions.clearSearch, - jumpToTarget: targetActions.jumpToTarget, + jumpToTarget: logPositionActions.jumpToTargetPosition, // search: searchActions.search, }) ); diff --git a/x-pack/plugins/infra/public/containers/logging_legacy/with_stream_items.ts b/x-pack/plugins/infra/public/containers/logging_legacy/with_stream_items.ts index 9ef8624314590..77cebd9033cc0 100644 --- a/x-pack/plugins/infra/public/containers/logging_legacy/with_stream_items.ts +++ b/x-pack/plugins/infra/public/containers/logging_legacy/with_stream_items.ts @@ -12,9 +12,9 @@ import { entriesActions, entriesSelectors, // searchResultsSelectors, + logPositionActions, + logPositionSelectors, State, - targetActions, - targetSelectors, } from '../../containers/logging_legacy/state'; import { LogEntry, LogEntryMessageSegment } from '../../utils/log_entry'; import { asChildFunctionRenderer } from '../../utils/typed_react'; @@ -22,13 +22,17 @@ import { bindPlainActionCreators } from '../../utils/typed_redux'; export const withStreamItems = connect( (state: State) => ({ - endLoadingState: entriesSelectors.selectEntriesEndLoadingState(state), + isReloading: entriesSelectors.selectIsReloadingEntries(state), + isLoadingMore: entriesSelectors.selectIsLoadingMoreEntries(state), + hasMoreBeforeStart: entriesSelectors.selectHasMoreBeforeStart(state), + hasMoreAfterEnd: entriesSelectors.selectHasMoreAfterEnd(state), + isStreaming: logPositionSelectors.selectIsAutoReloading(state), + lastLoadedTime: entriesSelectors.selectEntriesLastLoadedTime(state), items: selectItems(state), - startLoadingState: entriesSelectors.selectEntriesStartLoadingState(state), - target: targetSelectors.selectTarget(state), + target: logPositionSelectors.selectTargetPosition(state), }), bindPlainActionCreators({ - jumpToTarget: targetActions.jumpToTarget, + jumpToTarget: logPositionActions.jumpToTargetPosition, reportVisibleInterval: entriesActions.reportVisibleEntries, }) ); @@ -38,9 +42,10 @@ export const WithStreamItems = asChildFunctionRenderer(withStreamItems); const selectItems = createSelector( entriesSelectors.selectEntries, entriesSelectors.selectIsReloadingEntries, + logPositionSelectors.selectIsAutoReloading, // searchResultsSelectors.selectSearchResultsById, - (logEntries, isReloading /*, searchResults*/) => - isReloading + (logEntries, isReloading, isAutoReloading /*, searchResults*/) => + isReloading && !isAutoReloading ? [] : logEntries.map(logEntry => createLogEntryStreamItem(logEntry /*, searchResults[logEntry.gid] || null*/) diff --git a/x-pack/plugins/infra/public/containers/logging_legacy/with_text_stream_position.ts b/x-pack/plugins/infra/public/containers/logging_legacy/with_text_stream_position.ts index 3ad3608d9e142..200c7c1e61656 100644 --- a/x-pack/plugins/infra/public/containers/logging_legacy/with_text_stream_position.ts +++ b/x-pack/plugins/infra/public/containers/logging_legacy/with_text_stream_position.ts @@ -10,7 +10,13 @@ import { createSelector } from 'reselect'; import { getLogEntryKey } from '../../utils/log_entry'; import { asChildFunctionRenderer } from '../../utils/typed_react'; import { bindPlainActionCreators } from '../../utils/typed_redux'; -import { entriesActions, entriesSelectors, sharedSelectors, State, targetActions } from './state'; +import { + entriesActions, + entriesSelectors, + logPositionActions, + sharedSelectors, + State, +} from './state'; export const withTextStreamPosition = connect( (state: State) => ({ @@ -20,7 +26,7 @@ export const withTextStreamPosition = connect( visibleMidpoint: sharedSelectors.selectVisibleMidpointOrTargetTime(state), }), bindPlainActionCreators({ - jumpToPosition: targetActions.jumpToTarget, + jumpToPosition: logPositionActions.jumpToTargetPosition, reportVisibleInterval: entriesActions.reportVisibleEntries, }) ); diff --git a/x-pack/plugins/infra/public/containers/logging_legacy/with_time_controls_props.ts b/x-pack/plugins/infra/public/containers/logging_legacy/with_time_controls_props.ts index 794b8da969971..a6ebf04b23570 100644 --- a/x-pack/plugins/infra/public/containers/logging_legacy/with_time_controls_props.ts +++ b/x-pack/plugins/infra/public/containers/logging_legacy/with_time_controls_props.ts @@ -6,22 +6,19 @@ import { connect } from 'react-redux'; -import { isIntervalLoadingPolicy } from '../../utils/loading_state'; import { asChildFunctionRenderer } from '../../utils/typed_react'; import { bindPlainActionCreators } from '../../utils/typed_redux'; -import { entriesActions, entriesSelectors, sharedSelectors, State, targetActions } from './state'; +import { logPositionActions, logPositionSelectors, sharedSelectors, State } from './state'; export const withTimeControls = connect( (state: State) => ({ currentTime: sharedSelectors.selectVisibleMidpointOrTargetTime(state), - isLiveStreaming: isIntervalLoadingPolicy( - entriesSelectors.selectEntriesEndLoadingState(state).policy - ), + isLiveStreaming: logPositionSelectors.selectIsAutoReloading(state), }), bindPlainActionCreators({ - disableLiveStreaming: entriesActions.stopLiveStreaming, - enableLiveStreaming: entriesActions.startLiveStreaming, - jumpToTime: targetActions.jumpToTime, + startLiveStreaming: logPositionActions.startAutoReload, + stopLiveStreaming: logPositionActions.stopAutoReload, + jumpToTargetPositionTime: logPositionActions.jumpToTargetPositionTime, }) ); diff --git a/x-pack/plugins/infra/public/pages/logs/logs.tsx b/x-pack/plugins/infra/public/pages/logs/logs.tsx index d86c5d9322620..db3444b3dac33 100644 --- a/x-pack/plugins/infra/public/pages/logs/logs.tsx +++ b/x-pack/plugins/infra/public/pages/logs/logs.tsx @@ -30,7 +30,7 @@ import { LogTextWrapControls } from '../../components/logging/log_text_wrap_cont import { LogTimeControls } from '../../components/logging/log_time_controls'; import { withLibs } from '../../containers/libs'; -import { State, targetActions } from '../../containers/logging_legacy/state'; +import { logPositionActions, State } from '../../containers/logging_legacy/state'; // import { withLogSearchControlsProps } from '../../containers/logging_legacy/with_log_search_controls_props'; import { WithStreamItems } from '../../containers/logging_legacy/with_stream_items'; import { WithSummary } from '../../containers/logging_legacy/with_summary'; @@ -79,7 +79,7 @@ export const LogsPage = withLibs( public componentDidMount() { this.state.store.dispatch( - targetActions.jumpToTarget({ + logPositionActions.jumpToTargetPosition({ time: Date.now(), tiebreaker: 0, }) @@ -125,7 +125,21 @@ export const LogsPage = withLibs( - {timeProps => } + {({ + currentTime, + isLiveStreaming, + jumpToTargetPositionTime, + startLiveStreaming, + stopLiveStreaming, + }) => ( + + )} diff --git a/x-pack/plugins/infra/public/pages/logs/store.ts b/x-pack/plugins/infra/public/pages/logs/store.ts index fc1ee68828dc7..55e9bc730cfc2 100644 --- a/x-pack/plugins/infra/public/pages/logs/store.ts +++ b/x-pack/plugins/infra/public/pages/logs/store.ts @@ -13,9 +13,10 @@ import { createRootEpic, entriesSelectors, initialState, - reducer, + logPositionSelectors, // searchSelectors, // sourceSelectors, + reducer, State, // summarySelectors, // targetSelectors, @@ -44,6 +45,7 @@ export function createStore({ apolloClient, observableApi }: StoreDependencies) selectEntriesStart: entriesSelectors.selectEntriesStart, selectHasMoreAfterEnd: entriesSelectors.selectHasMoreAfterEnd, selectHasMoreBeforeStart: entriesSelectors.selectHasMoreBeforeStart, + selectIsAutoReloading: logPositionSelectors.selectIsAutoReloading, // selectEntriesEndLoadingState: entriesSelectors.selectEntriesEndLoadingState, // selectEntriesStartLoadingState: entriesSelectors.selectEntriesStartLoadingState, // selectFirstEntry: entriesSelectors.selectFirstEntry, diff --git a/x-pack/plugins/infra/public/utils/remote_state/remote_graphql_state.ts b/x-pack/plugins/infra/public/utils/remote_state/remote_graphql_state.ts index 8af643bbcb2fb..b550c332111a2 100644 --- a/x-pack/plugins/infra/public/utils/remote_state/remote_graphql_state.ts +++ b/x-pack/plugins/infra/public/utils/remote_state/remote_graphql_state.ts @@ -175,6 +175,10 @@ export const createGraphqlStateSelectors = ( selectLoadingResult, result => (!isUninitializedLoadingResult(result) ? result.parameters : null) ); + const selectLoadingResultTime = createSelector( + selectLoadingResult, + result => (!isUninitializedLoadingResult(result) ? result.time : null) + ); const selectIsUninitialized = createSelector(selectLoadingResult, isUninitializedLoadingResult); const selectIsSuccess = createSelector(selectLoadingResult, isSuccessLoadingResult); const selectIsFailure = createSelector(selectLoadingResult, isFailureLoadingResult); @@ -202,6 +206,7 @@ export const createGraphqlStateSelectors = ( selectLoadingProgressOperationInfo, selectLoadingResult, selectLoadingResultOperationInfo, + selectLoadingResultTime, selectLoadingState, }; };