Skip to content

Commit b5ea775

Browse files
authored
Merge pull request #39 from oslabs-beta/rydang/refactorbuttons
refactored stateful components into functional and added props validation
2 parents c3931b9 + 9e7fd63 commit b5ea775

File tree

8 files changed

+192
-140
lines changed

8 files changed

+192
-140
lines changed
Lines changed: 43 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,50 @@
1-
import React, { Component } from 'react';
1+
import React from 'react';
2+
import PropTypes from 'prop-types';
23
import Action from '../components/Action';
34

4-
class ActionContainer extends Component {
5-
constructor(props) {
6-
super(props);
5+
const ActionContainer = ({
6+
snapshots,
7+
snapshotIndex,
8+
handleChangeSnapshot,
9+
handleJumpSnapshot,
10+
emptySnapshot,
11+
}) => {
12+
let actionsArr = [];
13+
if (snapshots.length > 0) {
14+
actionsArr = snapshots.map((snapshot, index) => {
15+
const selected = index === snapshotIndex;
16+
return (
17+
<Action
18+
key={`action${index}`}
19+
index={index}
20+
snapshot={snapshot}
21+
selected={selected}
22+
handleChangeSnapshot={handleChangeSnapshot}
23+
handleJumpSnapshot={handleJumpSnapshot}
24+
/>
25+
);
26+
});
727
}
8-
9-
render() {
10-
const {
11-
snapshots,
12-
snapshotIndex,
13-
handleChangeSnapshot,
14-
handleJumpSnapshot,
15-
emptySnapshot,
16-
} = this.props;
17-
let actionsArr = [];
18-
if (snapshots.length > 0) {
19-
actionsArr = snapshots.map((snapshot, index) => {
20-
const selected = index === snapshotIndex;
21-
return (
22-
<Action
23-
key={`action${index}`}
24-
index={index}
25-
snapshot={snapshot}
26-
selected={selected}
27-
handleChangeSnapshot={handleChangeSnapshot}
28-
handleJumpSnapshot={handleJumpSnapshot}
29-
/>
30-
);
31-
});
32-
}
33-
return (
34-
<div className="action-container">
35-
<div className="action-component exclude">
36-
<div className="empty-button" onClick={emptySnapshot}>
37-
emptySnapshot
38-
</div>
28+
return (
29+
<div className="action-container">
30+
<div className="action-component exclude">
31+
<div className="empty-button" onClick={emptySnapshot}>
32+
emptySnapshot
3933
</div>
40-
<div>{actionsArr}</div>
4134
</div>
42-
);
43-
}
44-
}
35+
<div>{actionsArr}</div>
36+
</div>
37+
);
38+
};
39+
40+
ActionContainer.propTypes = {
41+
snapshots: PropTypes.arrayOf(
42+
PropTypes.object,
43+
).isRequired,
44+
snapshotIndex: PropTypes.number.isRequired,
45+
handleChangeSnapshot: PropTypes.func.isRequired,
46+
handleJumpSnapshot: PropTypes.func.isRequired,
47+
emptySnapshot: PropTypes.func.isRequired,
48+
};
4549

4650
export default ActionContainer;
Lines changed: 15 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,19 @@
1-
import React, { Component } from 'react';
1+
import React from 'react';
2+
import PropTypes from 'prop-types';
23

3-
const autoBind = require('auto-bind');
4+
const ButtonsContainer = ({ mode: { paused, locked }, toggleMode }) => (
5+
<div className="buttons-container">
6+
<div className="pause-button" onClick={() => toggleMode('paused')}>{(paused) ? 'Resume' : 'Pause'}</div>
7+
<div className="lock-button" onClick={() => toggleMode('locked')}>{(locked) ? 'Unlock' : 'Lock'}</div>
8+
</div>
9+
);
410

5-
class ButtonsContainer extends Component {
6-
constructor(props) {
7-
super(props);
11+
ButtonsContainer.propTypes = {
12+
toggleMode: PropTypes.func.isRequired,
13+
mode: PropTypes.shape({
14+
paused: PropTypes.bool,
15+
locked: PropTypes.bool,
16+
}).isRequired,
17+
};
818

9-
this.state = {
10-
paused: false,
11-
locked: false,
12-
};
13-
14-
autoBind(this);
15-
}
16-
17-
togglePause(port) {
18-
const { paused } = this.state;
19-
port.postMessage({ action: 'setPause', payload: !paused });
20-
this.setState({ paused: !paused });
21-
}
22-
23-
toggleLock(port) {
24-
const { locked } = this.state;
25-
port.postMessage({ action: 'setLock', payload: !locked });
26-
this.setState({ locked: !locked });
27-
}
28-
29-
render() {
30-
const { paused, locked } = this.state;
31-
const { port } = this.props;
32-
return (
33-
<div className="buttons-container">
34-
<div className="pause-button" onClick={() => this.togglePause(port)}>{(paused) ? 'Resume' : 'Pause'}</div>
35-
<div className="lock-button" onClick={() => this.toggleLock(port)}>{(locked) ? 'Unlock' : 'Lock'}</div>
36-
</div>
37-
);
38-
}
39-
}
4019
export default ButtonsContainer;

src/app/containers/HeadContainer.jsx

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,7 @@
1-
import React, { Component } from 'react';
1+
import React from 'react';
22

3-
class HeadContainer extends Component {
4-
constructor(props) {
5-
super(props);
6-
console.log(this);
7-
}
8-
9-
render() {
10-
return <div className="head-container" />;
11-
}
12-
}
3+
const HeadContainer = () => (
4+
<div className="head-container" />
5+
);
136

147
export default HeadContainer;

src/app/containers/MainContainer.jsx

Lines changed: 47 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,24 +13,40 @@ class MainContainer extends Component {
1313
this.state = {
1414
snapshots: [],
1515
snapshotIndex: 0,
16-
currentIndex: null,
1716
port: null,
17+
mode: {
18+
locked: false,
19+
paused: false,
20+
persist: false,
21+
},
1822
};
1923

2024
autoBind(this);
2125
}
2226

2327
componentDidMount() {
24-
console.log('componentDidMount');
2528
// open connection with background script
2629
const port = chrome.runtime.connect();
2730

2831
// listen for a message containing snapshots from the background script
29-
port.onMessage.addListener((snapshots) => {
30-
const snapshotIndex = snapshots.length - 1;
31-
32-
// set state with the information received from the background script
33-
this.setState({ snapshots, snapshotIndex });
32+
port.onMessage.addListener((message) => {
33+
const { action, payload } = message;
34+
switch (action) {
35+
case 'sendSnapshots': {
36+
const snapshotIndex = payload.length - 1;
37+
38+
// set state with the information received from the background script
39+
this.setState({ snapshots: payload, snapshotIndex });
40+
break;
41+
}
42+
case 'initialConnectSnapshot': {
43+
const { snapshots, mode } = payload;
44+
const snapshotIndex = snapshots.length - 1;
45+
this.setState({ snapshots, snapshotIndex, mode });
46+
break;
47+
}
48+
default:
49+
}
3450
});
3551

3652
// console log if the port with background script disconnects
@@ -78,7 +94,8 @@ class MainContainer extends Component {
7894
port.postMessage({ action: 'emptySnap' });
7995
}
8096

81-
// change the snapshot index, this will change the state shown in the state container but won't change the DOM
97+
// change the snapshot index
98+
// this will change the state shown in the state container but won't change the DOM
8299
handleChangeSnapshot(snapshotIndex) {
83100
// snapshotIndex
84101
// --> 1. affects the action that is highlighted
@@ -88,12 +105,31 @@ class MainContainer extends Component {
88105

89106
handleJumpSnapshot(snapshotIndex) {
90107
const { snapshots, port } = this.state;
91-
this.setState({ currentIndex: snapshotIndex });
92108
port.postMessage({ action: 'jumpToSnap', payload: snapshots[snapshotIndex] });
93109
}
94110

111+
toggleMode(targetMode) {
112+
const { mode, mode: { locked, paused, persist }, port } = this.state;
113+
switch (targetMode) {
114+
case 'paused':
115+
port.postMessage({ action: 'setPause', payload: !paused });
116+
mode.paused = !paused;
117+
break;
118+
case 'locked':
119+
port.postMessage({ action: 'setLock', payload: !locked });
120+
mode.locked = !locked;
121+
break;
122+
case 'persist':
123+
port.postMessage({ action: 'setPersist', payload: !locked });
124+
mode.persist = !persist;
125+
break;
126+
default:
127+
}
128+
this.setState({ mode });
129+
}
130+
95131
render() {
96-
const { snapshots, snapshotIndex, port } = this.state;
132+
const { snapshots, snapshotIndex, mode } = this.state;
97133
return (
98134
<div className="main-container">
99135
<HeadContainer />
@@ -115,7 +151,7 @@ class MainContainer extends Component {
115151
moveForward={this.moveForward}
116152
playForward={this.playForward}
117153
/>
118-
<ButtonsContainer port={port} />
154+
<ButtonsContainer mode={mode} toggleMode={this.toggleMode} />
119155
</div>
120156
</div>
121157
);

src/app/containers/StateContainer.jsx

Lines changed: 31 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,40 @@
1-
import React, { Component } from 'react';
1+
import React from 'react';
2+
import PropTypes from 'prop-types';
23
import {
34
MemoryRouter as Router, Route, NavLink, Switch,
45
} from 'react-router-dom';
56
import Tree from '../components/Tree';
67
import Chart from '../components/Chart';
78

8-
class StateContainer extends Component {
9-
constructor(props) {
10-
super(props);
11-
}
9+
const StateContainer = ({ snapshot }) => (
10+
<Router>
11+
<div className="state-container">
12+
<div className="navbar">
13+
<NavLink className="router-link" activeClassName="is-active" to="/">
14+
Tree
15+
</NavLink>
16+
<NavLink className="router-link" activeClassName="is-active" to="/chart">
17+
Chart
18+
</NavLink>
19+
</div>
20+
<Switch>
21+
<Route path="/chart" render={() => <Chart snapshot={snapshot} />} />
22+
<Route path="/" render={() => <Tree snapshot={snapshot} />} />
23+
</Switch>
24+
</div>
25+
</Router>
26+
);
1227

13-
render() {
14-
const { snapshot } = this.props;
15-
return (
16-
<Router>
17-
<div className="state-container">
18-
<div className="navbar">
19-
<NavLink className="router-link" activeClassName="is-active" exact to="/">
20-
Tree
21-
</NavLink>
22-
<NavLink className="router-link" activeClassName="is-active" exact to="/chart">
23-
Chart
24-
</NavLink>
25-
</div>
26-
<Switch>
27-
<Route path="/chart" render={() => <Chart snapshot={snapshot} />} />
28-
<Route path="/" render={() => <Tree snapshot={snapshot} />} />
29-
</Switch>
30-
</div>
31-
</Router>
32-
);
33-
}
34-
}
35-
{
36-
}
28+
StateContainer.propTypes = {
29+
snapshot: PropTypes.shape({
30+
state: PropTypes.oneOfType([
31+
PropTypes.string,
32+
PropTypes.object,
33+
]),
34+
children: PropTypes.arrayOf(
35+
PropTypes.object,
36+
),
37+
}).isRequired,
38+
};
3739

3840
export default StateContainer;

src/app/containers/TravelContainer.jsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import React from 'react';
2+
import PropTypes from 'prop-types';
23
import MainSlider from '../components/MainSlider';
34

45
const TravelContainer = ({
@@ -28,4 +29,14 @@ const TravelContainer = ({
2829
</div>
2930
</div>
3031
);
32+
33+
TravelContainer.propTypes = {
34+
playForward: PropTypes.func.isRequired,
35+
moveBackward: PropTypes.func.isRequired,
36+
moveForward: PropTypes.func.isRequired,
37+
snapshotsLength: PropTypes.number.isRequired,
38+
handleChangeSnapshot: PropTypes.func.isRequired,
39+
handleJumpSnapshot: PropTypes.func.isRequired,
40+
snapshotIndex: PropTypes.number.isRequired,
41+
};
3142
export default TravelContainer;

src/app/styles/layout/_stateContainer.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
.state-container {
22
font-size: 12px;
3-
overflow: scroll;
3+
overflow: auto;
44
background-color: $brand-color;
55
}
66

0 commit comments

Comments
 (0)