Skip to content

Commit e81a209

Browse files
authored
Merge pull request #22 from xsnippet/redux
Recent snippets
2 parents 07231b5 + 810073b commit e81a209

File tree

9 files changed

+152
-44
lines changed

9 files changed

+152
-44
lines changed

.eslintrc.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"jsx-a11y/anchor-is-valid": ["error", {
88
"components": ["Link"],
99
"specialLink": ["to"]
10-
}]
10+
}],
11+
"react/prop-types": [0]
1112
}
1213
}

package-lock.json

Lines changed: 45 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,16 @@
2020
],
2121
"dependencies": {
2222
"codemirror": "^5.33.0",
23+
"immutable": "^3.8.2",
2324
"prop-types": "^15.6.0",
2425
"react": "^16.0.0",
2526
"react-codemirror2": "^3.0.7",
2627
"react-custom-scrollbars": "^4.2.1",
2728
"react-dom": "^16.0.0",
28-
"react-router-dom": "^4.2.2"
29+
"react-redux": "^5.0.6",
30+
"react-router-dom": "^4.2.2",
31+
"redux": "^3.7.2",
32+
"redux-thunk": "^2.2.0"
2933
},
3034
"devDependencies": {
3135
"babel-cli": "^6.26.0",

src/actions/index.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
export const setRecentSnippets = snippets => ({
2+
type: 'SET_RECENT_SNIPPETS',
3+
snippets,
4+
});
5+
6+
export const fetchRecentSnippets = dispatch => (
7+
fetch('http://api.xsnippet.org/snippets')
8+
.then(response => response.json())
9+
.then(json => dispatch(setRecentSnippets(json)))
10+
);

src/components/RecentSnippetItem.jsx

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import React from 'react';
2+
import { Link } from 'react-router-dom';
3+
4+
const RecentSnippetItem = ({ snippet }) => (
5+
<li className="recent-snippet-item">
6+
<div className="recent-snippet-data">
7+
<div>
8+
<span className="recent-snippet-data-title">{snippet.get('title')}</span>
9+
<span className="recent-snippet-data-lang">[ {snippet.get('syntax', 'Text')} ]</span>
10+
</div>
11+
<span className="recent-snippet-data-author">By Guest</span>
12+
</div>
13+
<div>
14+
<button className="recent-snippet-button light">Raw</button>
15+
<button className="recent-snippet-button light">Download</button>
16+
<Link to={`${snippet.get('id')}`} className="recent-snippet-button">Show</Link>
17+
</div>
18+
</li>
19+
);
20+
21+
export default RecentSnippetItem;

src/components/RecentSnippets.jsx

Lines changed: 24 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,31 @@
11
import React from 'react';
2-
import { Link } from 'react-router-dom';
2+
import { connect } from 'react-redux';
33

44
import Title from './common/Title';
5+
import RecentSnippetItem from './RecentSnippetItem';
6+
import * as actions from '../actions';
57

68
import '../styles/RecentSnippets.styl';
79

8-
const RecentSnippets = () => (
9-
[
10-
<Title title="Recent snippets" additionalClass="recent-title" key="title-recent" />,
11-
<ul className="recent-snippet" key="recent-snippet">
12-
<li className="recent-snippet-item">
13-
<div className="recent-snippet-data">
14-
<div>
15-
<span className="recent-snippet-data-title">#235435, Untitled</span>
16-
<span className="recent-snippet-data-lang">[ Java ]</span>
17-
</div>
18-
<span className="recent-snippet-data-author">By Guest</span>
19-
</div>
20-
<div>
21-
<button className="recent-snippet-button light">Raw</button>
22-
<button className="recent-snippet-button light">Download</button>
23-
<Link to="/2" className="recent-snippet-button">Show</Link>
24-
</div>
25-
</li>
26-
<li className="recent-snippet-item">
27-
<div className="recent-snippet-data">
28-
<div>
29-
<span className="recent-snippet-data-title">#235435, Untitled</span>
30-
<span className="recent-snippet-data-lang">[ Java ]</span>
31-
</div>
32-
<span className="recent-snippet-data-author">By Guest</span>
33-
</div>
34-
<div>
35-
<button className="recent-snippet-button light">Raw</button>
36-
<button className="recent-snippet-button light">Download</button>
37-
<Link to="/3" className="recent-snippet-button">Show</Link>
38-
</div>
39-
</li>
40-
</ul>,
41-
]
42-
);
10+
class RecentSnippets extends React.Component {
11+
componentDidMount() {
12+
const { dispatch } = this.props;
13+
dispatch(actions.fetchRecentSnippets);
14+
}
4315

44-
export default RecentSnippets;
16+
render() {
17+
const { snippets, recent } = this.props;
18+
19+
return ([
20+
<Title title="Recent snippets" additionalClass="recent-title" key="title-recent" />,
21+
<ul className="recent-snippet" key="recent-snippet">
22+
{recent.map(id => <RecentSnippetItem key={id} snippet={snippets.get(id)} />)}
23+
</ul>,
24+
]);
25+
}
26+
}
27+
28+
export default connect(state => ({
29+
snippets: state.snippets,
30+
recent: state.recent,
31+
}))(RecentSnippets);

src/index.jsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
import React from 'react';
22
import ReactDOM from 'react-dom';
33
import { BrowserRouter } from 'react-router-dom';
4+
import { Provider } from 'react-redux';
45

56
import App from './components/App';
7+
import store from './store';
68

79
ReactDOM.render(
810
(
9-
<BrowserRouter>
10-
<App />
11-
</BrowserRouter>
11+
<Provider store={store}>
12+
<BrowserRouter>
13+
<App />
14+
</BrowserRouter>
15+
</Provider>
1216
), document.getElementById('root'),
1317
);

src/reducers/index.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { List, Map } from 'immutable';
2+
import { combineReducers } from 'redux';
3+
4+
const snippets = (state = Map(), action) => {
5+
switch (action.type) {
6+
case 'SET_RECENT_SNIPPETS':
7+
return state.merge(action.snippets.map(snippet => [snippet.id, snippet]));
8+
9+
default:
10+
return state;
11+
}
12+
};
13+
14+
const recent = (state = List(), action) => {
15+
switch (action.type) {
16+
case 'SET_RECENT_SNIPPETS':
17+
return List(action.snippets.map(snippet => snippet.id));
18+
19+
default:
20+
return state;
21+
}
22+
};
23+
24+
export default combineReducers({
25+
snippets,
26+
recent,
27+
});

src/store/index.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import * as redux from 'redux';
2+
import thunk from 'redux-thunk';
3+
4+
import reducer from '../reducers';
5+
6+
// Redux Thunk middleware allows you to write action creators that return a
7+
// function instead of an action. The thunk can be used to delay the dispatch
8+
// of an action, or to dispatch only if a certain condition is met. The former
9+
// is the case for XSnippet Web since we need to fetch data via HTTP API first
10+
// and then dispatch it to store.
11+
export default redux.createStore(reducer, redux.applyMiddleware(thunk));

0 commit comments

Comments
 (0)