Skip to content

Commit 9950072

Browse files
committed
Add loader and retry to get puzzle data action. Will retry every 5 seconds for 3 minutes.
1 parent d4b506a commit 9950072

File tree

11 files changed

+118
-10
lines changed

11 files changed

+118
-10
lines changed

applications/kr8sswordz-pages/src/actions/actionTypes.js

+2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
export const puzzle = {
2+
PUZZLE_LOADING: 'PUZZLE_LOADING',
23
CLEAR_PUZZLE_DATA: 'CLEAR_PUZZLE_DATA',
34
GET_PUZZLE_DATA_SUCCESS: 'GET_PUZZLE_DATA_SUCCESS',
45
GET_PUZZLE_DATA_FAILURE: 'GET_PUZZLE_DATA_FAILURE',
@@ -10,6 +11,7 @@ export const puzzle = {
1011
};
1112

1213
export const websocket = {
14+
CONNECTION_LOADING: 'CONNECTION_LOADING',
1315
CONNECT_TO_SOCKET: 'CONNECT_TO_SOCKET',
1416
DISCONNECT_FROM_SOCKET: 'DISCONNECT_FROM_SOCKET',
1517
GET_PODS: 'GET_PODS',

applications/kr8sswordz-pages/src/actions/puzzleActions.js

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import fetchRetry from 'fetch-retry';
12
import * as actions from './actionTypes';
23
import constants from '../constants';
34
const baseUrl = `http://puzzle.${constants.minikubeIp}.xip.io/puzzle/v1`;
@@ -13,7 +14,11 @@ export function getPuzzleDataFailure () {
1314

1415
export function getPuzzleData () {
1516
return dispatch => {
16-
return fetch(`${baseUrl}/crossword`)
17+
dispatch({type: actions.puzzle.PUZZLE_LOADING});
18+
return fetchRetry(`${baseUrl}/crossword`, {
19+
retries: 36,
20+
retryDelay: 5000
21+
})
1722
.then((resp) => {
1823
return resp.json();
1924
})

applications/kr8sswordz-pages/src/actions/webSocketActions.js

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ export function getPods () {
2525

2626
export function connectToSocket () {
2727
return dispatch => {
28+
dispatch({type: types.websocket.CONNECTION_LOADING});
2829
socket.open(() => {
2930
dispatch({type: 'CONNECT_TO_SOCKET'});
3031
});

applications/kr8sswordz-pages/src/components/App.js

+27-2
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,23 @@
11
import React, { PropTypes } from 'react';
2+
import { connect } from 'react-redux';
23
import Header from './shared/Header';
4+
import Loader from './shared/Loader';
35

46
/**
57
* The App component for the project.
68
*/
79
class App extends React.Component {
810
render () {
11+
let loading = false;
12+
if (this.props.webSocketLoading || this.props.puzzleLoading) {
13+
loading = true;
14+
}
15+
916
return (
1017
<div>
18+
{loading &&
19+
<Loader />
20+
}
1121
<Header />
1222
{this.props.children}
1323
</div>
@@ -19,7 +29,22 @@ App.propTypes = {
1929
/**
2030
* The child elements of the app.
2131
*/
22-
children: PropTypes.element
32+
children: PropTypes.element,
33+
/**
34+
* A boolean indicating whether the websocket connection is loaded or not.
35+
*/
36+
webSocketLoading: PropTypes.bool,
37+
/**
38+
* A boolean indicating whether the puzzle is loaded or not.
39+
*/
40+
puzzleLoading: PropTypes.bool
2341
};
2442

25-
export default App;
43+
function mapStateToProps (state) {
44+
return {
45+
webSocketLoading: state.webSocket.loading,
46+
puzzleLoading: state.puzzle.loading
47+
};
48+
}
49+
50+
export default connect(mapStateToProps, null)(App);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import React from 'react';
2+
3+
function Loader (props) {
4+
return (
5+
<div className="background-fade item-center">
6+
<div className="loader"></div>
7+
</div>
8+
);
9+
}
10+
11+
export default Loader;

applications/kr8sswordz-pages/src/reducers/puzzleReducer.js

+9-2
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,21 @@ const initialState = {
55
fromMongo: false,
66
sendingData: false,
77
puzzleId: '',
8-
puzzleData: []
8+
puzzleData: [],
9+
loading: false
910
};
1011

1112
export default function puzzleReducer (state = initialState, action) {
1213
switch (action.type) {
14+
case types.puzzle.PUZZLE_LOADING: {
15+
return Object.assign({}, state, {
16+
loading: true
17+
});
18+
}
1319
case types.puzzle.GET_PUZZLE_DATA_SUCCESS: {
1420
return Object.assign({}, state, {
15-
puzzleData: action.data.words
21+
puzzleData: action.data.words,
22+
loading: false
1623
});
1724
}
1825
case types.puzzle.GET_PUZZLE_DATA_FAILURE: {

applications/kr8sswordz-pages/src/reducers/websocketReducer.js

+17-4
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,21 @@ import * as types from '../actions/actionTypes';
33
const initialState = {
44
connected: false,
55
pods: [],
6-
activePod: undefined
6+
activePod: undefined,
7+
loading: false
78
};
89

910
export default function websocketReducer (state = initialState, action) {
1011
switch (action.type) {
12+
case types.websocket.CONNECTION_LOADING: {
13+
return Object.assign({}, state, {
14+
loading: true
15+
});
16+
}
1117
case types.websocket.CONNECT_TO_SOCKET: {
1218
return Object.assign({}, state, {
13-
connected: true
19+
connected: true,
20+
loading: false
1421
});
1522
}
1623
case types.websocket.DISCONNECT_FROM_SOCKET: {
@@ -19,14 +26,20 @@ export default function websocketReducer (state = initialState, action) {
1926
});
2027
}
2128
case types.websocket.GET_PODS: {
22-
return Object.assign({}, state, { pods: action.pods });
29+
return Object.assign({}, state, {
30+
pods: action.pods,
31+
loading: false
32+
});
2333
}
2434
case types.websocket.POD_UP: {
2535
if (state.pods.includes(action.pod)) {
2636
return state;
2737
} else {
2838
const pods = [...state.pods, action.pod];
29-
return Object.assign({}, state, { pods });
39+
return Object.assign({}, state, {
40+
pods,
41+
loading: false
42+
});
3043
}
3144
}
3245
case types.websocket.POD_DOWN: {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
@import '../utils/variables';
2+
3+
.loader {
4+
border: 16px solid $brand-gray;
5+
border-top: 16px solid $kubernetes-blue;
6+
border-radius: 50%;
7+
width: 120px;
8+
height: 120px;
9+
animation: spin 2s linear infinite;
10+
}
11+
12+
@keyframes spin {
13+
100% { transform: rotate(360deg); }
14+
}
15+
16+
.item-center {
17+
display: flex;
18+
align-items: center;
19+
justify-content: center;
20+
}
21+
22+
@mixin fadein-opacity($fade-time: 1s) {
23+
animation: fadein $fade-time ease-in-out forwards;
24+
}
25+
26+
.background-fade {
27+
@include fadein-opacity(250ms);
28+
position: fixed;
29+
top: 0;
30+
left: 0;
31+
min-height: 100%;
32+
width: 100%;
33+
background-color: $transparent-black;
34+
z-index: 11;
35+
}
36+
37+
38+
@keyframes fadein {
39+
from { opacity: 0; }
40+
to { opacity: 1; }
41+
}

applications/kr8sswordz-pages/src/styles/molecules/_molecules.scss

+1
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@
66
@import './image-column';
77
@import './puzzle';
88
@import './slider-container';
9+
@import './loader';

applications/kr8sswordz-pages/src/styles/utils/_variables.scss

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
$true-white: #fff;
33
$off-white: #eee;
44
$kubernetes-blue: #158d8b;
5+
$transparent-black: rgba(0,0,0,0.2);
56
$base-font-size: 1vw;
67
$brand-blue: #303e48;
78
$brand-gray: #dee0e2;

package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
"dependencies": {
77
"cmdify": "^0.0.4",
88
"colors": "^1.1.2",
9+
"fetch-retry": "^1.1.0",
910
"inquirer": "^3.0.6",
1011
"rx": "^4.1.0",
1112
"yamljs": "^0.2.8"
@@ -17,7 +18,7 @@
1718
"part1": "node start.js part1.yml",
1819
"part2": "node start.js part2.yml",
1920
"part3": "node start.js part3.yml",
20-
"part4": "node start.js part4.yml"
21+
"part4": "node start.js part4.yml"
2122
},
2223
"repository": {
2324
"type": "git",

0 commit comments

Comments
 (0)