aboutsummaryrefslogtreecommitdiffstats
path: root/web
diff options
context:
space:
mode:
Diffstat (limited to 'web')
-rw-r--r--web/src/js/components/flowtable-columns.js14
-rw-r--r--web/src/js/components/flowtable.js72
-rw-r--r--web/src/js/components/mainview.js4
-rw-r--r--web/src/js/ducks/flows.js37
-rw-r--r--web/src/js/ducks/utils/view.js10
5 files changed, 76 insertions, 61 deletions
diff --git a/web/src/js/components/flowtable-columns.js b/web/src/js/components/flowtable-columns.js
index 1eae6409..799b3f9f 100644
--- a/web/src/js/components/flowtable-columns.js
+++ b/web/src/js/components/flowtable-columns.js
@@ -3,7 +3,7 @@ import {RequestUtils, ResponseUtils} from "../flow/utils.js"
import {formatSize, formatTimeDelta} from "../utils.js"
-function TLSColumn({flow}) {
+export function TLSColumn({flow}) {
let ssl = (flow.request.scheme === "https")
let classes
if (ssl) {
@@ -17,7 +17,7 @@ TLSColumn.Title = ({className = "", ...props}) => <th {...props} className={"col
TLSColumn.sortKeyFun = flow => flow.request.scheme
-function IconColumn({flow}) {
+export function IconColumn({flow}) {
let icon
if (flow.response) {
var contentType = ResponseUtils.getContentType(flow.response)
@@ -49,7 +49,7 @@ function IconColumn({flow}) {
IconColumn.Title = ({className = "", ...props}) => <th {...props} className={"col-icon " + className }></th>
-function PathColumn({flow}) {
+export function PathColumn({flow}) {
return <td className="col-path">
{flow.request.is_replay ? <i className="fa fa-fw fa-repeat pull-right"></i> : null}
{flow.intercepted ? <i className="fa fa-fw fa-pause pull-right"></i> : null}
@@ -61,7 +61,7 @@ PathColumn.Title = ({className = "", ...props}) =>
PathColumn.sortKeyFun = flow => RequestUtils.pretty_url(flow.request)
-function MethodColumn({flow}) {
+export function MethodColumn({flow}) {
return <td className="col-method">{flow.request.method}</td>
}
MethodColumn.Title = ({className = "", ...props}) =>
@@ -69,7 +69,7 @@ MethodColumn.Title = ({className = "", ...props}) =>
MethodColumn.sortKeyFun = flow => flow.request.method
-function StatusColumn({flow}) {
+export function StatusColumn({flow}) {
let status
if (flow.response) {
status = flow.response.status_code
@@ -84,7 +84,7 @@ StatusColumn.Title = ({className = "", ...props}) =>
StatusColumn.sortKeyFun = flow => flow.response ? flow.response.status_code : undefined
-function SizeColumn({flow}) {
+export function SizeColumn({flow}) {
let total = flow.request.contentLength
if (flow.response) {
total += flow.response.contentLength || 0
@@ -104,7 +104,7 @@ SizeColumn.sortKeyFun = flow => {
}
-function TimeColumn({flow}) {
+export function TimeColumn({flow}) {
let time
if (flow.response) {
time = formatTimeDelta(1000 * (flow.response.timestamp_end - flow.request.timestamp_start))
diff --git a/web/src/js/components/flowtable.js b/web/src/js/components/flowtable.js
index d621387c..5a0793ba 100644
--- a/web/src/js/components/flowtable.js
+++ b/web/src/js/components/flowtable.js
@@ -2,13 +2,13 @@ import React from "react";
import ReactDOM from "react-dom";
import {connect} from 'react-redux'
import classNames from "classnames";
-import {reverseString} from "../utils.js";
import _ from "lodash";
import shallowEqual from "shallowequal";
import AutoScroll from "./helpers/AutoScroll";
import {calcVScroll} from "./helpers/VirtualScroll";
import flowtable_columns from "./flowtable-columns.js";
import Filt from "../filt/filt";
+import {setSort} from "../ducks/flows";
FlowRow.propTypes = {
@@ -46,61 +46,38 @@ const FlowRowContainer = connect(
})
)(FlowRow)
-class FlowTableHead extends React.Component {
+function FlowTableHead({setSort, columns, sort}) {
+ const sortColumn = sort.sortColumn;
+ const sortType = sort.sortDesc ? "sort-desc" : "sort-asc";
- static propTypes = {
- setSortKeyFun: React.PropTypes.func.isRequired,
- columns: React.PropTypes.array.isRequired,
- };
-
- constructor(props, context) {
- super(props, context);
- this.state = {sortColumn: undefined, sortDesc: false};
- }
-
- onClick(Column) {
- const hasSort = Column.sortKeyFun;
-
- let sortDesc = this.state.sortDesc;
-
- if (Column === this.state.sortColumn) {
- sortDesc = !sortDesc;
- this.setState({sortDesc});
- } else {
- this.setState({sortColumn: hasSort && Column, sortDesc: false});
- }
-
- let sortKeyFun = Column.sortKeyFun;
- if (sortDesc) {
- sortKeyFun = hasSort && function () {
- const k = Column.sortKeyFun.apply(this, arguments);
- if (_.isString(k)) {
- return reverseString("" + k);
- }
- return -k;
- };
- }
-
- this.props.setSortKeyFun(sortKeyFun);
- }
-
- render() {
- const sortColumn = this.state.sortColumn;
- const sortType = this.state.sortDesc ? "sort-desc" : "sort-asc";
return (
<tr>
- {this.props.columns.map(Column => (
+ {columns.map(Column => (
<Column.Title
key={Column.name}
- onClick={() => this.onClick(Column)}
- className={sortColumn === Column ? sortType : undefined}
+ onClick={() => setSort({sortColumn: Column.name, sortDesc: Column.name != sort.sortColumn ? false : !sort.sortDesc})}
+ className={sortColumn === Column.name ? sortType : undefined}
/>
))}
</tr>
);
- }
}
+FlowTableHead.propTypes = {
+ setSort: React.PropTypes.func.isRequired,
+ sort: React.PropTypes.object.isRequired,
+ columns: React.PropTypes.array.isRequired
+};
+
+const FlowTableHeadContainer = connect(
+ state => ({
+ sort: state.flows.sort
+ }),
+ dispatch => ({
+ setSort: (sort) => dispatch(setSort(sort)),
+ })
+)(FlowTableHead)
+
class FlowTable extends React.Component {
static propTypes = {
@@ -186,9 +163,10 @@ class FlowTable extends React.Component {
<div className="flow-table" onScroll={this.onViewportUpdate}>
<table>
<thead ref="head" style={{ transform }}>
- <FlowTableHead
+ <FlowTableHeadContainer
columns={flowtable_columns}
setSortKeyFun={this.props.setSortKeyFun}
+ setSort={this.props.setSort}
/>
</thead>
<tbody>
@@ -216,7 +194,7 @@ const parseFilter = _.memoize(Filt.parse)
const FlowTableContainer = connect(
state => ({
- flows: state.flows.view,
+ flows: state.flows.view
})
)(FlowTable)
diff --git a/web/src/js/components/mainview.js b/web/src/js/components/mainview.js
index 22895991..5915c9fc 100644
--- a/web/src/js/components/mainview.js
+++ b/web/src/js/components/mainview.js
@@ -23,9 +23,6 @@ var MainView = React.createClass({
this.props.setHighlight(nextProps.location.query[Query.HIGHLIGHT], false)
}
},
- setSortKeyFun: function (sortKeyFun) {
- // FIXME: Move to redux. This requires that sortKeyFun is not a function anymore.
- },
selectFlow: function (flow) {
// TODO: This belongs into redux
if (flow) {
@@ -161,7 +158,6 @@ var MainView = React.createClass({
<div className="main-view">
<FlowTable ref="flowTable"
selectFlow={this.selectFlow}
- setSortKeyFun={this.setSortKeyFun}
selected={this.props.selectedFlow} />
{details}
</div>
diff --git a/web/src/js/ducks/flows.js b/web/src/js/ducks/flows.js
index fdbc42ee..6adde71c 100644
--- a/web/src/js/ducks/flows.js
+++ b/web/src/js/ducks/flows.js
@@ -1,10 +1,13 @@
import makeList from "./utils/list"
import Filt from "../filt/filt"
-import {updateViewFilter, updateViewList} from "./utils/view"
+import {updateViewFilter, updateViewList, updateViewSort} from "./utils/view"
+import {reverseString} from "../utils.js";
+import * as flow_table_columns from "../components/flowtable-columns.js";
export const UPDATE_FLOWS = "UPDATE_FLOWS"
export const SET_FILTER = "SET_FLOW_FILTER"
export const SET_HIGHLIGHT = "SET_FLOW_HIGHLIGHT"
+export const SET_SORT = "SET_FLOW_SORT"
export const SELECT_FLOW = "SELECT_FLOW"
const {
@@ -20,12 +23,28 @@ const defaultState = {
view: [],
filter: undefined,
highlight: undefined,
+ sort: {sortColumn: undefined, sortDesc: false},
}
function makeFilterFn(filter) {
return filter ? Filt.parse(filter) : () => true;
}
+
+function makeSortFn(sort){
+ let column = flow_table_columns[sort.sortColumn];
+ if (!column) return;
+
+ let sortKeyFun = column.sortKeyFun;
+ if (sort.sortDesc) {
+ sortKeyFun = sortKeyFun && function (flow) {
+ const k = column.sortKeyFun(flow);
+ return _.isString(k) ? reverseString("" + k) : -k;
+ };
+ }
+ return sortKeyFun;
+}
+
export default function reducer(state = defaultState, action) {
switch (action.type) {
case UPDATE_FLOWS:
@@ -33,19 +52,25 @@ export default function reducer(state = defaultState, action) {
return {
...state,
all,
- view: updateViewList(state.view, state.all, all, action, makeFilterFn(action.filter))
+ view: updateViewList(state.view, state.all, all, action, makeFilterFn(action.filter), makeSortFn(state.sort))
}
case SET_FILTER:
return {
...state,
filter: action.filter,
- view: updateViewFilter(state.all, makeFilterFn(action.filter))
+ view: updateViewFilter(state.all, makeFilterFn(action.filter), makeSortFn(state.sort))
}
case SET_HIGHLIGHT:
return {
...state,
highlight: action.highlight
}
+ case SET_SORT:
+ return {
+ ...state,
+ sort: action.sort,
+ view: updateViewSort(state.view, makeSortFn(action.sort))
+ }
case SELECT_FLOW:
return {
...state,
@@ -69,6 +94,12 @@ export function setHighlight(highlight) {
highlight
}
}
+export function setSort(sort){
+ return {
+ type: SET_SORT,
+ sort
+ }
+}
export function selectFlow(flowId) {
return {
type: SELECT_FLOW,
diff --git a/web/src/js/ducks/utils/view.js b/web/src/js/ducks/utils/view.js
index fa23efcd..2d23a39c 100644
--- a/web/src/js/ducks/utils/view.js
+++ b/web/src/js/ducks/utils/view.js
@@ -122,3 +122,13 @@ export function updateViewFilter(list, filterFn = defaultFilterFn, sortFn = defa
return filtered
}
+
+export function updateViewSort(list, sortFn = defaultSortFn) {
+ let sorted = list.slice(0)
+ if (sortFn) {
+ sorted.sort(makeCompareFn(sortFn))
+ }
+ sorted.indexOf = x => sortedIndexOf(sorted, x, sortFn)
+
+ return sorted
+}