Skip to content
GitLab
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
3975f50f
Commit
3975f50f
authored
May 24, 2017
by
Wietse Kuipers
Browse files
Merge branch 'style/navigation' into 'master'
Style/navigation See merge request
!13
parents
3c5c6b32
da1a78c5
Changes
11
Hide whitespace changes
Inline
Side-by-side
android/app/build.gradle
View file @
3975f50f
...
...
@@ -127,6 +127,7 @@ android {
}
dependencies
{
compile
project
(
':react-native-vector-icons'
)
compile
fileTree
(
dir:
"libs"
,
include:
[
"*.jar"
])
compile
"com.android.support:appcompat-v7:23.0.1"
compile
"com.facebook.react:react-native:+"
// From node_modules
...
...
app/actions/login.js
View file @
3975f50f
...
...
@@ -3,13 +3,19 @@ import * as types from './actionTypes';
const
USERNAMEKEY
=
'
@MyStore:username
'
;
const
TOKENKEY
=
'
@MyStore:token
'
;
const
DISPLAYNAMEKEY
=
'
@MyStore:displayName
'
;
const
PHOTOKEY
=
'
@MyStore:photo
'
;
export
function
loginSuccess
(
username
,
token
)
{
const
defaultAvatar
=
'
http://localhost:8000/static/members/images/default-avatar.jpg
'
;
export
function
loginSuccess
(
username
,
token
,
displayName
,
photo
)
{
return
{
type
:
types
.
LOGINSUCCESS
,
loginState
:
'
loggedIn
'
,
username
,
token
,
displayName
,
photo
,
};
}
...
...
@@ -27,7 +33,37 @@ export function loginFailure() {
};
}
export
function
login
(
username
,
password
)
{
function
getUserInfo
(
token
)
{
const
data
=
{
method
:
'
GET
'
,
headers
:
{
Accept
:
'
application/json
'
,
'
Content-Type
'
:
'
application/json
'
,
Authorization
:
`Token
${
token
}
`
,
},
};
return
fetch
(
'
http://localhost:8000/api/members/info/
'
,
data
)
.
then
(
response
=>
response
.
json
())
.
then
(
(
responseJson
)
=>
{
const
avatar
=
responseJson
.
photo
===
null
?
defaultAvatar
:
responseJson
.
photo
;
return
{
photo
:
avatar
,
displayName
:
responseJson
.
display_name
,
};
},
)
.
catch
(
()
=>
({
photo
:
defaultAvatar
,
displayName
:
'
Naamloos
'
,
}),
);
}
export
function
login
(
user
,
pass
)
{
return
(
dispatch
)
=>
{
dispatch
(
loginProgress
());
const
data
=
{
...
...
@@ -37,8 +73,8 @@ export function login(username, password) {
'
Content-Type
'
:
'
application/json
'
,
},
body
:
JSON
.
stringify
({
username
,
password
,
username
:
user
,
password
:
pass
,
}),
};
return
fetch
(
'
http://localhost:8000/api/token-auth/
'
,
data
)
...
...
@@ -47,10 +83,20 @@ export function login(username, password) {
.
then
(
(
responseJson
)
=>
{
if
(
responseJson
.
token
)
{
return
AsyncStorage
.
multiSet
([[
USERNAMEKEY
,
username
],
[
TOKENKEY
,
responseJson
.
token
]])
const
token
=
responseJson
.
token
;
return
getUserInfo
(
token
)
.
then
(
()
=>
dispatch
(
loginSuccess
(
username
,
responseJson
.
token
)),
);
userInfo
=>
AsyncStorage
.
multiSet
([
[
USERNAMEKEY
,
user
],
[
TOKENKEY
,
token
],
[
DISPLAYNAMEKEY
,
userInfo
.
displayName
],
[
PHOTOKEY
,
userInfo
.
photo
],
])
.
then
(()
=>
dispatch
(
loginSuccess
(
user
,
token
,
userInfo
.
displayName
,
userInfo
.
photo
,
)),
));
}
return
dispatch
(
loginFailure
());
})
...
...
app/app.js
View file @
3975f50f
...
...
@@ -14,6 +14,9 @@ const store = createStoreWithMiddleware(reducer);
const
USERNAMEKEY
=
'
@MyStore:username
'
;
const
TOKENKEY
=
'
@MyStore:token
'
;
const
DISPLAYNAMEKEY
=
'
@MyStore:displayName
'
;
const
PHOTOKEY
=
'
@MyStore:photo
'
;
const
pairsToObject
=
(
obj
,
pair
)
=>
{
const
obj2
=
{
...
obj
};
obj2
[
pair
[
0
]]
=
pair
[
1
];
...
...
@@ -22,15 +25,17 @@ const pairsToObject = (obj, pair) => {
class
Main
extends
Component
{
componentDidMount
()
{
AsyncStorage
.
multiGet
([
USERNAMEKEY
,
TOKENKEY
])
AsyncStorage
.
multiGet
([
USERNAMEKEY
,
TOKENKEY
,
DISPLAYNAMEKEY
,
PHOTOKEY
])
.
then
(
(
result
)
=>
{
const
values
=
result
.
reduce
(
pairsToObject
,
{});
const
username
=
values
[
USERNAMEKEY
];
const
token
=
values
[
TOKENKEY
];
const
displayName
=
values
[
DISPLAYNAMEKEY
];
const
photo
=
values
[
DISPLAYNAMEKEY
];
if
(
username
!==
null
&&
token
!==
null
)
{
store
.
dispatch
(
loginSuccess
(
username
,
token
));
store
.
dispatch
(
loginSuccess
(
username
,
token
,
displayName
,
photo
));
}
});
}
...
...
app/components/Calendar.js
View file @
3975f50f
...
...
@@ -26,6 +26,7 @@ const Calendar = (props) => {
<
ListView
dataSource
=
{
dataSource
}
renderRow
=
{
rowData
=>
rowData
}
enableEmptySections
/>
<
/View
>
);
...
...
app/components/Sidebar.js
View file @
3975f50f
import
React
from
'
react
'
;
import
{
Text
,
View
}
from
'
react-native
'
;
import
{
Text
,
View
,
Image
,
TouchableHighlight
}
from
'
react-native
'
;
import
{
connect
}
from
'
react-redux
'
;
import
styles
from
'
../style
'
;
import
Icon
from
'
react-native-vector-icons/MaterialIcons
'
;
import
{
colors
}
from
'
../style
'
;
import
styles
from
'
./style/sidebar
'
;
import
*
as
actions
from
'
../actions/navigation
'
;
import
*
as
loginActions
from
'
../actions/login
'
;
const
Sidebar
=
props
=>
<
View
style
=
{
styles
.
sidebar
}
>
<
Text
style
=
{
styles
.
header
}
>
MENU
<
/Text
>
<
Text
onPress
=
{()
=>
props
.
navigate
(
'
welcome
'
)}
style
=
{
styles
.
button
}
>
Welcome
<
/Text
>
<
Text
onPress
=
{()
=>
props
.
navigate
(
'
eventList
'
)}
style
=
{
styles
.
button
}
>
Calendar
<
/Text
>
<
/View
>
;
const
background
=
require
(
'
../img/huygens.jpg
'
);
const
Sidebar
=
(
props
)
=>
{
const
buttons
=
[
{
onPress
:
()
=>
props
.
navigate
(
'
welcome
'
),
iconName
:
'
home
'
,
text
:
'
Welkom
'
,
style
:
{},
scene
:
'
welcome
'
,
},
{
onPress
:
()
=>
props
.
navigate
(
'
eventList
'
),
iconName
:
'
event
'
,
text
:
'
Agenda
'
,
style
:
{},
scene
:
'
eventList
'
,
},
{
onPress
:
props
.
logout
,
iconName
:
'
lock
'
,
text
:
'
Uitloggen
'
,
style
:
{
borderTopColor
:
colors
.
lightGray
,
borderTopWidth
:
1
,
},
scene
:
'
logout
'
,
},
];
return
(
<
View
style
=
{
styles
.
sidebar
}
>
<
TouchableHighlight
onPress
=
{()
=>
props
.
navigate
(
'
profile
'
)}
style
=
{
styles
.
headerButton
}
>
<
Image
source
=
{
background
}
style
=
{
styles
.
headerImage
}
resizeMode
=
"
cover
"
>
<
Image
source
=
{{
uri
:
props
.
photo
}}
style
=
{
styles
.
profileImage
}
resizeMode
=
"
cover
"
/>
<
Text
style
=
{
styles
.
nameField
}
>
{
props
.
displayName
}
<
/Text
>
<
/Image
>
<
/TouchableHighlight
>
<
View
style
=
{
styles
.
buttonList
}
>
{
buttons
.
map
(
button
=>
(
<
Icon
.
Button
onPress
=
{
button
.
onPress
}
name
=
{
button
.
iconName
}
borderRadius
=
{
0
}
backgroundColor
=
{
colors
.
white
}
color
=
{
props
.
currentScene
===
button
.
scene
?
colors
.
magenta
:
colors
.
textColour
}
size
=
{
28
}
iconStyle
=
{
styles
.
buttonIcon
}
style
=
{[
styles
.
buttonText
,
button
.
style
]}
key
=
{
button
.
scene
}
>
{
button
.
text
}
<
/Icon.Button
>
))}
<
/View
>
<
/View
>
);
};
Sidebar
.
propTypes
=
{
currentScene
:
React
.
PropTypes
.
string
.
isRequired
,
displayName
:
React
.
PropTypes
.
string
.
isRequired
,
photo
:
React
.
PropTypes
.
string
.
isRequired
,
navigate
:
React
.
PropTypes
.
func
.
isRequired
,
logout
:
React
.
PropTypes
.
func
.
isRequired
,
};
const
mapStateToProps
=
state
=>
({
currentScene
:
state
.
navigation
.
currentScene
,
displayName
:
state
.
session
.
displayName
,
photo
:
state
.
session
.
photo
,
});
const
mapDispatchToProps
=
dispatch
=>
({
navigate
:
scene
=>
dispatch
(
actions
.
navigate
(
scene
)),
logout
:
()
=>
dispatch
(
loginActions
.
logout
()),
});
export
default
connect
(
()
=>
({})
,
mapDispatchToProps
)(
Sidebar
);
export
default
connect
(
mapStateToProps
,
mapDispatchToProps
)(
Sidebar
);
app/components/navigator.js
View file @
3975f50f
import
React
from
'
react
'
;
import
{
Text
,
View
,
StatusBar
,
TouchableOpacity
}
from
'
react-native
'
;
import
{
connect
}
from
'
react-redux
'
;
import
Drawer
from
'
react-native-drawer
'
;
import
Icon
from
'
react-native-vector-icons/MaterialIcons
'
;
import
Login
from
'
./Login
'
;
import
Welcome
from
'
./Welcome
'
;
import
Sidebar
from
'
./Sidebar
'
;
...
...
@@ -8,16 +10,8 @@ import Event from './Event';
import
Calendar
from
'
./Calendar
'
;
import
*
as
actions
from
'
../actions/navigation
'
;
const
mapStateToProps
=
state
=>
({
currentScene
:
state
.
navigation
.
currentScene
,
loggedIn
:
state
.
navigation
.
loggedIn
,
drawerOpen
:
state
.
navigation
.
drawerOpen
,
});
const
mapDispatchToProps
=
dispatch
=>
({
updateDrawer
:
isOpen
=>
dispatch
(
actions
.
updateDrawer
(
isOpen
)),
});
import
styles
from
'
./style/navigator
'
;
import
{
colors
}
from
'
../style
'
;
const
sceneToComponent
=
(
scene
)
=>
{
switch
(
scene
)
{
...
...
@@ -32,33 +26,88 @@ const sceneToComponent = (scene) => {
}
};
const
sceneToTitle
=
(
scene
)
=>
{
switch
(
scene
)
{
case
'
welcome
'
:
return
'
Welkom
'
;
case
'
event
'
:
return
'
Evenement
'
;
case
'
eventList
'
:
return
'
Agenda
'
;
default
:
return
'
ThaliApp
'
;
}
};
const
ReduxNavigator
=
(
props
)
=>
{
const
{
currentScene
,
loggedIn
,
drawerOpen
,
updateDrawer
}
=
props
;
if
(
loggedIn
)
{
return
(
<
Drawer
type
=
"
displace
"
content
=
{
<
Sidebar
/>
}
openDrawerOffset
=
{
0.
4
}
openDrawerOffset
=
{
0.
2
}
panOpenMask
=
{
0.2
}
panCloseMask
=
{
0.2
}
panThreshold
=
{
0.3
}
tweenHandler
=
{
ratio
=>
({
main
:
{
opacity
:
(
2
-
ratio
)
/
2
}
})}
styles
=
{{
mainOverlay
:
{
backgroundColor
:
colors
.
black
,
opacity
:
0
,
},
}}
tweenHandler
=
{
ratio
=>
({
mainOverlay
:
{
opacity
:
ratio
*
0.75
}
})}
open
=
{
drawerOpen
}
onOpen
=
{()
=>
updateDrawer
(
true
)}
onClose
=
{()
=>
updateDrawer
(
false
)}
tapToClose
>
<
View
style
=
{
styles
.
statusBar
}
>
<
StatusBar
backgroundColor
=
{
colors
.
darkMagenta
}
barStyle
=
"
light-content
"
/>
<
/View
>
<
View
style
=
{
styles
.
appBar
}
>
<
TouchableOpacity
onPress
=
{
props
.
isFirstScene
?
()
=>
props
.
updateDrawer
(
!
props
.
drawerOpen
)
:
props
.
back
}
>
<
Icon
name
=
{
props
.
isFirstScene
?
'
menu
'
:
'
arrow-back
'
}
onClick
=
{
props
.
back
}
style
=
{
styles
.
icon
}
size
=
{
20
}
/
>
<
/TouchableOpacity
>
<
Text
style
=
{
styles
.
title
}
>
{
sceneToTitle
(
currentScene
)}
<
/Text
>
<
/View
>
{
sceneToComponent
(
currentScene
)}
<
/Drawer>
)
;
}
return
<
Login
/>
;
return
(
<
View
>
<
View
style
=
{
styles
.
statusBar
}
>
<
StatusBar
backgroundColor
=
{
colors
.
darkMagenta
}
barStyle
=
"
light-content
"
/>
<
/View
>
<
Login
/>
<
/View>
)
;
};
ReduxNavigator
.
propTypes
=
{
currentScene
:
React
.
PropTypes
.
string
.
isRequired
,
loggedIn
:
React
.
PropTypes
.
bool
.
isRequired
,
drawerOpen
:
React
.
PropTypes
.
bool
.
isRequired
,
isFirstScene
:
React
.
PropTypes
.
bool
.
isRequired
,
updateDrawer
:
React
.
PropTypes
.
func
.
isRequired
,
back
:
React
.
PropTypes
.
func
.
isRequired
,
};
const
mapStateToProps
=
state
=>
({
currentScene
:
state
.
navigation
.
currentScene
,
loggedIn
:
state
.
navigation
.
loggedIn
,
drawerOpen
:
state
.
navigation
.
drawerOpen
,
isFirstScene
:
state
.
navigation
.
previousScenes
.
length
===
0
,
});
const
mapDispatchToProps
=
dispatch
=>
({
updateDrawer
:
isOpen
=>
dispatch
(
actions
.
updateDrawer
(
isOpen
)),
back
:
()
=>
dispatch
(
actions
.
back
()),
});
export
default
connect
(
mapStateToProps
,
mapDispatchToProps
)(
ReduxNavigator
);
app/components/style/navigator.js
0 → 100644
View file @
3975f50f
import
{
Platform
,
StyleSheet
}
from
'
react-native
'
;
import
{
colors
}
from
'
../../style
'
;
const
STATUSBAR_HEIGHT
=
Platform
.
OS
===
'
ios
'
?
20
:
0
;
const
APPBAR_HEIGHT
=
Platform
.
OS
===
'
ios
'
?
44
:
56
;
const
styles
=
StyleSheet
.
create
({
statusBar
:
{
height
:
STATUSBAR_HEIGHT
,
backgroundColor
:
colors
.
darkMagenta
,
},
appBar
:
{
backgroundColor
:
colors
.
magenta
,
height
:
APPBAR_HEIGHT
,
justifyContent
:
'
flex-start
'
,
alignItems
:
'
center
'
,
flexWrap
:
'
wrap
'
,
flexDirection
:
'
row
'
,
},
title
:
{
color
:
colors
.
white
,
fontSize
:
24
,
},
icon
:
{
paddingLeft
:
20
,
paddingRight
:
50
,
color
:
colors
.
white
,
},
});
export
default
styles
;
app/components/style/sidebar.js
0 → 100644
View file @
3975f50f
import
{
StyleSheet
}
from
'
react-native
'
;
import
{
colors
}
from
'
../../style
'
;
const
styles
=
StyleSheet
.
create
({
sidebar
:
{
backgroundColor
:
colors
.
white
,
flex
:
1
,
alignItems
:
'
stretch
'
,
},
headerButton
:
{
flex
:
1
,
},
headerImage
:
{
flex
:
1
,
width
:
null
,
height
:
null
,
justifyContent
:
'
space-around
'
,
paddingLeft
:
10
,
},
profileImage
:
{
width
:
100
,
height
:
100
,
borderRadius
:
50
,
},
nameField
:
{
color
:
colors
.
white
,
fontSize
:
24
,
},
buttonList
:
{
flex
:
3
,
},
buttonIcon
:
{
marginRight
:
30
,
width
:
28
,
textAlign
:
'
center
'
,
},
buttonText
:
{
padding
:
20
,
},
});
export
default
styles
;
app/img/huygens.jpg
0 → 100644
View file @
3975f50f
304 KB
app/reducers/session.js
View file @
3975f50f
...
...
@@ -4,12 +4,21 @@ const initialState = {
loginState
:
''
,
token
:
''
,
username
:
''
,
displayName
:
''
,
photo
:
''
,
};
export
default
function
session
(
state
=
initialState
,
action
=
{})
{
switch
(
action
.
type
)
{
case
types
.
LOGINSUCCESS
:
return
{
...
state
,
loginState
:
'
success
'
,
username
:
action
.
username
,
token
:
action
.
token
};
return
{
...
state
,
loginState
:
'
success
'
,
username
:
action
.
username
,
token
:
action
.
token
,
displayName
:
action
.
displayName
,
photo
:
action
.
photo
,
};
case
types
.
LOGINFAILURE
:
return
{
...
state
,
loginState
:
'
failure
'
};
case
types
.
LOGINPROGRESS
:
...
...
app/style.js
View file @
3975f50f
import
{
StyleSheet
}
from
'
react-native
'
;
const
magenta
=
'
#E62272
'
;
const
white
=
'
#FFFFFF
'
;
const
black
=
'
#000000
'
;
const
styles
=
StyleSheet
.
create
({
sidebar
:
{
flex
:
1
,
backgroundColor
:
white
,
},
header
:
{
backgroundColor
:
magenta
,
color
:
white
,
fontWeight
:
'
bold
'
,
padding
:
20
,
},
button
:
{
backgroundColor
:
white
,
color
:
black
,
paddingLeft
:
10
,
paddingTop
:
20
,
paddingBottom
:
20
,
borderBottomWidth
:
1
,
},
});
export
default
styles
;
export
const
colors
=
{
magenta
:
'
#E62272
'
,
darkMagenta
:
'
#C2185B
'
,
white
:
'
#FFFFFF
'
,
black
:
'
#000000
'
,
lightGray
:
'
#BBBBBB
'
,
textColour
:
'
#313131
'
,
};
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new 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