Skip to content

Commit ad9c2bb

Browse files
committed
Merge pull request #368 from goatslacker/debug-component
A debug component
2 parents b57d4fb + efe1251 commit ad9c2bb

15 files changed

+699
-4
lines changed

.eslintrc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"browser": true,
55
"es6": true
66
},
7+
"parser": "babel-eslint",
78
"ecmaFeatures": {
89
"modules": true,
910
"jsx": true
@@ -25,7 +26,7 @@
2526
}],
2627
"no-use-before-define": 2,
2728
// possible errors
28-
"comma-dangle": [2, "never"],
29+
"comma-dangle": [0, "always"],
2930
"no-cond-assign": [2, "always"],
3031
"no-debugger": 1,
3132
"no-alert": 1,

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
"babel": "^5.6.6",
1616
"babel-core": "^5.6.6",
1717
"babel-loader": "^5.1.4",
18+
"babel-eslint": "3.1.18",
1819
"chai": "^2.3.0",
1920
"coveralls": "^2.11.2",
2021
"envify": "^3.4.0",

src/alt/index.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,15 @@ class Alt {
2424
}
2525

2626
dispatch(action, data, details) {
27-
this.batchingFunction(() => this.dispatcher.dispatch({ action, data, details }))
27+
this.batchingFunction(() => {
28+
const id = Math.random().toString(18).substr(2, 16)
29+
return this.dispatcher.dispatch({
30+
id,
31+
action,
32+
data,
33+
details
34+
})
35+
})
2836
}
2937

