Skip to content

Commit

Permalink
redux: moved fetched rows under store.watches.data[watchIndex] (#6)
Browse files Browse the repository at this point in the history
  • Loading branch information
mgurov authored Jul 15, 2018
1 parent f6e4acf commit 8e16c01
Show file tree
Hide file tree
Showing 13 changed files with 99 additions and 105 deletions.
3 changes: 2 additions & 1 deletion src/components/captor/EditCaptorsPopup.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import * as FormHelper from '../generic/FormHelper'
import { connect } from 'react-redux'
import { removeCaptor } from '../../actions'
import {captorKeyToView} from '../../domain/Captor'
import {selectedData} from '../../state/data'


const mapStateToProps = state => {
Expand All @@ -13,7 +14,7 @@ const mapStateToProps = state => {
return {
watchIndex,
captors,
timeline: state.data.timeline,
timeline: selectedData(state).timeline,
}
}

Expand Down
4 changes: 3 additions & 1 deletion src/components/datalist/FilterLikeThisView.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ import FilterLikethisForm from '../captor/FilterLikeThisForm'

import DataList from './DataList'

import {selectedData} from '../../state/data'

const mapStateToProps = state => {
return {
filterLikeThis: state.data.timeline.filterLikeThis,
filterLikeThis: selectedData(state).timeline.filterLikeThis,
}
}

Expand Down
6 changes: 4 additions & 2 deletions src/components/datalist/HitsTimeline.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@ import EditCaptorsButton from '../captor/EditCaptorsButton'
import {viewToCaptorKey} from '../../domain/Captor'
import FilterLikeThisView from './FilterLikeThisView'
import DataList from './DataList'
import {selectedData} from '../../state/data'

const mapStateToProps = (state) => {
let watchIndex = state.view.watchIndex
let data = selectedData(state, true)
return {
timeline: state.data.timeline,
hitIds: state.data.hits.ids,
timeline: data.timeline,
hitIds: data.hits.ids,
view: state.view.key,
viewProps: state.view,
error: state.fetchStatus.error,
Expand Down
3 changes: 2 additions & 1 deletion src/components/title/DocumentTitleContainer.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { connect } from 'react-redux'
import DocumentTitle from './DocumentTitle'
import _ from 'lodash'
import {selectedData} from '../../state/data'

const mapStateToProps = state => {
let titleArray = []

let pendingCount = (state.data.timeline.pending || []).length
let pendingCount = (selectedData(state, true).timeline.pending || []).length
if (pendingCount > 0) {
titleArray.push('' + pendingCount)
}
Expand Down
33 changes: 0 additions & 33 deletions src/reducers/captorPredicatesUpdater.js

This file was deleted.

31 changes: 0 additions & 31 deletions src/reducers/captorPredicatesUpdater.test.js

This file was deleted.

19 changes: 12 additions & 7 deletions src/reducers/data.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import _ from 'lodash'
import LogHit from '../domain/LogHit'
import update from 'immutability-helper';
import * as constant from '../constant'
import {matchPredicates, captorKeyToView} from '../domain/Captor'
import {matchPredicates, captorKeyToView, captorToPredicate} from '../domain/Captor'

export const emptyState = {
hits: {
Expand All @@ -12,24 +12,29 @@ export const emptyState = {
},
timeline: {},
acked: {}, // id -> true
captorPredicates: [], //hackishly copied here upon config update. see captorPredicatesUpdater
draftFilter: null, // editing filter
}

const data = (state = emptyState, action) => {
const data = (state = emptyState, action, filters) => {
switch (action.type) {
case 'RESET_DATA': //reset all
return { ...emptyState,
captorPredicates: state.captorPredicates
}
return emptyState
case 'NEW_IDS_ARRIVED' : {
let captorPredicates = _.flatMap(filters, c => {
try {
return [captorToPredicate(c)]
} catch (e) {
console.error('error making predicate from captor', c, e)
return []
}
})
return update(state, {
hits: {
newIds: {
$set: []
},
},
timeline: {$set: reprocessTimeline(state)},
timeline: {$set: reprocessTimeline({...state, captorPredicates})},
})
}
case 'INCOMING_HITS':
Expand Down
4 changes: 1 addition & 3 deletions src/reducers/data.newhitstimeline.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import dataReducer, {
emptyState,
import {
reprocessTimeline
} from './data'
import LogHit from '../domain/LogHit'
Expand All @@ -9,7 +8,6 @@ import {
messageExtractor,
captorToPredicate
} from '../domain/Captor'
import * as constant from '../constant'

const testConfig = {
timeField: 'timestamp',
Expand Down
19 changes: 2 additions & 17 deletions src/reducers/data.reducer.test.js
Original file line number Diff line number Diff line change
@@ -1,32 +1,17 @@
import dataReducer, { emptyState } from './data'
import _ from 'lodash'
import LogHit from '../domain/LogHit'
import {messageContainsCaptor, captorToPredicate, messageMatchesRegexCaptor, messageExtractor, keepPending } from '../domain/Captor'
import {captureConsoleError} from '../testutil/funmock'

const testConfig = {
timeField: 'timestamp',
messageField: 'message'
}

const toLogHit = (h) => LogHit(h, testConfig)

const captorForMessage = (key, messageSub) => captorToPredicate(messageContainsCaptor(key, messageSub))

describe('data reducer', () => {
it('intial state is empty state', () => {
expect(dataReducer(undefined, {}))
.toEqual(emptyState)
})
it('resets back to empty state, except for the captors hack', () => {
it('resets back to empty state', () => {
expect(dataReducer({
data: { hits: [1, 2, 3] },
captorPredicates: ['a', 'b', 'c']
}, { type: 'RESET_DATA' }))
.toEqual({
...emptyState,
captorPredicates: ['a', 'b', 'c'],
})
.toEqual(emptyState)
})

it('shall ack all', () => {
Expand Down
20 changes: 12 additions & 8 deletions src/reducers/index.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,28 @@
import { combineReducers} from 'redux'
import data from './data'
import watches from './watches'
import synctimes from './synctimes'
import config from './config'
import versions from './versions'
import fetchStatus from './fetchStatus'
import captorPredicatesUpdater from './captorPredicatesUpdater'
import view from './view'
import _ from 'lodash'

const combinedReducers = combineReducers({
data,
const combinedReducers = combineReducersWithState({
view,
watches,
fetchStatus,
synctimes,
config,
versions,
view,
})

function kibanatorApp(state, action) {
const intermediateState = combinedReducers(state, action);
return captorPredicatesUpdater(intermediateState, action)
return combinedReducers(state, action);
}

function combineReducersWithState(combination) {
return (state, action) => {
return _.mapValues(combination, (reducer, key)=> reducer(state[key], action, state))
}
}

export default kibanatorApp
39 changes: 39 additions & 0 deletions src/reducers/watches.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import data from './data'
import _ from 'lodash'

const startingState = {
data: {}
}

export default function watches (state = startingState, action, fullState) {

if (action.type === 'RESET_DATA') {
return startingState
}

//delegate the rest to the specific data reducer if watchIndex present
let watchIndex = _.get(action, 'payload.watchIndex')

if (undefined === watchIndex) {
watchIndex = _.get(fullState, 'view.watchIndex')
}

if (undefined === watchIndex) {
return startingState
}

watchIndex = "" + watchIndex //stringify index

let filters = _.get(fullState.config.watches[watchIndex], 'captors')

let updatedData = data(state.data[watchIndex], action, filters)

if (undefined === updatedData) {
console.warn('unexpectedly undefined data for watch index', watchIndex)
}

return {...state, data: {
...state.data,
[watchIndex]: updatedData
}}
}
15 changes: 15 additions & 0 deletions src/state/data.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import {emptyState} from '../reducers/data'
export function selectedData(state, fallbackEmptyState) {
const watchIndex = state.view.watchIndex
if (undefined !== watchIndex) {
let theData = state.watches.data[watchIndex + ""]
if (undefined !== theData) {
return theData
}
}
if (fallbackEmptyState) {
return emptyState
} else {
return undefined
}
}
8 changes: 7 additions & 1 deletion src/store.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
import thunkMiddleware from 'redux-thunk'
import {readConfigFromLocalStore, writeConfigToLocalStore} from './reducers/config'
//import { createLogger } from 'redux-logger'
import {selectedData} from './state/data'

import kibanatorApp from './reducers'

Expand Down Expand Up @@ -35,7 +36,12 @@ const onNewHitsArrivedMiddleware = store => {
}

let state = store.getState();
const newIds = state.data.hits.newIds
let data = selectedData(state, false)
if (data === undefined) {
console.warn('no selected data to propagate incoming hits')
return r
}
const newIds = data.hits.newIds

if (newIds && newIds.length > 0) {
store.dispatch({
Expand Down

0 comments on commit 8e16c01

Please sign in to comment.