aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMaximilian Hils <git@maximilianhils.com>2016-12-11 17:37:11 +0100
committerMaximilian Hils <git@maximilianhils.com>2016-12-11 17:37:11 +0100
commit795e76eee298e23079f7e979119defc4c187b833 (patch)
tree64bf62c1c00d5857d57af6e802567d1875aa3bd8
parentb92980efeca831c879c969e673cd60f93d0e3ace (diff)
downloadmitmproxy-795e76eee298e23079f7e979119defc4c187b833.tar.gz
mitmproxy-795e76eee298e23079f7e979119defc4c187b833.tar.bz2
mitmproxy-795e76eee298e23079f7e979119defc4c187b833.zip
[web] style options menu
The other menus are WIP.
-rw-r--r--web/src/css/header.less58
-rw-r--r--web/src/js/components/FlowView/ToggleEdit.jsx4
-rw-r--r--web/src/js/components/Header.jsx7
-rw-r--r--web/src/js/components/Header/FlowMenu.jsx15
-rw-r--r--web/src/js/components/Header/MainMenu.jsx21
-rw-r--r--web/src/js/components/Header/MenuToggle.jsx69
-rw-r--r--web/src/js/components/Header/OptionMenu.jsx112
-rw-r--r--web/src/js/components/Header/ViewMenu.jsx32
-rw-r--r--web/src/js/components/common/DocsLink.jsx14
-rw-r--r--web/src/js/ducks/ui/header.js4
10 files changed, 203 insertions, 133 deletions
diff --git a/web/src/css/header.less b/web/src/css/header.less
index 4813b933..90907ec7 100644
--- a/web/src/css/header.less
+++ b/web/src/css/header.less
@@ -1,24 +1,66 @@
@import (reference) '../../node_modules/bootstrap/less/variables.less';
@import (reference) '../../node_modules/bootstrap/less/mixins/grid.less';
+@menu-height: 85px;
+
+
header {
- padding-top: 0.5em;
+ padding-top: 6px;
background-color: white;
@separator-color: lighten(grey, 15%);
- .menu {
- padding: 10px;
+ menu {
+ display: block;
+ margin: 0;
+ padding: 0;
border-bottom: solid @separator-color 1px;
+ height: @menu-height;
+ overflow: visible; // search help context laps over.
}
}
-@menu-row-gutter-width: 5px;
-.menu-row {
- .make-row(@menu-row-gutter-width);
+.menu-group {
+ @description-height: 16px;
+ display: inline-block;
+ height: @menu-height;
+ vertical-align: top;
+
+ .entry {
+ height: (@menu-height - @description-height)/3;
+ line-height: 1;
+ padding: 0.5rem 1rem;
+
+ label {
+ font-size: 1.2rem;
+ font-weight: normal;
+ margin: 0;
+ }
+ input[type=checkbox] {
+ margin: 0 2px;
+ vertical-align: middle;
+ }
+ }
+ .description {
+ height: @description-height;
+ text-align: center;
+ font-size: 0.9rem;
+ }
+}
+.menu-group + .menu-group:before {
+ @space: 10px;
+ content: " ";
+ border-left: solid 1px lighten(grey, 40%);
+ margin-top: @space;
+ height: @menu-height - @space*2;
+ position: absolute;
+}
+
+@menu-main-gutter-width: 5px;
+.menu-main {
+ .make-row(@menu-main-gutter-width);
}
.filter-input {
- .make-sm-column(3, @menu-row-gutter-width);
- margin-bottom:5px;
+ .make-sm-column(4, @menu-main-gutter-width);
}
.filter-input .popover {
diff --git a/web/src/js/components/FlowView/ToggleEdit.jsx b/web/src/js/components/FlowView/ToggleEdit.jsx
index 9016348e..6a691a3d 100644
--- a/web/src/js/components/FlowView/ToggleEdit.jsx
+++ b/web/src/js/components/FlowView/ToggleEdit.jsx
@@ -14,11 +14,11 @@ function ToggleEdit({ isEdit, startEdit, stopEdit, flow, modifiedFlow }) {
return (
<div className="edit-flow-container">
{isEdit ?
- <a className="edit-flow" onClick={() => stopEdit(flow, modifiedFlow)}>
+ <a className="edit-flow" title="Finish Edit" onClick={() => stopEdit(flow, modifiedFlow)}>
<i className="fa fa-check"/>
</a>
:
- <a className="edit-flow" onClick={() => startEdit(flow)}>
+ <a className="edit-flow" title="Edit Flow" onClick={() => startEdit(flow)}>
<i className="fa fa-pencil"/>
</a>
}
diff --git a/web/src/js/components/Header.jsx b/web/src/js/components/Header.jsx
index 702786e6..1500db1b 100644
--- a/web/src/js/components/Header.jsx
+++ b/web/src/js/components/Header.jsx
@@ -2,14 +2,13 @@ import React, { Component, PropTypes } from 'react'
import { connect } from 'react-redux'
import classnames from 'classnames'
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/header'
class Header extends Component {
- static entries = [MainMenu, ViewMenu, OptionMenu]
+ static entries = [MainMenu, OptionMenu]
handleClick(active, e) {
e.preventDefault()
@@ -38,9 +37,9 @@ class Header extends Component {
</a>
))}
</nav>
- <div className="menu">
+ <menu>
<Active/>
- </div>
+ </menu>
</header>
)
}
diff --git a/web/src/js/components/Header/FlowMenu.jsx b/web/src/js/components/Header/FlowMenu.jsx
index e78a49aa..e0c59afe 100644
--- a/web/src/js/components/Header/FlowMenu.jsx
+++ b/web/src/js/components/Header/FlowMenu.jsx
@@ -18,15 +18,12 @@ FlowMenu.propTypes = {
function FlowMenu({ flow, acceptFlow, replayFlow, duplicateFlow, removeFlow, revertFlow }) {
return (
<div>
- <div className="menu-row">
- <Button disabled={!flow || !flow.intercepted} title="[a]ccept intercepted flow" text="Accept" icon="fa-play" onClick={() => acceptFlow(flow)} />
- <Button title="[r]eplay flow" text="Replay" icon="fa-repeat" onClick={() => replayFlow(flow)} />
- <Button title="[D]uplicate flow" text="Duplicate" icon="fa-copy" onClick={() => duplicateFlow(flow)} />
- <Button title="[d]elete flow" text="Delete" icon="fa-trash" onClick={() => removeFlow(flow)}/>
- <Button disabled={!flow || !flow.modified} title="revert changes to flow [V]" text="Revert" icon="fa-history" onClick={() => revertFlow(flow)} />
- <Button title="download" text="Download" icon="fa-download" onClick={() => window.location = MessageUtils.getContentURL(flow, flow.response)}/>
- </div>
- <div className="clearfix"/>
+ <Button disabled={!flow || !flow.intercepted} title="[a]ccept intercepted flow" text="Accept" icon="fa-play" onClick={() => acceptFlow(flow)} />
+ <Button title="[r]eplay flow" text="Replay" icon="fa-repeat" onClick={() => replayFlow(flow)} />
+ <Button title="[D]uplicate flow" text="Duplicate" icon="fa-copy" onClick={() => duplicateFlow(flow)} />
+ <Button title="[d]elete flow" text="Delete" icon="fa-trash" onClick={() => removeFlow(flow)}/>
+ <Button disabled={!flow || !flow.modified} title="revert changes to flow [V]" text="Revert" icon="fa-history" onClick={() => revertFlow(flow)} />
+ <Button title="download" text="Download" icon="fa-download" onClick={() => window.location = MessageUtils.getContentURL(flow, flow.response)}/>
</div>
)
}
diff --git a/web/src/js/components/Header/MainMenu.jsx b/web/src/js/components/Header/MainMenu.jsx
index 5ab3fa9d..6a4e12bf 100644
--- a/web/src/js/components/Header/MainMenu.jsx
+++ b/web/src/js/components/Header/MainMenu.jsx
@@ -1,20 +1,17 @@
-import React, { Component, PropTypes } from 'react'
-import { connect } from 'react-redux'
-import FilterInput from './FilterInput'
-import { update as updateSettings } from '../../ducks/settings'
-import { setFilter, setHighlight } from '../../ducks/flows'
+import React, { Component, PropTypes } from "react"
+import { connect } from "react-redux"
+import FilterInput from "./FilterInput"
+import { update as updateSettings } from "../../ducks/settings"
+import { setFilter, setHighlight } from "../../ducks/flows"
MainMenu.title = "Start"
export default function MainMenu() {
return (
- <div>
- <div className="menu-row">
- <FlowFilterInput/>
- <HighlightInput/>
- <InterceptInput/>
- </div>
- <div className="clearfix"></div>
+ <div className="menu-main">
+ <FlowFilterInput/>
+ <HighlightInput/>
+ <InterceptInput/>
</div>
)
}
diff --git a/web/src/js/components/Header/MenuToggle.jsx b/web/src/js/components/Header/MenuToggle.jsx
new file mode 100644
index 00000000..726db7bd
--- /dev/null
+++ b/web/src/js/components/Header/MenuToggle.jsx
@@ -0,0 +1,69 @@
+import { PropTypes } from "react"
+import { connect } from "react-redux"
+import { update as updateSettings } from "../../ducks/settings"
+import { toggleVisibility } from "../../ducks/eventLog"
+
+MenuToggle.propTypes = {
+ value: PropTypes.bool.isRequired,
+ onChange: PropTypes.func.isRequired,
+ children: PropTypes.node.isRequired,
+}
+
+export function MenuToggle({ value, onChange, children }) {
+ return (
+ <div className="entry">
+ <label>
+ <input type="checkbox"
+ value={value}
+ onChange={onChange}/>
+ {children}
+ </label>
+ </div>
+ )
+}
+
+
+SettingsToggle.propTypes = {
+ setting: PropTypes.string.isRequired,
+ children: PropTypes.node.isRequired,
+}
+
+export function SettingsToggle({ setting, children, settings, updateSettings }) {
+ return (
+ <MenuToggle
+ value={settings[setting] || false} // we don't have settings initially, so just pass false.
+ onChange={() => updateSettings({ [setting]: !settings[setting] })}
+ >
+ {children}
+ </MenuToggle>
+ )
+}
+SettingsToggle = connect(
+ state => ({
+ settings: state.settings,
+ }),
+ {
+ updateSettings,
+ }
+)(SettingsToggle)
+
+
+export function EventlogToggle({ toggleVisibility, eventLogVisible }) {
+ return (
+ <MenuToggle
+ value={eventLogVisible}
+ onChange={toggleVisibility}
+ >
+ Display Event Log
+ </MenuToggle>
+ )
+}
+EventlogToggle = connect(
+ state => ({
+ eventLogVisible: state.eventLog.visible,
+ }),
+ {
+ toggleVisibility,
+ }
+)(EventlogToggle)
+
diff --git a/web/src/js/components/Header/OptionMenu.jsx b/web/src/js/components/Header/OptionMenu.jsx
index f1d19f48..4fb5dc1f 100644
--- a/web/src/js/components/Header/OptionMenu.jsx
+++ b/web/src/js/components/Header/OptionMenu.jsx
@@ -1,75 +1,59 @@
import React, { PropTypes } from 'react'
import { connect } from 'react-redux'
-import ToggleButton from '../common/ToggleButton'
-import ToggleInputButton from '../common/ToggleInputButton'
-import { update as updateSettings } from '../../ducks/settings'
+import {SettingsToggle, EventlogToggle} from './MenuToggle'
+import DocsLink from '../common/DocsLink'
OptionMenu.title = 'Options'
-OptionMenu.propTypes = {
- settings: PropTypes.object.isRequired,
- updateSettings: PropTypes.func.isRequired,
-}
-
-function OptionMenu({ settings, updateSettings }) {
+export default function OptionMenu() {
return (
<div>
- <div className="menu-row">
- <ToggleButton text="showhost"
- checked={settings.showhost}
- onToggle={() => updateSettings({ showhost: !settings.showhost })}
- />
- <ToggleButton text="no_upstream_cert"
- checked={settings.no_upstream_cert}
- onToggle={() => updateSettings({ no_upstream_cert: !settings.no_upstream_cert })}
- />
- <ToggleButton text="rawtcp"
- checked={settings.rawtcp}
- onToggle={() => updateSettings({ rawtcp: !settings.rawtcp })}
- />
- <ToggleButton text="http2"
- checked={settings.http2}
- onToggle={() => updateSettings({ http2: !settings.http2 })}
- />
- <ToggleButton text="websocket"
- checked={settings.websocket}
- onToggle={() => updateSettings({ websocket: !settings.websocket })}
- />
- <ToggleButton text="anticache"
- checked={settings.anticache}
- onToggle={() => updateSettings({ anticache: !settings.anticache })}
- />
- <ToggleButton text="anticomp"
- checked={settings.anticomp}
- onToggle={() => updateSettings({ anticomp: !settings.anticomp })}
- />
- <ToggleInputButton name="stickyauth" placeholder="Sticky auth filter"
- checked={!!settings.stickyauth}
- txt={settings.stickyauth}
- onToggleChanged={txt => updateSettings({ stickyauth: !settings.stickyauth ? txt : null })}
- />
- <ToggleInputButton name="stickycookie" placeholder="Sticky cookie filter"
- checked={!!settings.stickycookie}
- txt={settings.stickycookie}
- onToggleChanged={txt => updateSettings({ stickycookie: !settings.stickycookie ? txt : null })}
- />
- <ToggleInputButton name="stream_large_bodies" placeholder="stream..."
- checked={!!settings.stream_large_bodies}
- txt={settings.stream_large_bodies}
- inputType="number"
- onToggleChanged={txt => updateSettings({ stream_large_bodies: !settings.stream_large_bodies ? txt : null })}
- />
+ <div className="menu-group">
+ <SettingsToggle setting="http2">HTTP/2.0</SettingsToggle>
+ <SettingsToggle setting="websocket">WebSockets</SettingsToggle>
+ <SettingsToggle setting="rawtcp">Raw TCP</SettingsToggle>
+ <div className="description">Protocol Support</div>
+ </div>
+ <div className="menu-group">
+ <SettingsToggle setting="anticache">
+ Disable Caching <DocsLink resource="features/anticache.html"/>
+ </SettingsToggle>
+ <SettingsToggle setting="anticomp">
+ Disable Compression <i className="fa fa-question-circle" title="Do not forward Accept-Encoding headers to the server to force an uncompressed response."></i>
+ </SettingsToggle>
+ <div className="entry"/>
+ <div className="description">HTTP Options</div>
</div>
- <div className="clearfix"/>
+ <div className="menu-group">
+ <SettingsToggle setting="showhost">
+ Use Host Header <i className="fa fa-question-circle" title="Use the Host header to construct URLs for display."></i>
+ </SettingsToggle>
+ <EventlogToggle/>
+ <div className="entry"/>
+ <div className="description">View Options</div>
+ </div>
+ { /*
+ <ToggleButton text="no_upstream_cert"
+ checked={settings.no_upstream_cert}
+ onToggle={() => updateSettings({ no_upstream_cert: !settings.no_upstream_cert })}
+ />
+ <ToggleInputButton name="stickyauth" placeholder="Sticky auth filter"
+ checked={!!settings.stickyauth}
+ txt={settings.stickyauth}
+ onToggleChanged={txt => updateSettings({ stickyauth: !settings.stickyauth ? txt : null })}
+ />
+ <ToggleInputButton name="stickycookie" placeholder="Sticky cookie filter"
+ checked={!!settings.stickycookie}
+ txt={settings.stickycookie}
+ onToggleChanged={txt => updateSettings({ stickycookie: !settings.stickycookie ? txt : null })}
+ />
+ <ToggleInputButton name="stream_large_bodies" placeholder="stream..."
+ checked={!!settings.stream_large_bodies}
+ txt={settings.stream_large_bodies}
+ inputType="number"
+ onToggleChanged={txt => updateSettings({ stream_large_bodies: !settings.stream_large_bodies ? txt : null })}
+ />
+ */}
</div>
)
}
-
-export default connect(
- state => ({
- settings: state.settings,
- }),
- {
- updateSettings,
- }
-)(OptionMenu)
diff --git a/web/src/js/components/Header/ViewMenu.jsx b/web/src/js/components/Header/ViewMenu.jsx
deleted file mode 100644
index 22b370d1..00000000
--- a/web/src/js/components/Header/ViewMenu.jsx
+++ /dev/null
@@ -1,32 +0,0 @@
-import React, { PropTypes } from 'react'
-import { connect } from 'react-redux'
-import ToggleButton from '../common/ToggleButton'
-import { toggleVisibility } from '../../ducks/eventLog'
-
-ViewMenu.title = 'View'
-ViewMenu.route = 'flows'
-
-ViewMenu.propTypes = {
- eventLogVisible: PropTypes.bool.isRequired,
- toggleEventLog: PropTypes.func.isRequired,
-}
-
-function ViewMenu({ eventLogVisible, toggleEventLog }) {
- return (
- <div>
- <div className="menu-row">
- <ToggleButton text="Show Event Log" checked={eventLogVisible} onToggle={toggleEventLog} />
- </div>
- <div className="clearfix"></div>
- </div>
- )
-}
-
-export default connect(
- state => ({
- eventLogVisible: state.eventLog.visible,
- }),
- {
- toggleEventLog: toggleVisibility,
- }
-)(ViewMenu)
diff --git a/web/src/js/components/common/DocsLink.jsx b/web/src/js/components/common/DocsLink.jsx
new file mode 100644
index 00000000..182811a3
--- /dev/null
+++ b/web/src/js/components/common/DocsLink.jsx
@@ -0,0 +1,14 @@
+import { PropTypes } from 'react'
+
+DocsLink.propTypes = {
+ resource: PropTypes.string.isRequired,
+}
+
+export default function DocsLink({ children, resource }) {
+ let url = `http://docs.mitmproxy.org/en/stable/${resource}`
+ return (
+ <a target="_blank" href={url}>
+ {children || <i className="fa fa-question-circle"></i>}
+ </a>
+ )
+}
diff --git a/web/src/js/ducks/ui/header.js b/web/src/js/ducks/ui/header.js
index 25dfe602..1eff3ef6 100644
--- a/web/src/js/ducks/ui/header.js
+++ b/web/src/js/ducks/ui/header.js
@@ -4,7 +4,7 @@ export const SET_ACTIVE_MENU = 'UI_SET_ACTIVE_MENU'
const defaultState = {
- activeMenu: 'Start',
+ activeMenu: 'Options',
isFlowSelected: false,
}
@@ -22,7 +22,7 @@ export default function reducer(state = defaultState, action) {
if (action.flowIds.length && !state.isFlowSelected) {
return {
...state,
- activeMenu: 'Flow',
+ activeMenu: 'Options',
isFlowSelected: true,
}
}