make columns configurable and customizable
This commit is contained in:
parent
c996f1ee74
commit
1efe44745b
|
@ -137,6 +137,7 @@ def mitmweb(opts):
|
|||
opts.make_parser(group, "web_open_browser")
|
||||
opts.make_parser(group, "web_port", metavar="PORT")
|
||||
opts.make_parser(group, "web_host", metavar="HOST")
|
||||
opts.make_parser(group, "web_columns")
|
||||
|
||||
common_options(parser, opts)
|
||||
group = parser.add_argument_group(
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -1,6 +1,8 @@
|
|||
import webbrowser
|
||||
|
||||
from mitmproxy import ctx
|
||||
from typing import Sequence
|
||||
|
||||
|
||||
|
||||
class WebAddon:
|
||||
|
@ -21,6 +23,10 @@ class WebAddon:
|
|||
"web_host", str, "127.0.0.1",
|
||||
"Web UI host."
|
||||
)
|
||||
loader.add_option(
|
||||
"web_columns", Sequence[str], ["tls", "icon", "path", "method", "status", "size", "time"],
|
||||
"Columns to show in the flow list"
|
||||
)
|
||||
|
||||
def running(self):
|
||||
if hasattr(ctx.options, "web_open_browser") and ctx.options.web_open_browser:
|
||||
|
|
|
@ -125,6 +125,9 @@
|
|||
.col-time {
|
||||
width: 50px;
|
||||
}
|
||||
.col-timestamp {
|
||||
width: auto;
|
||||
}
|
||||
td.col-time, td.col-size {
|
||||
text-align: right;
|
||||
}
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
import React from 'react'
|
||||
import renderer from 'react-test-renderer'
|
||||
import FlowRow from '../../../components/FlowTable/FlowRow'
|
||||
import { TFlow } from '../../ducks/tutils'
|
||||
import { TFlow, TStore } from '../../ducks/tutils'
|
||||
import { Provider } from 'react-redux'
|
||||
|
||||
describe('FlowRow Component', () => {
|
||||
let tFlow = new TFlow(),
|
||||
selectFn = jest.fn(),
|
||||
flowRow = renderer.create(<FlowRow flow={tFlow} onSelect={selectFn}/>),
|
||||
store = TStore(),
|
||||
flowRow = renderer.create(
|
||||
<Provider store={store} >
|
||||
<FlowRow flow={tFlow} onSelect={selectFn}/>
|
||||
</Provider>),
|
||||
tree = flowRow.toJSON()
|
||||
|
||||
it('should render correctly', () => {
|
||||
|
|
|
@ -7,7 +7,11 @@ import { TStore } from '../../ducks/tutils'
|
|||
|
||||
describe('FlowTableHead Component', () => {
|
||||
let sortFn = jest.fn(),
|
||||
flowTableHead = renderer.create(<FlowTableHead setSort={sortFn} sortDesc={true}/>),
|
||||
store = TStore(),
|
||||
flowTableHead = renderer.create(
|
||||
<Provider store={store}>
|
||||
<FlowTableHead setSort={sortFn} sortDesc={true}/>
|
||||
</Provider>),
|
||||
tree =flowTableHead.toJSON()
|
||||
|
||||
it('should render correctly', () => {
|
||||
|
|
|
@ -79,6 +79,12 @@ exports[`FlowTableHead Component should render correctly 1`] = `
|
|||
>
|
||||
Status
|
||||
</th>
|
||||
<th
|
||||
className="col-timestamp"
|
||||
onClick={[Function]}
|
||||
>
|
||||
TimeStamp
|
||||
</th>
|
||||
<th
|
||||
className="col-size"
|
||||
onClick={[Function]}
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
import React, { Component } from 'react'
|
||||
import classnames from 'classnames'
|
||||
import { RequestUtils, ResponseUtils } from '../../flow/utils.js'
|
||||
import { formatSize, formatTimeDelta } from '../../utils.js'
|
||||
import { formatSize, formatTimeDelta, formatTimeStamp } from '../../utils.js'
|
||||
|
||||
export const defaultColumnNames = ["tls", "icon", "path", "method", "status", "size", "time"]
|
||||
|
||||
export function TLSColumn({ flow }) {
|
||||
return (
|
||||
|
@ -148,12 +150,28 @@ export function TimeColumn({ flow }) {
|
|||
TimeColumn.headerClass = 'col-time'
|
||||
TimeColumn.headerName = 'Time'
|
||||
|
||||
export function TimeStampColumn({ flow }) {
|
||||
return (
|
||||
<td className="col-start">
|
||||
{flow.request.timestamp_start ? (
|
||||
formatTimeStamp(flow.request.timestamp_start)
|
||||
) : (
|
||||
'...'
|
||||
)}
|
||||
</td>
|
||||
)
|
||||
}
|
||||
|
||||
TimeStampColumn.headerClass = 'col-timestamp'
|
||||
TimeStampColumn.headerName = 'TimeStamp'
|
||||
|
||||
export default [
|
||||
TLSColumn,
|
||||
IconColumn,
|
||||
PathColumn,
|
||||
MethodColumn,
|
||||
StatusColumn,
|
||||
TimeStampColumn,
|
||||
SizeColumn,
|
||||
TimeColumn,
|
||||
]
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import classnames from 'classnames'
|
||||
import columns from './FlowColumns'
|
||||
import {defaultColumnNames} from './FlowColumns'
|
||||
import { pure } from '../../utils'
|
||||
import {getDisplayColumns} from './FlowTableHead'
|
||||
import { connect } from 'react-redux'
|
||||
|
||||
FlowRow.propTypes = {
|
||||
onSelect: PropTypes.func.isRequired,
|
||||
|
@ -11,7 +13,7 @@ FlowRow.propTypes = {
|
|||
selected: PropTypes.bool,
|
||||
}
|
||||
|
||||
function FlowRow({ flow, selected, highlighted, onSelect }) {
|
||||
function FlowRow({ flow, selected, highlighted, onSelect, displayColumnNames }) {
|
||||
const className = classnames({
|
||||
'selected': selected,
|
||||
'highlighted': highlighted,
|
||||
|
@ -20,13 +22,19 @@ function FlowRow({ flow, selected, highlighted, onSelect }) {
|
|||
'has-response': flow.response,
|
||||
})
|
||||
|
||||
const displayColumns = getDisplayColumns(displayColumnNames)
|
||||
|
||||
return (
|
||||
<tr className={className} onClick={() => onSelect(flow.id)}>
|
||||
{columns.map(Column => (
|
||||
{displayColumns.map(Column => (
|
||||
<Column key={Column.name} flow={flow}/>
|
||||
))}
|
||||
</tr>
|
||||
)
|
||||
}
|
||||
|
||||
export default pure(FlowRow)
|
||||
export default connect(
|
||||
state => ({
|
||||
displayColumnNames: state.options["web_columns"] ? state.options["web_columns"].value : defaultColumnNames,
|
||||
})
|
||||
)(pure(FlowRow))
|
||||
|
|
|
@ -2,7 +2,7 @@ import React from 'react'
|
|||
import PropTypes from 'prop-types'
|
||||
import { connect } from 'react-redux'
|
||||
import classnames from 'classnames'
|
||||
import columns from './FlowColumns'
|
||||
import columns, {defaultColumnNames} from './FlowColumns'
|
||||
|
||||
import { setSort } from '../../ducks/flows'
|
||||
|
||||
|
@ -10,14 +10,30 @@ FlowTableHead.propTypes = {
|
|||
setSort: PropTypes.func.isRequired,
|
||||
sortDesc: PropTypes.bool.isRequired,
|
||||
sortColumn: PropTypes.string,
|
||||
displayColumnNames: PropTypes.array,
|
||||
}
|
||||
|
||||
export function FlowTableHead({ sortColumn, sortDesc, setSort }) {
|
||||
export function getDisplayColumns(displayColumnNames) {
|
||||
let displayColumns = []
|
||||
if (typeof displayColumnNames == "undefined") {
|
||||
return columns
|
||||
}
|
||||
for (const column of columns) {
|
||||
if (displayColumnNames.includes(column.name.slice(0,-6).toLowerCase())) {
|
||||
displayColumns.push(column)
|
||||
}
|
||||
}
|
||||
return displayColumns
|
||||
}
|
||||
|
||||
export function FlowTableHead({ sortColumn, sortDesc, setSort, displayColumnNames}) {
|
||||
const sortType = sortDesc ? 'sort-desc' : 'sort-asc'
|
||||
|
||||
const displayColumns = getDisplayColumns(displayColumnNames)
|
||||
|
||||
return (
|
||||
<tr>
|
||||
{columns.map(Column => (
|
||||
{displayColumns.map(Column => (
|
||||
<th className={classnames(Column.headerClass, sortColumn === Column.name && sortType)}
|
||||
key={Column.name}
|
||||
onClick={() => setSort(Column.name, Column.name !== sortColumn ? false : !sortDesc)}>
|
||||
|
@ -32,6 +48,7 @@ export default connect(
|
|||
state => ({
|
||||
sortDesc: state.flows.sort.desc,
|
||||
sortColumn: state.flows.sort.column,
|
||||
displayColumnNames: state.options["web_columns"] ? state.options["web_columns"].value : defaultColumnNames,
|
||||
}),
|
||||
{
|
||||
setSort
|
||||
|
|
Loading…
Reference in New Issue