Skip to content
This repository has been archived by the owner on May 12, 2022. It is now read-only.

Commit

Permalink
Fetch notes from server
Browse files Browse the repository at this point in the history
  • Loading branch information
arkanoryn committed Aug 6, 2017
1 parent 828f03d commit 3ca3c72
Show file tree
Hide file tree
Showing 11 changed files with 116 additions and 36 deletions.
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
REACT_APP_API_HOST_URL=http://192.168.55.55:4000/api
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@ npm-debug.log*
yarn-debug.log*
yarn-error.log*

.env
server
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
## Setup
* Install [Yarn](yarnpkg.com/lang/en/)
* `yarn install`
* `cp .env.example .env`
* `yarn start`

Yarn should start a new tab on your browser linking to `localhost:3000`.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"private": true,
"dependencies": {
"antd": "^2.12.3",
"dotenv": "^4.0.0",
"lodash": "^4.17.4",
"react": "^15.6.1",
"react-dom": "^15.6.1",
Expand Down
38 changes: 38 additions & 0 deletions src/API/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import fetch from 'isomorphic-fetch';

const API_HOST = process.env.REACT_APP_API_HOST_URL;

function headers() {
return {
Accept: 'application/json',
'Content-Type': 'application/json',
};
}

function parseResponse(response) {
return response.json().then((json) => {
if (!response.ok) {
return Promise.reject(json);
}
return json;
});
}

function queryString(params) {
const query = Object.keys(params)
.map((k) => `${encodeURIComponent(k)}=${encodeURIComponent(params[k])}`)
.join('&');
return `${query.length ? '?' : ''}${query}`;
}

const API = {
fetch(url, params = {}) {
return fetch(`${API_HOST}${url}${queryString(params)}`, {
method: 'GET',
headers: headers(),
})
.then(parseResponse);
},
}

export default API;
30 changes: 29 additions & 1 deletion src/NotesList/Actions.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,19 @@
import { OVER_IN_NOTE, OVER_OUT_NOTE, NEW_NOTE, SELECT_NOTE } from './Types';
import { OVER_IN_NOTE, OVER_OUT_NOTE, NEW_NOTE, RECEIVE_NOTES, REQUEST_NOTES, SELECT_NOTE } from './Types';
import API from '../API';

export const fetchNotes = () => {
return function(dispatch) {
dispatch(requestNotes());

return API.fetch('/notes')
.then((response) => {
dispatch(receiveNotes(response));
})
.catch(() => {
dispatch({ type: 'FETCH_NOTES_FAILURE' });
});
};
};

export const overInNote = function overInNote(id) {
return ({
Expand All @@ -14,6 +29,19 @@ export const overOutNote = function overOutNote(id) {
});
}

export const requestNotes = () => {
return {
type: REQUEST_NOTES
};
};

export const receiveNotes = (json) => {
return {
type: RECEIVE_NOTES,
notes: json.data
};
};

export const selectNote = function selectNote(id) {
return ({
type: SELECT_NOTE,
Expand Down
36 changes: 20 additions & 16 deletions src/NotesList/Reducer.js
Original file line number Diff line number Diff line change
@@ -1,27 +1,18 @@
import _ from 'lodash';
import { OVER_IN_NOTE, OVER_OUT_NOTE, NEW_NOTE, SELECT_NOTE } from './Types';
import { GENERAL, UPDATE_BODY, UPDATE_STATUS, UPDATE_TITLE, TRASH } from '../Note/Types';
import NoteReducer from '../Note/Reducer'

const mockNotes = [
{id: 1, title: "This is my first note", body: "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec hendrerit tempor tellus. Donec pretium posuere tellus. Proin quam nisl, tincidunt et, mattis eget, convallis nec, purus. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nulla posuere. Donec vitae dolor. Nullam tristique diam non turpis. Cras placerat accumsan nulla. Nullam rutrum. Nam vestibulum accumsan nisl.", status: GENERAL},
{id: 2, title: "Lorem", body: "Nullam libero mauris, consequat quis, varius et, dictum id, arcu.\nDonec at pede.\nSed diam.", status: GENERAL},
{id: 3, title: "Ipsum", body: "Nullam libero mauris, consequat quis, varius et, dictum id, arcu.\nDonec at pede.\nSed diam.", status: GENERAL},
{id: 4, title: "Ipsum", body: "Nullam libero mauris, consequat quis, varius et, dictum id, arcu.\nDonec at pede.\nSed diam.", status: TRASH},
{id: 5, title: "Ipsum", body: "Nullam libero mauris, consequat quis, varius et, dictum id, arcu.\nDonec at pede.\nSed diam.", status: GENERAL},
{id: 6, title: "Ipsum", body: "Nullam libero mauris, consequat quis, varius et, dictum id, arcu.\nDonec at pede.\nSed diam.", status: TRASH},
{id: 7, title: "Ipsum", body: "Nullam libero mauris, consequat quis, varius et, dictum id, arcu.\nDonec at pede.\nSed diam.", status: GENERAL},
];
import _ from 'lodash';
import { OVER_IN_NOTE, OVER_OUT_NOTE, NEW_NOTE, REQUEST_NOTES, RECEIVE_NOTES, SELECT_NOTE } from './Types';
import { GENERAL, UPDATE_BODY, UPDATE_STATUS, UPDATE_TITLE } from '../Note/Types';
import NoteReducer from '../Note/Reducer'

const latestAvailableId = function latestAvailableId(notes) {
let lastNote = _.last(notes);
let lastNote = _.last(notes) || {id: 0};

return (lastNote.id + 1);
};

const initialState = {
isFetching: false,
noteId: -1,
notes: mockNotes,
notes: [],
status: GENERAL,
};

Expand Down Expand Up @@ -60,6 +51,19 @@ let NotesListReducer = (state = initialState, action) => {
}
));

case REQUEST_NOTES:
return (Object.assign({}, state, {isFetching: true}));

case RECEIVE_NOTES:
return (Object.assign(
{},
state,
{
isFetching: false,
notes: action.notes,
}
));

case SELECT_NOTE:
return (Object.assign({}, state, {...state, noteId: action.id}));

Expand Down
8 changes: 5 additions & 3 deletions src/NotesList/Types.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
export const OVER_IN_NOTE = 'OVER_IN_NOTE';
export const OVER_IN_NOTE = 'OVER_IN_NOTE';
export const OVER_OUT_NOTE = 'OVER_OUT_NOTE';
export const SELECT_NOTE = 'SELECT_NOTE';
export const NEW_NOTE = 'NEW_NOTE';
export const SELECT_NOTE = 'SELECT_NOTE';
export const NEW_NOTE = 'NEW_NOTE';
export const REQUEST_NOTES = 'REQUEST_NOTES';
export const RECEIVE_NOTES = 'RECEIVE_NOTES';
10 changes: 5 additions & 5 deletions src/SubMenu/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,9 @@ const RenderSubMenu = function RenderSubMenu({match,
<Sider style={{ overflow: 'auto', height: '100vh', position: 'fixed', left: 120, backgroundColor: '#fff' }}>
<Header onNewNoteClick={onNewNoteClick} />

<Spin size="large" spinning={isFetching} delay={500}>
<NotesList notes={notes} isTrash={isTrash} onNoteClick={onNoteClick} action={action} />
</Spin>
<Spin spinning={isFetching} delay={2000} style={{ marginTop: '30px' }}>
<NotesList notes={notes} isTrash={isTrash} onNoteClick={onNoteClick} action={action} />
</Spin>
</Sider>
);
};
Expand All @@ -61,8 +61,8 @@ RenderSubMenu.propTypes = Props;

const mapStateToProps = function mapStateToProps(state) {
return ({
allNotes: state.NotesListReducer.notes,
isFetching: true,
allNotes: state.NotesListReducer.notes,
isFetching: state.NotesListReducer.isFetching,
});
};

Expand Down
24 changes: 14 additions & 10 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
import { createLogger } from 'redux-logger';
import { BrowserRouter as Router } from 'react-router-dom';
import './index.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
import NoteApp from './Reducers';
import React from 'react';
import ReactDOM from 'react-dom';
import thunkMiddleware from 'redux-thunk';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
import { createLogger } from 'redux-logger';
import { BrowserRouter as Router } from 'react-router-dom';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
import NoteApp from './Reducers';
import { fetchNotes } from './NotesList/Actions';

const loggerMiddleware = createLogger();

let store = createStore(NoteApp,
applyMiddleware(loggerMiddleware)
applyMiddleware(thunkMiddleware, loggerMiddleware)
);

store.dispatch(fetchNotes()).then(() => console.log(store.getState()));

ReactDOM.render(
<Provider store={store}>
<Router>
Expand Down
2 changes: 1 addition & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2056,7 +2056,7 @@ dot-prop@^3.0.0:
dependencies:
is-obj "^1.0.0"

[email protected]:
[email protected], dotenv@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-4.0.0.tgz#864ef1379aced55ce6f95debecdce179f7a0cd1d"

Expand Down

0 comments on commit 3ca3c72

Please sign in to comment.