From 7ed6f10e357ef7b08fc94b46a0901218e62f418e Mon Sep 17 00:00:00 2001 From: Maximilian Hils Date: Thu, 25 Dec 2014 02:03:55 +0100 Subject: web: much ui work, such christmas --- web/src/css/flowtable.less | 153 ++++++++++++++----------- web/src/css/tabs.less | 6 +- web/src/js/components/flowdetail.jsx.js | 79 ++++++++++++- web/src/js/components/flowtable-columns.jsx.js | 6 +- web/src/js/components/header.jsx.js | 103 +++++++++-------- web/src/js/components/mainview.jsx.js | 13 ++- 6 files changed, 235 insertions(+), 125 deletions(-) (limited to 'web/src') diff --git a/web/src/css/flowtable.less b/web/src/css/flowtable.less index 38f5e0e8..9988f1a8 100644 --- a/web/src/css/flowtable.less +++ b/web/src/css/flowtable.less @@ -1,78 +1,95 @@ .flow-table { - width: 100%; - overflow: auto; + width: 100%; + overflow: auto; - table { - width: 100%; - table-layout: fixed; - } + table { + width: 100%; + table-layout: fixed; + } - thead { - background-color: #F2F2F2; - line-height: 23px; - } + thead { + background-color: #F2F2F2; + line-height: 23px; + } - th { - font-weight: normal; - box-shadow: 0 1px 0 #a6a6a6; - } + th { + font-weight: normal; + box-shadow: 0 1px 0 #a6a6a6; + } - tr { - cursor: pointer; + tr { + cursor: pointer; - &:nth-child(even) { - background-color : rgba(0,0,0,0.05); - } - &.selected { - background-color: hsla(209, 52%, 84%, 0.5) !important; - } - &.highlighted { - background-color: hsla(48, 100%, 50%, 0.4); - } - &.highlighted:nth-child(even) { - background-color: hsla(48, 100%, 50%, 0.5); - } - } + &:nth-child(even) { + background-color: rgba(0, 0, 0, 0.05); + } + &.selected { + background-color: hsla(209, 52%, 84%, 0.5) !important; + } + &.highlighted { + background-color: hsla(48, 100%, 50%, 0.4); + } + &.highlighted:nth-child(even) { + background-color: hsla(48, 100%, 50%, 0.5); + } + } - td { - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; - } + td { + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + } - tr.intercepted:not(.has-response) { - .col-path, .col-method { - color: hsl(30, 100%, 50%); - } - } - tr.intercepted.has-response { - .col-status, .col-size, .col-time { - color: hsl(30, 100%, 50%); - } - } + @interceptorange: hsl(30, 100%, 50%); - .col-tls { - width: 10px; - } - .col-tls-https { - background-color: rgba(0, 185, 0, 0.5); - } - .col-icon { - width: 32px; - } - .col-method { - width: 60px; - } - .col-status { - width: 50px; - } - .col-size { - width: 70px; - } - .col-time { - width: 50px; - } - td.col-time, td.col-size { - text-align: right; - } + tr.intercepted:not(.has-response) { + .col-path, .col-method { + color: @interceptorange; + } + } + tr.intercepted.has-response { + .col-status, .col-size, .col-time { + color: @interceptorange; + } + } + + .fa { + line-height: inherit; + &.pull-right { + margin-left: 0; + } + } + + .col-tls { + width: 10px; + } + .col-tls-https { + background-color: rgba(0, 185, 0, 0.5); + } + .col-icon { + width: 32px; + } + .col-path { + .fa-repeat { + color: green; + } + .fa-pause { + color: @interceptorange; + } + } + .col-method { + width: 60px; + } + .col-status { + width: 50px; + } + .col-size { + width: 70px; + } + .col-time { + width: 50px; + } + td.col-time, td.col-size { + text-align: right; + } } \ No newline at end of file diff --git a/web/src/css/tabs.less b/web/src/css/tabs.less index 36bc5b68..43f7264e 100644 --- a/web/src/css/tabs.less +++ b/web/src/css/tabs.less @@ -40,6 +40,10 @@ a { padding: 0px 7px; margin: 2px 2px -1px; - + } + a.nav-action { + float: right; + padding: 0; + margin: 1px 0 0px; } } \ No newline at end of file diff --git a/web/src/js/components/flowdetail.jsx.js b/web/src/js/components/flowdetail.jsx.js index 5727ec75..dfc0099e 100644 --- a/web/src/js/components/flowdetail.jsx.js +++ b/web/src/js/components/flowdetail.jsx.js @@ -1,7 +1,72 @@ +var DeleteButton = React.createClass({ + onClick: function (e) { + e.preventDefault(); + FlowActions.delete(this.props.flow); + }, + render: function () { + return ( + + + + ); + } +}); +var DuplicateButton = React.createClass({ + onClick: function (e) { + e.preventDefault(); + FlowActions.duplicate(this.props.flow); + }, + render: function () { + return ( + + + + ); + } +}); +var ReplayButton = React.createClass({ + onClick: function (e) { + e.preventDefault(); + FlowActions.replay(this.props.flow); + }, + render: function () { + return ( + + + + ); + } +}); +var AcceptButton = React.createClass({ + onClick: function (e) { + e.preventDefault(); + FlowActions.accept(this.props.flow); + }, + render: function () { + return ( + + + + ); + } +}); var FlowDetailNav = React.createClass({ render: function () { + var flow = this.props.flow; - var items = this.props.tabs.map(function (e) { + var tabs = this.props.tabs.map(function (e) { var str = e.charAt(0).toUpperCase() + e.slice(1); var className = this.props.active === e ? "active" : ""; var onClick = function (event) { @@ -13,9 +78,14 @@ var FlowDetailNav = React.createClass({ className={className} onClick={onClick}>{str}; }.bind(this)); + return ( ); } @@ -104,7 +174,9 @@ var FlowDetailError = React.createClass({
{flow.error.msg} -
{ formatTimeStamp(flow.error.timestamp) }
+
+ { formatTimeStamp(flow.error.timestamp) } +
); @@ -341,6 +413,7 @@ var FlowDetail = React.createClass({ return (
diff --git a/web/src/js/components/flowtable-columns.jsx.js b/web/src/js/components/flowtable-columns.jsx.js index 1aa256c4..9162e077 100644 --- a/web/src/js/components/flowtable-columns.jsx.js +++ b/web/src/js/components/flowtable-columns.jsx.js @@ -66,7 +66,11 @@ var PathColumn = React.createClass({ }, render: function () { var flow = this.props.flow; - return {flow.request.scheme + "://" + flow.request.host + flow.request.path}; + return + {flow.request.is_replay ? : null} + {flow.intercepted ? : null} + {flow.request.scheme + "://" + flow.request.host + flow.request.path} + ; } }); diff --git a/web/src/js/components/header.jsx.js b/web/src/js/components/header.jsx.js index 9e6b8f2f..e1016950 100644 --- a/web/src/js/components/header.jsx.js +++ b/web/src/js/components/header.jsx.js @@ -111,23 +111,9 @@ var FilterInput = React.createClass({ var MainMenu = React.createClass({ mixins: [Navigation, State], statics: { - title: "Traffic", + title: "Start", route: "flows" }, - toggleEventLog: function () { - var d = {}; - - if(this.getQuery()[Query.SHOW_EVENTLOG]){ - d[Query.SHOW_EVENTLOG] = undefined; - } else { - d[Query.SHOW_EVENTLOG] = "t"; // any non-false value will do it, keep it short - } - - this.setQuery(d); - }, - clearFlows: function () { - FlowActions.clear(); - }, onFilterChange: function (val) { var d = {}; d[Query.FILTER] = val; @@ -145,22 +131,9 @@ var MainMenu = React.createClass({ var filter = this.getQuery()[Query.FILTER] || ""; var highlight = this.getQuery()[Query.HIGHLIGHT] || ""; var intercept = this.props.settings.intercept || ""; - var showEventLog = this.getQuery()[Query.SHOW_EVENTLOG]; return (
- - - -
Tools Menu
; + var showEventLog = this.getQuery()[Query.SHOW_EVENTLOG]; + return ( +
+ + +
+ ); } }); @@ -232,7 +228,9 @@ var FileMenu = React.createClass({ }, handleNewClick: function (e) { e.preventDefault(); - console.error("unimplemented: handleNewClick"); + if (confirm("Delete all flows?")) { + FlowActions.clear(); + } }, handleOpenClick: function (e) { e.preventDefault(); @@ -259,25 +257,34 @@ var FileMenu = React.createClass({ New -
  • - - - Open - -
  • -
  • - - - Save - -
  • - - - Shutdown + + + Install Certificates...
  • + {/* +
  • + + + Open + +
  • +
  • + + + Save + +
  • +
  • +
  • + + + Shutdown + +
  • + */}
    ); @@ -285,7 +292,7 @@ var FileMenu = React.createClass({ }); -var header_entries = [MainMenu, ToolsMenu, ReportsMenu]; +var header_entries = [MainMenu, ViewMenu /*, ReportsMenu */]; var Header = React.createClass({ diff --git a/web/src/js/components/mainview.jsx.js b/web/src/js/components/mainview.jsx.js index 78415ad0..41f22a95 100644 --- a/web/src/js/components/mainview.jsx.js +++ b/web/src/js/components/mainview.jsx.js @@ -44,6 +44,7 @@ var MainView = React.createClass({ view.addListener("recalculate", this.onRecalculate); view.addListener("add update remove", this.onUpdate); + view.addListener("remove", this.onRemove); }, onRecalculate: function () { this.forceUpdate(); @@ -57,6 +58,12 @@ var MainView = React.createClass({ this.forceUpdate(); } }, + onRemove: function (flow_id, index) { + if (flow_id === this.getParams().flowId) { + var flow_to_select = this.state.view.list[Math.min(index, this.state.view.list.length -1)]; + this.selectFlow(flow_to_select); + } + }, closeView: function () { this.state.view.close(); }, @@ -106,7 +113,7 @@ var MainView = React.createClass({ }, onKeyDown: function (e) { var flow = this.getSelected(); - if(e.ctrlKey){ + if (e.ctrlKey) { return; } switch (e.keyCode) { @@ -157,8 +164,6 @@ var MainView = React.createClass({ if (e.shiftKey) { FlowActions.duplicate(flow); } else { - var last_flow = this.state.view.index(flow) === this.state.view.list.length - 1; - this.selectFlowRelative(last_flow ? -1 : +1); FlowActions.delete(flow); } } @@ -171,7 +176,7 @@ var MainView = React.createClass({ } break; case Key.R: - if(!e.shiftKey && flow){ + if (!e.shiftKey && flow) { FlowActions.replay(flow); } break; -- cgit v1.2.3