Skip to content
This repository was archived by the owner on Aug 13, 2018. It is now read-only.

Commit dd6ea4f

Browse files
committed
Merge branch 'esphen-issue30'
2 parents cdc4c61 + c7eb869 commit dd6ea4f

File tree

7 files changed

+211
-83
lines changed

7 files changed

+211
-83
lines changed

chrome/locale/en-US/websocket-monitor.properties

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,12 @@ websocketmonitor.option.tip.tabularView=Use table for list of sent and received
5353
# a footer in table perspective.
5454
websocketmonitor.summary.frameCount=%1$S frame;%1$S frames
5555

56+
# LOCALIZATION NOTE (websocketmonitor.ConnectionFilter.NoFilter): A label displayed
57+
# to the user inside the connection ID dropdown filter. It shows that the user has
58+
# not yet selected a connection to filter on, and should inform the user of the
59+
# purpose of the dropdown.
60+
websocketmonitor.ConnectionFilter.NoFilter=Filter by Socket ID
61+
5662
# LOCALIZATION NOTE (websocketmonitor.label.sent, websocketmonitor.label.received):
5763
# A label for frames displayed in the frame list.
5864
websocketmonitor.label.sent=Sent
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/* See license.txt for terms of usage */
2+
3+
define(function(require, exports/*, module*/) {
4+
5+
"use strict";
6+
7+
// Dependencies
8+
const React = require("react");
9+
10+
// WebSockets Monitor
11+
const { filterFrames } = require("../actions/frames");
12+
13+
// Shortcuts
14+
const { span, select, option } = React.DOM;
15+
16+
/**
17+
* This component renders a select element when unique
18+
* webSocket connections > 1. Using this dropdown, the
19+
* user can select the connection ID they are interested
20+
* in seeing, and a reducer should filter out all other
21+
* connections.
22+
*/
23+
var ConnectionFilter = React.createClass({
24+
/** @lends ConnectionFilter */
25+
26+
displayName: "ConnectionFilter",
27+
28+
getInitialState() {
29+
return {
30+
uniqueConnections: []
31+
};
32+
},
33+
34+
handleChange(e) {
35+
const { value } = e.target;
36+
const currentFilter = this.props.frames.filter;
37+
38+
// Dispatch new filter, merging with old filter to
39+
// retain text filter alongside this filter.
40+
this.props.dispatch(filterFrames(
41+
Object.assign({}, currentFilter, {
42+
webSocketSerialID: value !== null ? Number(value) : null
43+
})
44+
));
45+
},
46+
47+
// When the platform API supports it, this should be replaced
48+
// with some API call listing only the current connections on
49+
// the page.
50+
componentWillReceiveProps({ frames }) {
51+
frames.frames.forEach(frame => {
52+
const { uniqueConnections } = this.state;
53+
54+
if (!uniqueConnections.includes(frame.webSocketSerialID)) {
55+
this.setState({
56+
uniqueConnections: [...uniqueConnections, frame.webSocketSerialID]
57+
});
58+
}
59+
})
60+
},
61+
62+
render() {
63+
const { uniqueConnections } = this.state;
64+
return (
65+
uniqueConnections.length > 1 ?
66+
select({
67+
className: "ConnectionFilter",
68+
value: this.props.frames.filter.webSocketSerialID,
69+
onChange: this.handleChange
70+
}, option({ value: null }, Locale.$STR("websocketmonitor.ConnectionFilter.NoFilter")),
71+
uniqueConnections.map((id, i) => {
72+
return option({key: i, value: id}, id);
73+
})
74+
) :
75+
// else, no-op
76+
span()
77+
);
78+
}
79+
});
80+
81+
// Exports from this module
82+
exports.ConnectionFilter = ConnectionFilter;
83+
});
84+

data/components/main-toolbar.js

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ const { Toolbar, ToolbarButton } = createFactories(require("reps/toolbar"));
1414

1515
// WebSockets Monitor
1616
const { clear } = require("../actions/frames");
17-
const { SearchBox } = require("./search-box");
17+
const { SearchBox } = createFactories(require("./search-box"));
18+
const { ConnectionFilter } = createFactories(require("./connection-filter"));
1819

