Skip to content

Commit bf57c2f

Browse files
committed
Merge pull request #9 from Solshal/logout
Logout feat, Loading indicator and token verification
2 parents b4d2ec4 + 23b3791 commit bf57c2f

File tree

13 files changed

+187
-24
lines changed

13 files changed

+187
-24
lines changed

dist/assets/app.js

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

dist/assets/app.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
"name": "Solshal",
55
"description": "The easiest way to bookmark and organize links. Be productive.",
6-
"version": "1.0",
6+
"version": "0.0.1",
77

88
"browser_action": {
99
"default_icon": "icon.png",

src/actions/api.js

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ import {
1111
getHeaders
1212
} from '../sources/helpers';
1313
import {
14-
setNotification
14+
setNotification,
15+
setLoading
1516
} from './app';
1617

1718
export function authed(token, tokenDecoded) {
@@ -68,20 +69,24 @@ export function updateFolders(folders) {
6869
* @param token
6970
* @returns {Promise.<T>}
7071
*/
71-
export function verifyToken(token) {
72-
return (dispatch) => {
73-
return fetch(`${types.BASE_API}/auth/verify`, {
72+
export function verifyToken() {
73+
return (dispatch, getState) => {
74+
return fetch(`${types.BASE}/auth/verify`, {
7475
method: 'post',
7576
headers: {
7677
'Accept': 'application/json',
7778
'Content-Type': 'application/json'
7879
},
79-
body: JSON.stringify({token : token})
80+
body: JSON.stringify({token : getState().auth.token})
8081
})
8182
.then(checkStatus)
8283
.then(parseJSON)
8384
.then(json => {
84-
return json.isValid;
85+
if ( json.isValid ) {
86+
return json.isValid
87+
} else {
88+
dispatch(logout());
89+
}
8590
})
8691
.catch((err) => {
8792
dispatch(setNotification(types.RESPONSE_FAILED, err.message));
@@ -98,6 +103,7 @@ export function verifyToken(token) {
98103
*/
99104
export function signin(body) {
100105
return (dispatch) => {
106+
dispatch(setLoading(true));
101107
return fetch(`${types.BASE}/login`, {
102108
method: 'post',
103109
headers: {
@@ -112,18 +118,19 @@ export function signin(body) {
112118
let tokenDecoded = decodeToken(json);
113119
dispatch(saveToken(json));
114120
dispatch(authed(json, tokenDecoded));
121+
dispatch(setLoading(false));
115122
})
116123
.catch((err) => {
117124
dispatch(unauthed());
118125
dispatch(setNotification(types.RESPONSE_FAILED, err.message));
126+
dispatch(setLoading(false));
119127
})
120128
}
121129
}
122130

123131
/**
124132
* Get latest folders
125133
* once successful set current folder if existent
126-
* @param currentFolderParam {string}
127134
* @returns {Function}
128135
*/
129136
export function getFolders() {
@@ -149,11 +156,11 @@ export function getFolders() {
149156
* then call save collection
150157
* @param newFolder
151158
* @param newCollection
152-
* @param currentFolderParam
153159
* @returns {function()}
154160
*/
155161
export function addNewFolderAndSaveCollection(newFolder, newCollection) {
156162
return (dispatch) => {
163+
dispatch(setLoading(true));
157164
let endpoint = `${types.BASE_API}/users/${getUserId()}/folders`;
158165
return fetch(endpoint, {
159166
method: 'post',
@@ -168,8 +175,10 @@ export function addNewFolderAndSaveCollection(newFolder, newCollection) {
168175
dispatch(updateFolders(json.folders));
169176
// save new collection
170177
dispatch(saveCollection(newCollection));
178+
dispatch(setLoading(false));
171179
}).catch((err) => {
172180
dispatch(setNotification(types.RESPONSE_FAILED, err.message));
181+
dispatch(setLoading(false));
173182
})
174183
}
175184
}
@@ -181,6 +190,7 @@ export function addNewFolderAndSaveCollection(newFolder, newCollection) {
181190
*/
182191
export function saveCollection(body) {
183192
return (dispatch) => {
193+
dispatch(setLoading(true));
184194
let endpoint = `${types.BASE_API}/users/${getUserId()}/folders/${body.folderId}/collections`;
185195
return fetch(endpoint, {
186196
method: 'post',
@@ -191,7 +201,9 @@ export function saveCollection(body) {
191201
.then(parseJSON)
192202
.then(json => {
193203
dispatch(setNotification(types.RESPONSE_SUCCESSFUL));
204+
dispatch(setLoading(false));
194205
}).catch((err) => {
206+
dispatch(setLoading(false));
195207
dispatch(setNotification(types.RESPONSE_FAILED, err.message));
196208
})
197209
}

src/actions/app.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,10 @@ export function resetNotification() {
3838
isOpen: false
3939
}
4040
}
41+
42+
export function setLoading(value) {
43+
return {
44+
type: types.SET_LOADING,
45+
isLoading: value
46+
}
47+
}

src/actions/constants.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,4 @@ export const RESPONSE_SUCCESSFUL = 'RESPONSE_SUCCESSFUL';
1616
export const RESPONSE_FAILED = 'RESPONSE_FAILED';
1717
export const RESPONSE_WARNING = 'RESPONSE_WARNING';
1818
export const SET_NOTIFICATION = 'SET_NOTIFICATION';
19+
export const SET_LOADING = 'SET_LOADING';

src/components/header.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import React, {Component} from 'React';
2+
import { logout } from '../actions/api';
3+
4+
class Header extends Component {
5+
logout(e) {
6+
e.preventDefault();
7+
let { dispatch } = this.props;
8+
dispatch(logout());
9+
}
10+
11+
resolveLogout() {
12+
let { isAuthenticated } = this.props;
13+
14+
if ( isAuthenticated ) {
15+
return (
16+
<a className="logout" title="logout" onClick={this.logout.bind(this)}>logout</a>
17+
)
18+
} else {
19+
return null;
20+
}
21+
}
22+
23+
render() {
24+
return (
25+
<div className="header">
26+
{this.resolveLogout()}
27+
</div>
28+
)
29+
}
30+
}
31+
32+
export default Header;

src/components/unauthorized.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import React, { Component } from 'react';
22
import ReactDOM from 'react-dom';
3+
import Button from '../containers/button';
34
import { signin } from '../actions/api';
45

56
class Unauthorized extends Component {
@@ -31,7 +32,7 @@ class Unauthorized extends Component {
3132
<label htmlFor="password">
3233
<input type="password" ref="password" name="password" placeholder="password" required />
3334
</label>
34-
<button type="submit" className="app-form_button">login</button>
35+
<Button label="login" />
3536
</form>
3637
</div>
3738
</div>

src/containers/app.js

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,35 @@ import React, { Component } from 'react';
55
import { connect } from 'react-redux';
66
import Notification from './notification';
77
import Authorized from './authorized';
8-
import Unauthorized from './../components/unauthorized';
8+
import Unauthorized from '../components/unauthorized';
9+
import Header from '../components/header';
910

11+
import { verifyToken } from '../actions/api';
1012

1113
class App extends Component {
14+
componentDidMount() {
15+
let { dispatch, token } = this.props;
16+
if ( token ) {
17+
dispatch(verifyToken());
18+
}
19+
}
20+
1221
resolveComponent() {
1322
let { isAuthenticated, dispatch } = this.props;
1423

15-
if ( isAuthenticated ) {
24+
if ( isAuthenticated) {
1625
return <Authorized />
1726
} else {
1827
return <Unauthorized dispatch={dispatch} />
1928
}
2029
}
2130

2231
render() {
32+
let { isAuthenticated, dispatch } = this.props;
33+
2334
return (
2435
<div>
36+
<Header isAuthenticated={isAuthenticated} dispatch={dispatch} />
2537
{this.resolveComponent()}
2638
<Notification />
2739
</div>
@@ -30,8 +42,9 @@ class App extends Component {
3042
}
3143

3244
function mapStateToProps(state) {
33-
let { isAuthenticated } = state.auth;
45+
let { isAuthenticated, token } = state.auth;
3446
return {
47+
token: token,
3548
isAuthenticated: isAuthenticated
3649
}
3750

src/containers/authorized.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import React, { Component } from 'react';
44
import { connect } from 'react-redux';
55
import ReactDom from 'react-dom';
6+
import Button from './button';
67
import {
78
getCurrentTabUrl
89
} from '../actions/app';
@@ -93,7 +94,7 @@ class Authorized extends Component {
9394
</select>
9495
<input type="text" ref="newFolder" name="newFolder" placeholder="Add new folder"/>
9596
</label>
96-
<button type="submit" className="app-form_button">save</button>
97+
<Button label="save" />
9798
</form>
9899
</div>
99100
</div>

0 commit comments

Comments
 (0)