Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
thalia
ThaliApp
Commits
951826ad
Commit
951826ad
authored
Oct 11, 2017
by
Wietse Kuipers
Browse files
Merge branch 'feature/error-screens' into 'master'
Add nicer error screens/handling Closes #18 See merge request
!71
parents
a516fa8b
ff1f1041
Changes
15
Show whitespace changes
Inline
Side-by-side
app/components/Calendar.js
View file @
951826ad
import
React
,
{
Component
}
from
'
react
'
;
import
PropTypes
from
'
prop-types
'
;
import
{
Text
,
View
,
SectionList
}
from
'
react-native
'
;
import
{
Text
,
View
,
SectionList
,
ScrollView
,
RefreshControl
}
from
'
react-native
'
;
import
{
connect
}
from
'
react-redux
'
;
import
Moment
from
'
moment
'
;
import
'
moment/locale/nl
'
;
import
*
as
calendarActions
from
'
../actions/calendar
'
;
import
EventCard
from
'
./EventCard
'
;
import
LoadingScreen
from
'
./LoadingScreen
'
;
import
ErrorScreen
from
'
./ErrorScreen
'
;
import
styles
from
'
./style/calendar
'
;
...
...
@@ -123,17 +125,39 @@ class Calendar extends Component {
};
render
()
{
if
(
this
.
props
.
eventList
.
length
===
0
&&
!
this
.
props
.
loading
)
{
if
(
this
.
props
.
status
===
'
initial
'
)
{
return
<
LoadingScreen
/>
;
}
else
if
(
this
.
props
.
status
===
'
failure
'
)
{
return
(
<
View
>
<
Text
>
No
events
found
!
<
/Text
>
<
/View
>
<
ScrollView
contentContainerStyle
=
{
styles
.
content
}
refreshControl
=
{(
<
RefreshControl
onRefresh
=
{
this
.
handleRefresh
}
refreshing
=
{
this
.
props
.
loading
}
/
>
)}
>
<
ErrorScreen
message
=
"
Sorry! We couldn't load any data.
"
/>
<
/ScrollView
>
);
}
else
if
(
this
.
props
.
eventList
.
length
===
0
)
{
return
(
<
ScrollView
contentContainerStyle
=
{
styles
.
content
}
refreshControl
=
{(
<
RefreshControl
onRefresh
=
{
this
.
handleRefresh
}
refreshing
=
{
this
.
props
.
loading
}
/
>
)}
>
<
ErrorScreen
message
=
"
No events found!
"
/>
<
/ScrollView
>
);
}
return
(
<
View
>
<
View
style
=
{
styles
.
content
}
>
<
SectionList
style
=
{
styles
.
sectionList
}
renderItem
=
{
renderItem
}
...
...
@@ -166,12 +190,14 @@ Calendar.propTypes = {
url
:
PropTypes
.
string
,
})).
isRequired
,
loading
:
PropTypes
.
bool
.
isRequired
,
status
:
PropTypes
.
string
.
isRequired
,
refresh
:
PropTypes
.
func
.
isRequired
,
};
const
mapStateToProps
=
state
=>
({
eventList
:
state
.
calendar
.
eventList
,
loading
:
state
.
calendar
.
loading
,
status
:
state
.
calendar
.
status
,
});
const
mapDispatchToProps
=
dispatch
=>
({
...
...
app/components/ErrorScreen.js
0 → 100644
View file @
951826ad
import
React
from
'
react
'
;
import
{
Image
,
Text
,
View
}
from
'
react-native
'
;
import
PropTypes
from
'
prop-types
'
;
import
styles
from
'
./style/errorScreen
'
;
const
smiley
=
require
(
'
../img/smiley.png
'
);
const
ErrorScreen
=
props
=>
(
<
View
style
=
{
styles
.
content
}
>
<
Image
source
=
{
smiley
}
style
=
{
styles
.
image
}
/
>
<
Text
style
=
{
styles
.
text
}
>
{
props
.
message
}
<
/Text
>
<
Text
style
=
{
styles
.
text
}
>
Try
again
later
.
<
/Text
>
<
/View
>
);
ErrorScreen
.
propTypes
=
{
message
:
PropTypes
.
string
.
isRequired
,
};
export
default
ErrorScreen
;
app/components/Event.js
View file @
951826ad
...
...
@@ -8,6 +8,7 @@ import 'moment/locale/nl';
import
styles
from
'
./style/event
'
;
import
MemberView
from
'
./MemberView
'
;
import
LoadingScreen
from
'
./LoadingScreen
'
;
import
ErrorScreen
from
'
./ErrorScreen
'
;
import
{
colors
}
from
'
../style
'
;
class
Event
extends
Component
{
...
...
@@ -252,9 +253,7 @@ class Event extends Component {
);
}
return
(
<
ScrollView
backgroundColor
=
{
colors
.
background
}
contentContainerStyle
=
{
styles
.
eventView
}
>
<
Text
>
Kon
het
evenement
niet
laden
...
<
/Text
>
<
/ScrollView
>
<
ErrorScreen
message
=
"
Could not load the event...
"
/>
);
}
}
...
...
app/components/Pizza.js
View file @
951826ad
...
...
@@ -6,19 +6,13 @@ import Icon from 'react-native-vector-icons/MaterialIcons';
import
Moment
from
'
moment
'
;
import
'
moment/locale/nl
'
;
import
LoadingScreen
from
'
./LoadingScreen
'
;
import
ErrorScreen
from
'
./ErrorScreen
'
;
import
{
retrievePizzaInfo
,
cancelOrder
,
orderPizza
}
from
'
../actions/pizza
'
;
import
styles
from
'
./style/pizza
'
;
import
{
colors
}
from
'
../style
'
;
class
Pizza
extends
Component
{
constructor
(
props
)
{
super
(
props
);
this
.
state
=
{
refreshing
:
false
,
};
}
getProductFromList
=
(
pk
,
pizzaList
)
=>
{
for
(
let
i
=
0
;
i
<
pizzaList
.
length
;
i
+=
1
)
{
if
(
pizzaList
[
i
].
pk
===
pk
)
{
...
...
@@ -122,9 +116,7 @@ class Pizza extends Component {
);
handleRefresh
=
()
=>
{
this
.
setState
({
refreshing
:
true
});
this
.
props
.
retrievePizzaInfo
(
this
.
props
.
token
);
this
.
setState
({
refreshing
:
false
});
};
render
()
{
...
...
@@ -135,16 +127,13 @@ class Pizza extends Component {
<
ScrollView
refreshControl
=
{
<
RefreshControl
refreshing
=
{
this
.
state
.
refresh
ing
}
refreshing
=
{
this
.
props
.
load
ing
}
onRefresh
=
{
this
.
handleRefresh
}
/
>
}
contentContainerStyle
=
{
styles
.
content
}
>
<
View
style
=
{
styles
.
content
}
>
<
Text
style
=
{
styles
.
title
}
>
Something
went
wrong
while
retrieving
pizza
info
.
<
/Text
>
<
/View
>
<
ErrorScreen
message
=
"
Sorry! We couldn't load any data.
"
/>
<
/ScrollView
>
);
}
else
if
(
!
this
.
props
.
event
)
{
...
...
@@ -152,16 +141,15 @@ class Pizza extends Component {
<
ScrollView
refreshControl
=
{
<
RefreshControl
refreshing
=
{
this
.
state
.
refresh
ing
}
refreshing
=
{
this
.
props
.
load
ing
}
onRefresh
=
{
this
.
handleRefresh
}
/
>
}
contentContainerStyle
=
{
styles
.
content
}
>
<
View
style
=
{
styles
.
content
}
>
<
Text
style
=
{
styles
.
title
}
>
There
is
currently
no
event
for
which
you
can
order
food
.
<
/Text
>
<
/View
>
<
/ScrollView
>
);
}
...
...
@@ -186,7 +174,7 @@ class Pizza extends Component {
<
ScrollView
refreshControl
=
{
<
RefreshControl
refreshing
=
{
this
.
state
.
refresh
ing
}
refreshing
=
{
this
.
props
.
load
ing
}
onRefresh
=
{
this
.
handleRefresh
}
/
>
}
...
...
@@ -205,6 +193,7 @@ class Pizza extends Component {
Pizza
.
propTypes
=
{
success
:
PropTypes
.
bool
.
isRequired
,
loading
:
PropTypes
.
bool
.
isRequired
,
hasLoaded
:
PropTypes
.
bool
.
isRequired
,
event
:
PropTypes
.
shape
({
start
:
PropTypes
.
string
.
isRequired
,
...
...
@@ -239,7 +228,8 @@ Pizza.defaultProps = {
const
mapStateToProps
=
state
=>
({
success
:
state
.
pizza
.
success
,
hasLoaded
:
state
.
pizza
.
success
,
loading
:
state
.
pizza
.
loading
,
hasLoaded
:
state
.
pizza
.
hasLoaded
,
event
:
state
.
pizza
.
event
,
order
:
state
.
pizza
.
order
,
pizzaList
:
state
.
pizza
.
pizzaList
,
...
...
app/components/Profile.js
View file @
951826ad
...
...
@@ -7,6 +7,7 @@ import LinearGradient from 'react-native-linear-gradient';
import
Moment
from
'
moment
'
;
import
LoadingScreen
from
'
./LoadingScreen
'
;
import
ErrorScreen
from
'
./ErrorScreen
'
;
import
{
back
}
from
'
../actions/navigation
'
;
...
...
@@ -108,11 +109,7 @@ class Profile extends Component {
this
.
scrollY
=
new
Animated
.
Value
(
0
);
}
render
()
{
if
(
!
this
.
props
.
hasLoaded
)
{
return
<
LoadingScreen
/>
;
}
getAppbar
=
()
=>
{
const
headerHeight
=
this
.
props
.
success
?
this
.
scrollY
.
interpolate
({
inputRange
:
[
0
,
HEADER_SCROLL_DISTANCE
],
outputRange
:
[
HEADER_MAX_HEIGHT
,
HEADER_MIN_HEIGHT
],
...
...
@@ -148,28 +145,6 @@ class Profile extends Component {
})
:
(
HEADER_MIN_HEIGHT
-
24
)
/
2
;
return
(
<
View
style
=
{
styles
.
container
}
>
{
this
.
props
.
success
?
(
<
ScrollView
style
=
{
styles
.
container
}
scrollEventThrottle
=
{
16
}
onScroll
=
{
Animated
.
event
([{
nativeEvent
:
{
contentOffset
:
{
y
:
this
.
scrollY
}
}
}])}
>
<
View
style
=
{
styles
.
content
}
>
{
getDescription
(
this
.
props
.
profile
)}
{
getPersonalInfo
(
this
.
props
.
profile
)}
{
getAchievements
(
this
.
props
.
profile
)}
<
/View
>
<
/ScrollView
>
)
:
(
<
View
style
=
{
styles
.
container
}
>
<
Text
style
=
{
styles
.
errorText
}
>
Ophalen
profiel
mislukt
.
<
/Text
>
<
/View
>
)
}
<
Animated
.
View
style
=
{[
styles
.
header
,
{
height
:
headerHeight
}]}
>
<
Animated
.
Image
style
=
{[
...
...
@@ -202,6 +177,41 @@ class Profile extends Component {
>
{
this
.
props
.
success
?
this
.
props
.
profile
.
display_name
:
'
Profiel
'
}
<
/Animated.Text
>
<
/Animated.View
>
<
/Animated.View
>
);
};
render
()
{
if
(
!
this
.
props
.
hasLoaded
)
{
return
(
<
View
style
=
{
styles
.
container
}
>
<
LoadingScreen
/>
{
this
.
getAppbar
()}
<
/View
>
);
}
return
(
<
View
style
=
{
styles
.
container
}
>
{
this
.
props
.
success
?
(
<
ScrollView
style
=
{
styles
.
container
}
scrollEventThrottle
=
{
16
}
onScroll
=
{
Animated
.
event
([{
nativeEvent
:
{
contentOffset
:
{
y
:
this
.
scrollY
}
}
}])}
>
<
View
style
=
{
styles
.
content
}
>
{
getDescription
(
this
.
props
.
profile
)}
{
getPersonalInfo
(
this
.
props
.
profile
)}
{
getAchievements
(
this
.
props
.
profile
)}
<
/View
>
<
/ScrollView
>
)
:
(
<
View
style
=
{
styles
.
container
}
>
<
ErrorScreen
message
=
"
Sorry! We couldn't load any data.
"
/>
<
/View
>
)
}
{
this
.
getAppbar
()}
<
/View
>
);
}
...
...
app/components/Welcome.js
View file @
951826ad
import
React
,
{
Component
}
from
'
react
'
;
import
PropTypes
from
'
prop-types
'
;
import
{
View
,
Text
,
SectionList
,
TouchableOpacity
}
from
'
react-native
'
;
import
{
View
,
Text
,
SectionList
,
TouchableOpacity
,
ScrollView
,
RefreshControl
}
from
'
react-native
'
;
import
{
connect
}
from
'
react-redux
'
;
import
Moment
from
'
moment
'
;
import
'
moment/locale/nl
'
;
import
EventDetailCard
from
'
./EventDetailCard
'
;
import
LoadingScreen
from
'
./LoadingScreen
'
;
import
ErrorScreen
from
'
./ErrorScreen
'
;
import
*
as
welcomeActions
from
'
../actions/welcome
'
;
import
{
navigate
}
from
'
../actions/navigation
'
;
...
...
@@ -67,17 +70,39 @@ class Welcome extends Component {
};
render
()
{
if
(
this
.
props
.
eventList
.
length
===
0
)
{
if
(
this
.
props
.
status
===
'
initial
'
)
{
return
<
LoadingScreen
/>
;
}
else
if
(
this
.
props
.
status
===
'
failure
'
)
{
return
(
<
View
>
<
Text
>
No
events
found
!
<
/Text
>
<
/View
>
<
ScrollView
contentContainerStyle
=
{
styles
.
content
}
refreshControl
=
{(
<
RefreshControl
onRefresh
=
{
this
.
handleRefresh
}
refreshing
=
{
this
.
props
.
loading
}
/
>
)}
>
<
ErrorScreen
message
=
"
Sorry! We couldn't load any data.
"
/>
<
/ScrollView
>
);
}
else
if
(
this
.
props
.
eventList
.
length
===
0
)
{
return
(
<
ScrollView
contentContainerStyle
=
{
styles
.
content
}
refreshControl
=
{(
<
RefreshControl
onRefresh
=
{
this
.
handleRefresh
}
refreshing
=
{
this
.
props
.
loading
}
/
>
)}
>
<
ErrorScreen
message
=
"
No events found!
"
/>
<
/ScrollView
>
);
}
return
(
<
View
>
<
View
style
=
{
styles
.
content
}
>
<
SectionList
style
=
{
styles
.
sectionList
}
renderItem
=
{
item
=>
<
EventDetailCard
event
=
{
item
.
item
}
/>
}
...
...
@@ -110,11 +135,13 @@ Welcome.propTypes = {
})).
isRequired
,
refresh
:
PropTypes
.
func
.
isRequired
,
loading
:
PropTypes
.
bool
.
isRequired
,
status
:
PropTypes
.
string
.
isRequired
,
};
const
mapStateToProps
=
state
=>
({
eventList
:
state
.
welcome
.
eventList
,
loading
:
state
.
welcome
.
loading
,
status
:
state
.
welcome
.
status
,
});
const
mapDispatchToProps
=
dispatch
=>
({
...
...
app/components/style/calendar.js
View file @
951826ad
...
...
@@ -4,6 +4,10 @@ import { TOTAL_BAR_HEIGHT } from './navigator';
import
{
colors
}
from
'
../../style
'
;
const
styles
=
StyleSheet
.
create
({
content
:
{
flex
:
1
,
backgroundColor
:
colors
.
background
,
},
day
:
{
flex
:
1
,
flexDirection
:
'
row
'
,
...
...
app/components/style/errorScreen.js
0 → 100644
View file @
951826ad
import
{
StyleSheet
}
from
'
react-native
'
;
import
{
colors
}
from
'
../../style
'
;
const
styles
=
StyleSheet
.
create
({
content
:
{
flex
:
1
,
alignItems
:
'
center
'
,
justifyContent
:
'
center
'
,
backgroundColor
:
colors
.
background
,
},
image
:
{
width
:
200
,
height
:
200
,
marginBottom
:
30
,
},
text
:
{
fontFamily
:
'
sans-serif-regular
'
,
fontSize
:
18
,
color
:
colors
.
textColour
,
textAlign
:
'
center
'
,
},
});
export
default
styles
;
app/components/style/welcome.js
View file @
951826ad
...
...
@@ -4,6 +4,10 @@ import { TOTAL_BAR_HEIGHT } from './navigator';
import
{
colors
}
from
'
../../style
'
;
const
styles
=
StyleSheet
.
create
({
content
:
{
flex
:
1
,
backgroundColor
:
colors
.
background
,
},
sectionList
:
{
backgroundColor
:
colors
.
background
,
height
:
Dimensions
.
get
(
'
window
'
).
height
-
TOTAL_BAR_HEIGHT
,
...
...
app/img/smiley.png
0 → 100644
View file @
951826ad
79.2 KB
app/reducers/calendar.js
View file @
951826ad
...
...
@@ -3,6 +3,7 @@ import * as calendarActions from '../actions/calendar';
const
initialState
=
{
eventList
:
[],
loading
:
true
,
status
:
'
initial
'
,
};
export
default
function
calendar
(
state
=
initialState
,
action
=
{})
{
...
...
@@ -11,9 +12,14 @@ export default function calendar(state = initialState, action = {}) {
return
{
eventList
:
action
.
payload
.
eventList
,
loading
:
false
,
status
:
'
success
'
,
};
case
calendarActions
.
FAILURE
:
return
{
...
state
,
loading
:
false
};
return
{
...
state
,
loading
:
false
,
status
:
'
failure
'
,
};
case
calendarActions
.
REFRESH
:
return
{
...
state
,
loading
:
true
};
default
:
...
...
app/reducers/pizza.js
View file @
951826ad
...
...
@@ -2,6 +2,7 @@ import * as pizzaActions from '../actions/pizza';
const
initialState
=
{
success
:
false
,
loading
:
false
,
hasLoaded
:
false
,
event
:
null
,
order
:
null
,
...
...
@@ -13,6 +14,7 @@ export default function pizza(state = initialState, action = {}) {
case
pizzaActions
.
SUCCESS
:
return
{
success
:
true
,
loading
:
false
,
hasLoaded
:
true
,
event
:
action
.
payload
.
event
,
order
:
action
.
payload
.
order
,
...
...
@@ -22,12 +24,13 @@ export default function pizza(state = initialState, action = {}) {
return
{
...
state
,
success
:
false
,
loading
:
false
,
hasLoaded
:
true
,
};
case
pizzaActions
.
FETCHING
:
return
{
...
state
,
hasLoaded
:
fals
e
,
loading
:
tru
e
,
};
case
pizzaActions
.
CANCEL_SUCCESS
:
return
{
...
...
app/reducers/profile.js
View file @
951826ad
import
*
as
profileActions
from
'
../actions/profile
'
;
import
{
defaultProfileImage
}
from
'
../url
'
;
const
initialState
=
{
profile
:
{
pk
:
-
1
,
display_name
:
''
,
photo
:
''
,
photo
:
defaultProfileImage
,
profile_description
:
''
,
birthday
:
''
,
starting_year
:
-
1
,
...
...
app/reducers/welcome.js
View file @
951826ad
...
...
@@ -3,6 +3,7 @@ import * as welcomeActions from '../actions/welcome';
const
initialState
=
{
eventList
:
[],
loading
:
true
,
status
:
'
initial
'
,
};
export
default
function
welcome
(
state
=
initialState
,
action
=
{})
{
...
...
@@ -11,9 +12,14 @@ export default function welcome(state = initialState, action = {}) {
return
{
eventList
:
action
.
payload
.
eventList
,
loading
:
false
,
status
:
'
success
'
,
};
case
welcomeActions
.
FAILURE
:
return
{
...
state
,
loading
:
false
};
return
{
...
state
,
loading
:
false
,
status
:
'
failure
'
,
};
case
welcomeActions
.
REFRESH
:
return
{
...
state
,
loading
:
true
};
default
:
...
...
app/url.js
View file @
951826ad
...
...
@@ -6,6 +6,7 @@ if (__DEV__) { // eslint-disable-line no-undef
export
const
url
=
server
;
export
const
apiUrl
=
`
${
server
}
/api/v1`
;
export
const
pizzaUrl
=
'
https://pizza.thalia.nu
'
;
export
const
defaultProfileImage
=
`
${
server
}
/static/members/images/default-avatar.jpg`
;
export
const
tokenSelector
=
state
=>
state
.
session
.
token
;
export
class
ServerError
extends
Error
{
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment