diff options
Diffstat (limited to 'web/src/js/ducks/flows.js')
| -rw-r--r-- | web/src/js/ducks/flows.js | 142 | 
1 files changed, 114 insertions, 28 deletions
| diff --git a/web/src/js/ducks/flows.js b/web/src/js/ducks/flows.js index 519b5e7d..3375e4bd 100644 --- a/web/src/js/ducks/flows.js +++ b/web/src/js/ducks/flows.js @@ -1,47 +1,58 @@ -import { fetchApi } from '../utils' -import reduceList, * as listActions from './utils/list' -import { selectRelative } from './flowView' - -export const ADD = 'FLOWS_ADD' -export const UPDATE = 'FLOWS_UPDATE' -export const REMOVE = 'FLOWS_REMOVE' -export const RECEIVE = 'FLOWS_RECEIVE' +import { fetchApi } from "../utils" +import reduceStore from "./utils/store" +import * as storeActions from "./utils/store" +import Filt from "../filt/filt" +import { RequestUtils } from "../flow/utils" + +export const ADD            = 'FLOWS_ADD' +export const UPDATE         = 'FLOWS_UPDATE' +export const REMOVE         = 'FLOWS_REMOVE' +export const RECEIVE        = 'FLOWS_RECEIVE' +export const SELECT         = 'FLOWS_SELECT' +export const SET_FILTER     = 'FLOWS_SET_FILTER' +export const SET_SORT       = 'FLOWS_SET_SORT' +export const SET_HIGHLIGHT  = 'FLOWS_SET_HIGHLIGHT'  export const REQUEST_ACTION = 'FLOWS_REQUEST_ACTION' -export const UNKNOWN_CMD = 'FLOWS_UNKNOWN_CMD' -export const FETCH_ERROR = 'FLOWS_FETCH_ERROR' -export const SELECT = 'FLOWS_SELECT'  const defaultState = { +    highlight: null, +    filter: null, +    sort: { column: null, desc: false },      selected: [], -    ...reduceList(undefined, {}), +    ...reduceStore(undefined, {})  }  export default function reduce(state = defaultState, action) {      switch (action.type) {          case ADD: -            return { -                ...state, -                ...reduceList(state, listActions.add(action.item)), -            } -          case UPDATE: +        case REMOVE: +        case RECEIVE: +            // FIXME: Implement select switch for remove +            let storeAction = storeActions[action.cmd]( +                action.data, +                makeFilter(state.filter), +                makeSort(state.sort) +            )              return {                  ...state, -                ...reduceList(state, listActions.update(action.item)), +                ...reduceStore(state, storeAction)              } -        case REMOVE: +        case SET_FILTER:              return {                  ...state, -                ...reduceList(state, listActions.remove(action.id)), +                filter: action.filter, +                ...reduceStore(state, storeActions.setFilter(makeFilter(action.filter), makeSort(state.sort)))              } -        case RECEIVE: +        case SET_SORT:              return {                  ...state, -                ...reduceList(state, listActions.receive(action.flows)), +                sort: action.sort, +                ...reduceStore(state, storeActions.setSort(makeSort(action.sort)))              }          case SELECT: @@ -51,13 +62,88 @@ export default function reduce(state = defaultState, action) {              }          default: -            return { -                ...state, -                ...reduceList(state, action), -            } +            return state      }  } + +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 +    } +} + +export function setFilter(filter) { +    return { type: SET_FILTER, filter } +} + +export function setHighlight(highlight) { +    return { type: SET_HIGHLIGHT, highlight } +} + +export function setSort(column, desc) { +    return { type: SET_SORT, sort: { column, desc } } +} + +export function selectRelative(shift) { +    return (dispatch, getState) => { +        let currentSelectionIndex = getState().flows.viewIndex[getState().flows.selected[0]] +        let minIndex              = 0 +        let maxIndex              = getState().flows.view.length - 1 +        let newIndex +        if (currentSelectionIndex === undefined) { +            newIndex = (shift < 0) ? minIndex : maxIndex +        } else { +            newIndex = currentSelectionIndex + shift +            newIndex = window.Math.max(newIndex, minIndex) +            newIndex = window.Math.min(newIndex, maxIndex) +        } +        let flow = getState().flows.view[newIndex] +        dispatch(select(flow ? flow.id : undefined)) +    } +} + +  export function accept(flow) {      return dispatch => fetchApi(`/flows/${flow.id}/accept`, { method: 'POST' })  } @@ -88,9 +174,9 @@ export function update(flow, data) {  export function uploadContent(flow, file, type) {      const body = new FormData() -    file = new Blob([file], {type: 'plain/text'}) +    file       = new window.Blob([file], { type: 'plain/text' })      body.append('file', file) -    return dispatch => fetchApi(`/flows/${flow.id}/${type}/content`, {method: 'post',  body} ) +    return dispatch => fetchApi(`/flows/${flow.id}/${type}/content`, { method: 'post', body })  } | 
