aboutsummaryrefslogtreecommitdiffstats
path: root/web/src
diff options
context:
space:
mode:
authorMaximilian Hils <git@maximilianhils.com>2016-06-15 13:40:03 -0700
committerMaximilian Hils <git@maximilianhils.com>2016-06-15 13:40:03 -0700
commitc7a891b652f4f85877c4dc8ee04fcd45d9e20a74 (patch)
treef80bdafc25555b459bd618ff20273b6b8eddc627 /web/src
parent7de5d7b2984db3c835d3ef2ec3f81ba26a4e458a (diff)
parent94e2929b3fd6dc335d1c787167956df18f05494e (diff)
downloadmitmproxy-c7a891b652f4f85877c4dc8ee04fcd45d9e20a74.tar.gz
mitmproxy-c7a891b652f4f85877c4dc8ee04fcd45d9e20a74.tar.bz2
mitmproxy-c7a891b652f4f85877c4dc8ee04fcd45d9e20a74.zip
Merge branch 'add_flow_to_options'
Diffstat (limited to 'web/src')
-rw-r--r--web/src/js/components/Header.js42
-rw-r--r--web/src/js/components/Header/FlowMenu.jsx32
-rw-r--r--web/src/js/components/MainView.jsx1
-rw-r--r--web/src/js/components/common.js12
-rw-r--r--web/src/js/ducks/flows.js9
-rw-r--r--web/src/js/ducks/index.js4
-rw-r--r--web/src/js/ducks/ui.js42
-rw-r--r--web/src/js/ducks/utils/view.js2
8 files changed, 123 insertions, 21 deletions
diff --git a/web/src/js/components/Header.js b/web/src/js/components/Header.js
index 7134f7d9..8aaa6411 100644
--- a/web/src/js/components/Header.js
+++ b/web/src/js/components/Header.js
@@ -1,42 +1,46 @@
import React, { Component, PropTypes } from 'react'
+import { connect } from 'react-redux'
+import { bindActionCreators } from 'redux'
import classnames from 'classnames'
import { toggleEventLogVisibility } from '../ducks/eventLog'
import MainMenu from './Header/MainMenu'
import ViewMenu from './Header/ViewMenu'
import OptionMenu from './Header/OptionMenu'
import FileMenu from './Header/FileMenu'
+import FlowMenu from './Header/FlowMenu'
+import {setActiveMenu} from '../ducks/ui.js'
-export default class Header extends Component {
-
+class Header extends Component {
static entries = [MainMenu, ViewMenu, OptionMenu]
static propTypes = {
settings: PropTypes.object.isRequired,
}
- constructor(props, context) {
- super(props, context)
- this.state = { active: Header.entries[0] }
- }
-
handleClick(active, e) {
e.preventDefault()
- this.props.updateLocation(active.route)
- this.setState({ active })
+ this.props.setActiveMenu(active.title)
+ // this.props.updateLocation(active.route)
+ // this.setState({ active })
}
render() {
- const { active: Active } = this.state
- const { settings, updateLocation, query } = this.props
+ const { settings, updateLocation, query, selectedFlow, activeMenu} = this.props
+
+ let entries = [...Header.entries]
+ if(selectedFlow)
+ entries.push(FlowMenu)
+
+ const Active = _.find(entries, (e) => e.title == activeMenu)
return (
<header>
<nav className="nav-tabs nav-tabs-lg">
<FileMenu/>
- {Header.entries.map(Entry => (
+ {entries.map(Entry => (
<a key={Entry.title}
href="#"
- className={classnames({ active: Entry === Active })}
+ className={classnames({ active: Entry === Active})}
onClick={e => this.handleClick(Entry, e)}>
{Entry.title}
</a>
@@ -44,13 +48,21 @@ export default class Header extends Component {
</nav>
<div className="menu">
<Active
- ref="active"
settings={settings}
updateLocation={updateLocation}
query={query}
- />
+ />
</div>
</header>
)
}
}
+export default connect(
+ (state) => ({
+ selectedFlow: state.flows.selected[0],
+ activeMenu: state.ui.activeMenu
+ }),
+ dispatch => bindActionCreators({
+ setActiveMenu,
+ }, dispatch)
+)(Header)
diff --git a/web/src/js/components/Header/FlowMenu.jsx b/web/src/js/components/Header/FlowMenu.jsx
new file mode 100644
index 00000000..4a43f40f
--- /dev/null
+++ b/web/src/js/components/Header/FlowMenu.jsx
@@ -0,0 +1,32 @@
+import React, { PropTypes } from 'react'
+import { Button } from '../common.js'
+import {FlowActions} from "../../actions.js";
+import {MessageUtils} from "../../flow/utils.js";
+import { connect } from 'react-redux'
+
+FlowMenu.title = "Flow"
+
+FlowMenu.propTypes = {
+ flow: PropTypes.object.isRequired,
+}
+
+function FlowMenu({ flow }) {
+
+ return (
+ <div>
+ <div className="menu-row">
+ <Button disabled title="[r]eplay flow" text="Replay" icon="fa-repeat" onClick={FlowActions.replay.bind(null, flow)} />
+ <Button title="[D]uplicate flow" text="Duplicate" icon="fa-copy" onClick={FlowActions.duplicate.bind(null, flow)} />
+ <Button title="[d]elete flow" text="Delete" icon="fa-trash" onClick={FlowActions.delete.bind(null, flow)}/>
+ <Button title="download" text="Download" icon="fa-download" onClick={() => window.location = MessageUtils.getContentURL(flow, flow.response)}/>
+ </div>
+ <div className="clearfix"/>
+ </div>
+ )
+}
+
+export default connect(
+ state => ({
+ flow: state.flows.all.byId[state.flows.selected[0]]
+ })
+)(FlowMenu)
diff --git a/web/src/js/components/MainView.jsx b/web/src/js/components/MainView.jsx
index dbea76e5..eb15af8a 100644
--- a/web/src/js/components/MainView.jsx
+++ b/web/src/js/components/MainView.jsx
@@ -1,7 +1,6 @@
import React, { Component, PropTypes } from 'react'
import { connect } from 'react-redux'
import { bindActionCreators } from 'redux'
-
import { FlowActions } from '../actions.js'
import { Query } from '../actions.js'
import { Key } from '../utils.js'
diff --git a/web/src/js/components/common.js b/web/src/js/components/common.js
index 3496f1de..1497e15d 100644
--- a/web/src/js/components/common.js
+++ b/web/src/js/components/common.js
@@ -121,6 +121,18 @@ ToggleButton.propTypes = {
text: React.PropTypes.string.isRequired
};
+export const Button = ({onClick, text, icon}) =>
+ <div className={"btn btn-default"} onClick={onClick}>
+ <i className={"fa fa-fw " + icon}/>
+ &nbsp;
+ {text}
+ </div>;
+
+Button.propTypes = {
+ onClick: React.PropTypes.func.isRequired,
+ text: React.PropTypes.string.isRequired
+};
+
export class ToggleInputButton extends React.Component {
constructor(props) {
super(props);
diff --git a/web/src/js/ducks/flows.js b/web/src/js/ducks/flows.js
index f7a5538a..b877d3e4 100644
--- a/web/src/js/ducks/flows.js
+++ b/web/src/js/ducks/flows.js
@@ -101,9 +101,12 @@ export function setSort(sort){
}
}
export function selectFlow(flowId) {
- return {
- type: SELECT_FLOW,
- flowId
+ return (dispatch, getState) => {
+ dispatch({
+ type: SELECT_FLOW,
+ currentSelection: getState().flows.selected[0],
+ flowId
+ })
}
}
diff --git a/web/src/js/ducks/index.js b/web/src/js/ducks/index.js
index 6c521a70..fee4d792 100644
--- a/web/src/js/ducks/index.js
+++ b/web/src/js/ducks/index.js
@@ -2,11 +2,13 @@ import {combineReducers} from 'redux'
import eventLog from './eventLog'
import websocket from './websocket'
import flows from './flows'
+import ui from './ui'
const rootReducer = combineReducers({
eventLog,
websocket,
flows,
+ ui
})
-export default rootReducer \ No newline at end of file
+export default rootReducer
diff --git a/web/src/js/ducks/ui.js b/web/src/js/ducks/ui.js
new file mode 100644
index 00000000..28a13ea4
--- /dev/null
+++ b/web/src/js/ducks/ui.js
@@ -0,0 +1,42 @@
+import { SELECT_FLOW } from './flows'
+const SET_ACTIVE_MENU = 'SET_ACTIVE_MENU'
+
+
+const defaultState = {
+ activeMenu: 'Start',
+}
+export default function reducer(state = defaultState, action) {
+ switch (action.type) {
+ case SET_ACTIVE_MENU:
+ return {
+ ...state,
+ activeMenu: action.activeMenu
+ }
+ case SELECT_FLOW:
+ let isNewSelect = (action.flowId && !action.currentSelection)
+ let isDeselect = (!action.flowId && action.currentSelection)
+ if(isNewSelect) {
+ return {
+ ...state,
+ activeMenu: "Flow"
+ }
+ }
+ if(isDeselect && state.activeMenu === "Flow") {
+ return {
+ ...state,
+ activeMenu: "Start"
+ }
+ }
+ return state
+ default:
+ return state
+ }
+}
+
+export function setActiveMenu(activeMenu) {
+ return {
+ type: SET_ACTIVE_MENU,
+ activeMenu
+ }
+}
+
diff --git a/web/src/js/ducks/utils/view.js b/web/src/js/ducks/utils/view.js
index 2d23a39c..01d57b17 100644
--- a/web/src/js/ducks/utils/view.js
+++ b/web/src/js/ducks/utils/view.js
@@ -124,7 +124,7 @@ export function updateViewFilter(list, filterFn = defaultFilterFn, sortFn = defa
}
export function updateViewSort(list, sortFn = defaultSortFn) {
- let sorted = list.slice(0)
+ let sorted = [...list]
if (sortFn) {
sorted.sort(makeCompareFn(sortFn))
}