import reduceView, * as viewActions from './utils/view' import * as flowActions from './flows' import Filt from '../filt/filt' import { RequestUtils } from '../flow/utils' export const UPDATE_FILTER = 'FLOWVIEW_UPDATE_FILTER' export const UPDATE_SORT = 'FLOWVIEW_UPDATE_SORT' export const UPDATE_HIGHLIGHT = 'FLOWVIEW_UPDATE_HIGHLIGHT' const sortKeyFuns = { TLSColumn: flow => flow.request.scheme, PathColumn: flow => RequestUtils.pretty_url(flow.request), MethodColumn: flow => flow.request.method, StatusColumn: flow => flow.response && flow.response.status_code, TimeColumn: flow => flow.response && flow.response.timestamp_end - flow.request.timestamp_start, SizeColumn: flow => { let total = flow.request.contentLength if (flow.response) { total += flow.response.contentLength || 0 } return total }, } export function makeFilter(filter) { if (!filter) { return } return Filt.parse(filter) } export function makeSort({ column, desc }) { const sortKeyFun = sortKeyFuns[column] if (!sortKeyFun) { return } return (a, b) => { const ka = sortKeyFun(a) const kb = sortKeyFun(b) if (ka > kb) { return desc ? -1 : 1 } if (ka < kb) { return desc ? 1 : -1 } return 0 } } const defaultState = { highlight: null, filter: null, sort: { column: null, desc: false }, ...reduceView(undefined, {}) } export default function reduce(state = defaultState, action) { switch (action.type) { case UPDATE_HIGHLIGHT: return { ...state, highlight: action.highlight, } case UPDATE_FILTER: return { ...reduceView( state, viewActions.updateFilter( action.flows, makeFilter(action.filter), makeSort(state.sort) ) ), filter: action.filter, } case UPDATE_SORT: const sort = { column: action.column, desc: action.desc } return { ...reduceView( state, viewActions.updateSort( makeSort(sort) ) ), sort, } case flowActions.ADD: return { ...reduceView( state, viewActions.add( action.item, makeFilter(state.filter), makeSort(state.sort) ) ), } case flowActions.UPDATE: return { ...reduceView( state, viewActions.update( action.item, makeFilter(state.filter), makeSort(state.sort) ) ), } case flowActions.REMOVE: return { ...reduceView( state, viewActions.remove( action.id ) ), } case flowActions.RECEIVE: return { ...reduceView( state, viewActions.receive( action.list, makeFilter(state.filter), makeSort(state.sort) ) ), } default: return { ...reduceView(state, action), } } } /** * @public */ export function updateFilter(filter) { return (dispatch, getState) => { dispatch({ type: UPDATE_FILTER, filter, flows: getState().flows.data }) } } /** * @public */ export function updateHighlight(highlight) { return { type: UPDATE_HIGHLIGHT, highlight } } /** * @public */ export function updateSort(column, desc) { return { type: UPDATE_SORT, column, desc } } /** * @public */ export function selectRelative(shift) { return (dispatch, getState) => { let currentSelectionIndex = getState().flowView.indexOf[getState().flows.selected[0]] let minIndex = 0 let maxIndex = getState().flowView.data.length - 1 let newIndex if (currentSelectionIndex === undefined) { newIndex = (shift < 0) ? minIndex : maxIndex } else { newIndex = currentSelectionIndex + shift newIndex = Math.max(newIndex, minIndex) newIndex = Math.min(newIndex, maxIndex) } let flow = getState().flowView.data[newIndex] dispatch(flowActions.select(flow ? flow.id : undefined)) } }