1920
/**
2021
* @template This object is responsible for rendering the toolbar
@@ -31,16 +32,6 @@ var MainToolbar = React.createClass({
3132
}
3233
},
3334

34-
componentDidMount: function() {
35-
var toolbar = ReactDOM.findDOMNode(this.refs.toolbar);
36-
SearchBox.create(toolbar);
37-
},
38-
39-
componentWillUnmount: function() {
40-
var toolbar = ReactDOM.findDOMNode(this.refs.toolbar);
41-
SearchBox.destroy(toolbar);
42-
},
43-
4435
// Commands
4536

4637
onTogglePause: function() {
@@ -89,7 +80,9 @@ var MainToolbar = React.createClass({
8980
),
9081
ToolbarButton({bsSize: "xsmall", onClick: this.onSwitchPerspective},
9182
perspectiveLabel
92-
)
83+
),
84+
SearchBox(this.props),
85+
ConnectionFilter(this.props)
9386
)
9487
);
9588
},

data/components/search-box.js

Lines changed: 46 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -4,77 +4,70 @@ define(function(require, exports/*, module*/) {
44

55
"use strict";
66

7+
// Dependencies
8+
const React = require("react");
9+
10+
// WebSockets Monitor
11+
const { filterFrames } = require("../actions/frames");
12+
13+
// Shortcuts
14+
const { input } = React.DOM;
15+
716
/**
8-
* TODO docs xxxHonza: use ReactJS.
17+
* This component renders a search box that allows the
18+
* user to filter on the content of the frames in the
19+
* list. It dispatches a "filterFrames" event with the
20+
* updated text filter.
921
*/
10-
var SearchBox =
22+
var SearchBox = React.createClass({
1123
/** @lends SearchBox */
12-
{
13-
create: function(parentNode) {
14-
var doc = parentNode.ownerDocument;
15-
var win = doc.defaultView;
16-
var toolbar = doc.querySelector(".mainPanel .toolbar");
17-
18-
// Search box
19-
var searchBox = doc.createElement("input");
20-
searchBox.setAttribute("class", "devtools-searchinput");
21-
searchBox.setAttribute("type", "search");
22-
searchBox.setAttribute("results", "true");
23-
toolbar.appendChild(searchBox);
24-
25-
searchBox.addEventListener("command", this.onChange.bind(this, searchBox), false);
26-
searchBox.addEventListener("input", this.onChange.bind(this, searchBox), false);
27-
searchBox.addEventListener("keypress", this.onKeyPress.bind(this, searchBox), false);
28-
29-
this.handleThemeChange = this.handleThemeChange.bind(this, searchBox);
30-
win.addEventListener("theme-changed", this.handleThemeChange);
24+
25+
displayName: "SearchBox",
26+
27+
getInitialState() {
28+
return {
29+
text: ""
30+
};
31+
},
32+
33+
componentDidMount() {
34+
document.defaultView.addEventListener("theme-changed", this.handleThemeChange);
3135
},
3236

33-
destroy: function(parentNode) {
34-
var doc = parentNode.ownerDocument;
35-
var searchBox = doc.querySelector(".searchBox");
36-
searchBox.remove();
37-
win.removeEventListener("theme-changed", this.handleThemeChange);
37+
componentWillUnmount() {
38+
document.defaultView.removeEventListener("theme-changed", this.handleThemeChange);
3839
},
3940

40-
handleThemeChange: function(searchBox, event) {
41-
var data = event.data;
42-
var win = searchBox.ownerDocument.defaultView;
41+
handleThemeChange(event) {
42+
const data = event.data;
4343

4444
// Reset the filter if Firebug theme has been activated or deactivated.
4545
if (data.newTheme == "firebug" || data.oldTheme == "firebug") {
46-
searchBox.value = "";
47-
this.dispatch(win, {
48-
text: ""
49-
});
46+
this.onChange("");
5047
}
5148
},
5249

53-
onKeyPress: function(searchBox/*, event*/) {
54-
this.onSearch(searchBox);
55-
},
56-
57-
onChange: function(searchBox/*, event*/) {
58-
this.onSearch(searchBox);
59-
},
50+
onChange(text) {
51+
const currentFilter = this.props.frames.filter;
6052

61-
onSearch: function(searchBox) {
62-
var win = searchBox.ownerDocument.defaultView;
63-
this.dispatch(win, {
64-
text: searchBox.value
65-
});
53+
// Dispatch new filter, merging with old filter to
54+
// retain connectionId filter alongside this filter.
55+
this.props.dispatch(filterFrames(
56+
Object.assign({}, currentFilter, { text })
57+
));
58+
this.setState({ text });
6659
},
6760

68-
dispatch: function(win, filter) {
69-
var event = new win.MessageEvent("firebug.sdk/chrome-event", {
70-
data: {
71-
method: "onSearch",
72-
args: filter
73-
}
61+
render() {
62+
return input({
63+
className: "devtools-searchinput",
64+
type: "search",
65+
results: "true",
66+
value: this.state.text,
67+
onChange: e => this.onChange(e.target.value)
7468
});
75-
win.dispatchEvent(event);
7669
}
77-
};
70+
});
7871

7972
// Exports from this module
8073
exports.SearchBox = SearchBox;

data/css/connection-filter.css

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/* See license.txt for terms of usage */
2+
3+
/******************************************************************************/
4+
/* Connection Filter Dropdown */
5+
6+
.theme-dark .ConnectionFilter {
7+
color: var(--theme-content-color1);
8+
border: none;
9+
background: rgba(170, 170, 170, .3);
10+
}
11+
12+
.theme-firebug .ConnectionFilter {
13+
color: #333;
14+
border-radius: 2px;
15+
}
16+
17+
.ConnectionFilter {
18+
float: right;
19+
height: 22px;
20+
border: 1px solid rgb(204, 204, 204);
21+
22+
background: rgb(255, 255, 255) none repeat scroll 0% 0%;
23+
box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.075) inset;
24+
color: rgb(85, 85, 85);
25+
}
26+

data/reducers/frames.js

Lines changed: 43 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -95,51 +95,76 @@ function addFrames(state, newFrames) {
9595
});
9696

9797
// Apply filter on incoming frames.
98-
if (newState.filter.text) {
99-
return filterFrames(newState, newState.filter);
100-
}
101-
102-
return newState;
98+
return filterFrames(newState, newState.filter);
10399
}
104100

105101
function filterFrames(state, filter) {
106-
var frames;
107-
108-
var summary = {
109-
totalSize: 0,
110-
startTime: 0,
111-
endTime: 0,
112-
frameCount: 0
113-
};
102+
var { frames } = state;
103+
var summary = null;
114104

115105
if (filter.text) {
116-
frames = state.frames.filter(frame => {
106+
summary = {
107+
totalSize: 0,
108+
startTime: 0,
109+
endTime: 0,
110+
frameCount: 0
111+
};
112+
113+
frames = frames.filter(frame => {
117114
var data = frame.data;
118-
if (data.payload && data.payload.indexOf(filter.text) != -1) {
115+
116+
// Exclude where data is null (events). Events have no payload
117+
if (data && data.payload && data.payload.indexOf(filter.text) != -1) {
119118
summary.totalSize += data.payload.length;
120119
summary.startTime = summary.startTime ? summary.startTime : data.timeStamp;
121120
summary.endTime = data.timeStamp;
122121
summary.frameCount++;
123122
return true;
124123
}
125124
});
126-
} else {
127-
summary = null;
125+
}
126+
127+
if (filter.webSocketSerialID) {
128+
summary = {
129+
totalSize: 0,
130+
startTime: 0,
131+
endTime: 0,
132+
frameCount: 0
133+
};
134+
135+
frames = frames.filter(frame => {
136+
var data = frame.data;
137+
if (frame.webSocketSerialID === filter.webSocketSerialID) {
138+
139+
// If data is null, this is not an actual frame, but an event
140+
// like "connect" or "disconnect". We still want to keep it
141+
// in the list, though.
142+
if (data) {
143+
summary.totalSize += data.payload.length;
144+
summary.startTime = summary.startTime ? summary.startTime : data.timeStamp;
145+
summary.endTime = data.timeStamp;
146+
summary.frameCount++;
147+
}
148+
return true;
149+
}
150+
});
128151
}
129152

130153
return Object.assign({}, state, {
131154
filter: {
132155
text: filter.text,
156+
webSocketSerialID: filter.webSocketSerialID,
133157
frames: frames,
134158
summary: summary,
135159
}
136160
});
137161
}
138162

139163
function clear(state) {
140-
// All data are cleared except of the current filter.
164+
// All data is cleared except for the current filters.
141165
var newState = getInitialState();
142166
newState.filter.text = state.filter.text;
167+
newState.filter.webSocketSerialID = state.filter.webSocketSerialID;
143168
return newState;
144169
}
145170

data/view.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
<link href="./css/styles.css" rel="stylesheet">
1010
<link href="./css/frame-table.css" rel="stylesheet">
1111
<link href="./css/frame-list.css" rel="stylesheet">
12+
<link href="./css/connection-filter.css" rel="stylesheet">
1213
<link href="./css/search-box.css" rel="stylesheet">
1314
<link href="./css/no-service-warning.css" rel="stylesheet">
1415
<script src="../node_modules/keymaster/keymaster.js"></script>

0 commit comments

Comments
 (0)