3038
createUnsavedStore(StoreModel, ...args) {

src/utils/Debugger.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*eslint-disable */
2+
import DebugActions from './debug/DebugActions'
3+
import DispatcherDebugger from './DispatcherDebugger'
4+
import React from 'react'
5+
import StoreExplorer from './StoreExplorer'
6+
7+
class Debugger extends React.Component {
8+
componentDidMount() {
9+
DebugActions.setAlt(this.props.alt)
10+
}
11+
12+
renderInspectorWindow() {
13+
return this.props.inspector
14+
? <this.props.inspector />
15+
: null
16+
}
17+
18+
render() {
19+
return (
20+
<div>
21+
<h1>Debug</h1>
22+
<DispatcherDebugger alt={this.props.alt} />
23+
<StoreExplorer alt={this.props.alt} />
24+
{this.renderInspectorWindow()}
25+
</div>
26+
)
27+
}
28+
}
29+
30+
export default Debugger

src/utils/DispatcherDebugger.js

Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
/*eslint-disable */
2+
import React from 'react'
3+
import { Column, Table } from 'fixed-data-table'
4+
import makeFinalStore from './makeFinalStore'
5+
import connectToStores from './connectToStores'
6+
7+
import FixedDataTableCss from './debug/FixedDataTableCss'
8+
9+
import DebugActions from './debug/DebugActions'
10+
import DispatcherStore from './debug/DispatcherStore'
11+
12+
class DispatcherDebugger extends React.Component {
13+
constructor() {
14+
super()
15+
16+
this.getDispatch = this.getDispatch.bind(this)
17+
this.renderName = this.renderName.bind(this)
18+
this.renderReplay = this.renderReplay.bind(this)
19+
this.renderRevert = this.renderRevert.bind(this)
20+
this.view = this.view.bind(this)
21+
}
22+
23+
componentDidMount() {
24+
const finalStore = makeFinalStore(this.props.alt)
25+
finalStore.listen(state => DebugActions.addDispatch(state.payload))
26+
DebugActions.setAlt(this.props.alt)
27+
}
28+
29+
clear() {
30+
DebugActions.clear()
31+
}
32+
33+
getDispatch(idx) {
34+
const dispatch = this.props.dispatches[idx]
35+
return {
36+
id: dispatch.id,
37+
action: dispatch.action,
38+
data: dispatch.data,
39+
details: dispatch.details,
40+
recorded: dispatch.recorded,
41+
dispatchedStores: dispatch.dispatchedStores,
42+
mtime: this.props.mtime,
43+
}
44+
}
45+
46+
loadRecording() {
47+
const json = prompt('Give me a serialized recording')
48+
if (json) DebugActions.loadRecording(json)
49+
}
50+
51+
revert(ev) {
52+
const data = ev.target.dataset
53+
DebugActions.revert(data.dispatchId)
54+
}
55+
56+
saveRecording() {
57+
DebugActions.saveRecording()
58+
}
59+
60+
startReplay() {
61+
DebugActions.startReplay()
62+
DebugActions.replay()
63+
}
64+
65+
stopReplay() {
66+
DebugActions.stopReplay()
67+
}
68+
69+
toggleLogDispatches() {
70+
DebugActions.toggleLogDispatches()
71+
}
72+
73+
togglePauseReplay() {
74+
DebugActions.togglePauseReplay()
75+
}
76+
77+
toggleRecording() {
78+
DebugActions.toggleRecording()
79+
}
80+
81+
view(ev) {
82+
const data = ev.target.dataset
83+
const dispatch = this.props.dispatches[data.index]
84+
DebugActions.selectData(dispatch)
85+
}
86+
87+
renderName(name, _, dispatch, idx) {
88+
return (
89+
<div
90+
data-index={idx}
91+
onClick={this.view}
92+
style={{ cursor: 'pointer' }}
93+
>
94+
{name}
95+
</div>
96+
)
97+
}
98+
99+
renderReplay() {
100+
if (this.props.inReplayMode) {
101+
return (
102+
<span>
103+
<span onClick={this.togglePauseReplay}>
104+
{this.props.isReplaying ? 'Pause Replay' : 'Resume Replay'}
105+
</span>
106+
{' | '}
107+
<span onClick={this.stopReplay}>
108+
Stop Replay
109+
</span>
110+
</span>
111+
)
112+
}
113+
114+
return (
115+
<span onClick={this.startReplay}>
116+
Start Replay
117+
</span>
118+
)
119+
}
120+
121+
renderRevert(a, b, dispatch) {
122+
return (
123+
<div>
124+
<span
125+
data-dispatch-id={dispatch.id}
126+
onClick={this.revert}
127+
style={{ cursor: 'pointer' }}
128+
>
129+
Revert
130+
</span>
131+
<span dangerouslySetInnerHTML={{
132+
__html: this.props.currentStateId === dispatch.id ? '&#10003;' : ''
133+
}} />
134+
</div>
135+
)
136+
}
137+
138+
render() {
139+
return (
140+
<div>
141+
<h3>Dispatches</h3>
142+
<FixedDataTableCss />
143+
<div>
144+
<span onClick={this.toggleRecording}>
145+
{this.props.isRecording ? 'Stop Recording' : 'Record'}
146+
</span>
147+
{' | '}
148+
<span onClick={this.clear}>
149+
Clear
150+
</span>
151+
{' | '}
152+
<span onClick={this.saveRecording}>
153+
Save
154+
</span>
155+
{' | '}
156+
<span onClick={this.loadRecording}>
157+
Load
158+
</span>
159+
{' | '}
160+
{this.renderReplay()}
161+
</div>
162+
<Table
163+
headerHeight={30}
164+
height={480}
165+
rowGetter={this.getDispatch}
166+
rowHeight={30}
167+
rowsCount={this.props.dispatches.length}
168+
width={320}
169+
>
170+
<Column
171+
cellRenderer={this.renderName}
172+
dataKey="action"
173+
label="Name"
174+
width={250}
175+
/>
176+
<Column
177+
cellRenderer={this.renderRevert}
178+
dataKey=""
179+
label="Revert"
180+
width={70}
181+
/>
182+
</Table>
183+
</div>
184+
)
185+
}
186+
}
187+
188+
export default connectToStores({
189+
getPropsFromStores() {
190+
return DispatcherStore.getState()
191+
},
192+
193+
getStores() {
194+
return [DispatcherStore]
195+
}
196+
}, DispatcherDebugger)

src/utils/DispatcherRecorder.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,9 @@ DispatcherRecorder.prototype.replay = function (replayTime, done) {
110110
DispatcherRecorder.prototype.serializeEvents = function () {
111111
const events = this.events.map((event) => {
112112
return {
113+
id: event.id,
113114
action: event.action,
114-
data: event.data
115+
data: event.data || {}
115116
}
116117
})
117118
return JSON.stringify(events)
@@ -129,6 +130,7 @@ DispatcherRecorder.prototype.loadEvents = function (events) {
129130
data: event.data
130131
}
131132
})
133+
return parsedEvents
132134
}
133135

134136
export default DispatcherRecorder

0 commit comments

Comments
 (0)