Skip to content

Commit 2e4aaf7

Browse files
committed
add PersonalSettingModal
1 parent 2f754bb commit 2e4aaf7

14 files changed

Lines changed: 460 additions & 67 deletions

File tree

browser/main/Actions/AuthActions.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,6 @@ var Reflux = require('reflux')
33
module.exports = Reflux.createActions([
44
'login',
55
'register',
6-
'logout'
6+
'logout',
7+
'updateProfile'
78
])
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
/* global localStorage */
2+
var React = require('react/addons')
3+
var request = require('superagent')
4+
5+
var Catalyst = require('../Mixins/Catalyst')
6+
7+
var AuthActions = require('../Actions/AuthActions')
8+
9+
var apiUrl = 'http://localhost:8000/'
10+
11+
module.exports = React.createClass({
12+
mixins: [Catalyst.LinkedStateMixin],
13+
propTypes: {
14+
close: React.PropTypes.func,
15+
currentUser: React.PropTypes.object
16+
},
17+
getInitialState: function () {
18+
return {
19+
currentTab: 'profile',
20+
userName: this.props.currentUser.name,
21+
email: this.props.currentUser.email,
22+
currentPassword: '',
23+
newPassword: '',
24+
confirmation: '',
25+
contactTitle: '',
26+
contactContent: ''
27+
}
28+
},
29+
activeProfile: function () {
30+
this.setState({currentTab: 'profile'})
31+
},
32+
activeContact: function () {
33+
this.setState({currentTab: 'contact'})
34+
},
35+
activeInfo: function () {
36+
this.setState({currentTab: 'info'})
37+
},
38+
activeLogout: function () {
39+
this.setState({currentTab: 'logout'})
40+
},
41+
saveProfile: function () {
42+
AuthActions.updateProfile({
43+
name: this.state.userName,
44+
email: this.state.email
45+
})
46+
},
47+
savePassword: function () {
48+
if (this.state.newPassword === this.state.confirmation) {
49+
request
50+
.put(apiUrl + 'auth/password')
51+
.set({
52+
Authorization: 'Bearer ' + localStorage.getItem('token')
53+
})
54+
.send({
55+
currentPassword: this.state.currentPassword,
56+
newPassword: this.state.newPassword
57+
})
58+
.end(function (err, res) {
59+
this.setState({
60+
currentPassword: '',
61+
newPassword: '',
62+
confirmation: ''
63+
})
64+
if (err) {
65+
console.error(err)
66+
return
67+
}
68+
69+
}.bind(this))
70+
}
71+
},
72+
sendEmail: function () {
73+
74+
},
75+
logOut: function () {
76+
AuthActions.logout()
77+
},
78+
interceptClick: function (e) {
79+
e.stopPropagation()
80+
},
81+
render: function () {
82+
var content
83+
if (this.state.currentTab === 'profile') {
84+
content = (
85+
<div className='profile'>
86+
<div className='profileTop'>
87+
<div className='profileFormRow'>
88+
<label>Name</label>
89+
<input valueLink={this.linkState('userName')} className='block-input' type='text' placeholder='Name'/>
90+
</div>
91+
<div className='profileFormRow'>
92+
<label>E-mail</label>
93+
<input valueLink={this.linkState('email')} className='block-input' type='text' placeholder='E-mail'/>
94+
</div>
95+
<div className='profileFormRow'>
96+
<button onClick={this.saveProfile} className='saveButton btn-primary'>Save</button>
97+
</div>
98+
</div>
99+
100+
<div className='profileBottom'>
101+
<div className='profileFormRow'>
102+
<label>Current password</label>
103+
<input valueLink={this.linkState('currentPassword')} className='block-input' type='password' placeholder='Current password'/>
104+
</div>
105+
<div className='profileFormRow'>
106+
<label>New password</label>
107+
<input valueLink={this.linkState('newPassword')} className='block-input' type='password' placeholder='New password'/>
108+
</div>
109+
<div className='profileFormRow'>
110+
<label>Confirmation</label>
111+
<input valueLink={this.linkState('confirmation')} className='block-input' type='password' placeholder='Confirmation'/>
112+
</div>
113+
<div className='profileFormRow'>
114+
<button onClick={this.savePassword} className='saveButton btn-primary'>Save</button>
115+
</div>
116+
</div>
117+
</div>
118+
)
119+
} else if (this.state.currentTab === 'contact') {
120+
content = (
121+
<div className='contact'>
122+
<p>
123+
Let us know your opinion about CodeXen.<br/>
124+
Your feedback might be used to improvement of CodeXen.
125+
</p>
126+
<input valueLink={this.linkState('contactTitle')} className='block-input' type='text' placeholder='title'/>
127+
<textarea valueLink={this.linkState('contactContent')} className='block-input' placeholder='message content'/>
128+
<div className='contactFormRow'>
129+
<button onClick={this.sendEmail} className='saveButton btn-primary'>Send</button>
130+
</div>
131+
</div>
132+
)
133+
} else if (this.state.currentTab === 'info') {
134+
content = (
135+
<div className='info'>
136+
<h2 className='infoLabel'>External links</h2>
137+
<ul className='externalList'>
138+
<li><a>CodeXen Homepage <i className='fa fa-external-link'/></a></li>
139+
<li><a>Regulation <i className='fa fa-external-link'/></a></li>
140+
<li><a>Private policy <i className='fa fa-external-link'/></a></li>
141+
</ul>
142+
</div>
143+
)
144+
} else {
145+
content = (
146+
<div className='logout'>
147+
<p className='logoutLabel'>Are you sure to logout?</p>
148+
<img className='userPhoto' width='150' height='150' src='../vendor/dummy.jpg'/><br/>
149+
<button onClick={this.logOut} className='logoutButton btn-default'>Logout</button>
150+
</div>
151+
)
152+
}
153+
154+
return (
155+
<div onClick={this.interceptClick} className='PersonalSettingModal modal'>
156+
<div className='settingNav'>
157+
<h1>Personal setting</h1>
158+
<nav>
159+
<button className={this.state.currentTab === 'profile' ? 'active' : ''} onClick={this.activeProfile}><i className='fa fa-user fa-fw'/> Profile</button>
160+
<button className={this.state.currentTab === 'contact' ? 'active' : ''} onClick={this.activeContact}><i className='fa fa-phone fa-fw'/> Contact</button>
161+
<button className={this.state.currentTab === 'info' ? 'active' : ''} onClick={this.activeInfo}><i className='fa fa-info-circle fa-fw'/> Info</button>
162+
<button className={this.state.currentTab === 'logout' ? 'active' : ''} onClick={this.activeLogout}><i className='fa fa-sign-out fa-fw'/> Logout</button>
163+
</nav>
164+
</div>
165+
<div className='settingBody'>
166+
{content}
167+
</div>
168+
</div>
169+
)
170+
}
171+
})

browser/main/Components/PlanetSettingModal.jsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ module.exports = React.createClass({
2222
this.setState({currentTab: 'planetProfile'})
2323

2424
},
25-
activeManageMember: function () {
26-
this.setState({currentTab: 'manageMember'})
25+
activeMembers: function () {
26+
this.setState({currentTab: 'members'})
2727
},
2828
saveProfile: function () {
2929
var currentPlanet = this.props.currentPlanet
@@ -79,7 +79,7 @@ module.exports = React.createClass({
7979
}.bind(this))
8080

8181
content = (
82-
<div className='manageMember'>
82+
<div className='members'>
8383
<ul className='userList'>
8484
{members}
8585
</ul>
@@ -99,8 +99,8 @@ module.exports = React.createClass({
9999
<div className='settingNav'>
100100
<h1>Planet setting</h1>
101101
<nav>
102-
<button className={this.state.currentTab === 'planetProfile' ? 'active' : ''} onClick={this.activePlanetProfile}><i className='fa fa-globe'/> Planet profile</button>
103-
<button className={this.state.currentTab === 'manageMember' ? 'active' : ''} onClick={this.activeManageMember}><i className='fa fa-group'/> Manage member</button>
102+
<button className={this.state.currentTab === 'planetProfile' ? 'active' : ''} onClick={this.activePlanetProfile}><i className='fa fa-globe fa-fw'/> Planet profile</button>
103+
<button className={this.state.currentTab === 'members' ? 'active' : ''} onClick={this.activeMembers}><i className='fa fa-group fa-fw'/> Members</button>
104104
</nav>
105105
</div>
106106

browser/main/Components/UserNavigator.jsx

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ var ReactRouter = require('react-router')
33
var Link = ReactRouter.Link
44

55
var ModalBase = require('./ModalBase')
6+
var PersonalSettingModal = require('./PersonalSettingModal')
67
var PlanetCreateModal = require('./PlanetCreateModal')
78

89
var AuthStore = require('../Stores/AuthStore')
@@ -27,6 +28,12 @@ module.exports = React.createClass({
2728
onLogout: function () {
2829
this.transitionTo('login')
2930
},
31+
openPersonalSettingModal: function () {
32+
this.setState({isPersonalSettingModalOpen: true})
33+
},
34+
closePersonalSettingModal: function () {
35+
this.setState({isPersonalSettingModalOpen: false})
36+
},
3037
openPlanetCreateModal: function () {
3138
this.setState({isPlanetCreateModalOpen: true})
3239
},
@@ -51,13 +58,18 @@ module.exports = React.createClass({
5158

5259
return (
5360
<div tabIndex='2' className='UserNavigator'>
54-
<Link to='userHome' params={{userName: this.props.currentUser.name}} className='userConfig'>
61+
<button onClick={this.openPersonalSettingModal} className='userButton'>
5562
<img width='50' height='50' src='../vendor/dummy.jpg'/>
56-
</Link>
57-
<ul>
63+
</button>
64+
<ul className='planetList'>
5865
{planets}
5966
</ul>
6067
<button onClick={this.openPlanetCreateModal} className='newPlanet'><i className='fa fa-plus'/></button>
68+
69+
<ModalBase isOpen={this.state.isPersonalSettingModalOpen} close={this.closePersonalSettingModal}>
70+
<PersonalSettingModal currentUser={this.props.currentUser} close={this.closePersonalSettingModal}/>
71+
</ModalBase>
72+
6173
<ModalBase isOpen={this.state.isPlanetCreateModalOpen} close={this.closePlanetCreateModal}>
6274
<PlanetCreateModal close={this.closePlanetCreateModal}/>
6375
</ModalBase>

browser/main/Containers/LoginContainer.jsx

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ var React = require('react/addons')
22
var ReactRouter = require('react-router')
33
var Link = ReactRouter.Link
44

5-
var AuthStore = require('../Stores/AuthStore')
65
var AuthActions = require('../Actions/AuthActions')
76

87
var OnlyGuest = require('../Mixins/OnlyGuest')
@@ -15,27 +14,13 @@ module.exports = React.createClass({
1514
password: ''
1615
}
1716
},
18-
componentDidMount: function () {
19-
this.unsubscribe = AuthStore.listen(this.onLogin)
20-
},
21-
componentWillUnmount: function () {
22-
this.unsubscribe()
23-
},
2417
handleSubmit: function (e) {
2518
AuthActions.login({
2619
email: this.state.email,
2720
password: this.state.password
2821
})
2922
e.preventDefault()
3023
},
31-
onLogin: function (user) {
32-
var planet = user.Planets.length > 0 ? user.Planets[0] : null
33-
if (planet == null) {
34-
this.transitionTo('user', {userName: user.name})
35-
return
36-
}
37-
this.transitionTo('planetHome', {userName: user.name, planetName: planet.name})
38-
},
3924
render: function () {
4025
return (
4126
<div className='LoginContainer'>

browser/main/Containers/MainContainer.jsx

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,33 @@ var React = require('react/addons')
22
var ReactRouter = require('react-router')
33
var RouteHandler = ReactRouter.RouteHandler
44

5+
var AuthStore = require('../Stores/AuthStore')
6+
57
module.exports = React.createClass({
68
mixins: [ReactRouter.Navigation, ReactRouter.State],
9+
componentDidMount: function () {
10+
this.unsubscribe = AuthStore.listen(this.onListen)
11+
},
12+
componentWillUnmount: function () {
13+
this.unsubscribe()
14+
},
15+
onListen: function (res) {
16+
if (res.status === 'loggedIn' || res.status === 'registered') {
17+
var user = res.data
18+
var planet = user.Planets.length > 0 ? user.Planets[0] : null
19+
if (planet == null) {
20+
this.transitionTo('user', {userName: user.name})
21+
return
22+
}
23+
this.transitionTo('planetHome', {userName: user.name, planetName: planet.name})
24+
return
25+
}
26+
27+
if (res.status === 'loggedOut') {
28+
this.transitionTo('login')
29+
return
30+
}
31+
},
732
render: function () {
833
// Redirect Login state
934
if (this.getPath() === '/') {

browser/main/Containers/PlanetContainer.jsx

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,18 +56,21 @@ module.exports = React.createClass({
5656
},
5757
getInitialState: function () {
5858
return {
59+
currentUser: AuthStore.getUser(),
5960
currentPlanet: null,
6061
search: '',
6162
isFetched: false
6263
}
6364
},
6465
componentDidMount: function () {
65-
this.unsubscribe = PlanetStore.listen(this.onFetched)
66+
this.unsubscribePlanet = PlanetStore.listen(this.onFetched)
67+
this.unsubscribeAuth = AuthStore.listen(this.onListenAuth)
6668

6769
PlanetActions.fetchPlanet(this.props.params.userName, this.props.params.planetName)
6870
},
6971
componentWillUnmount: function () {
70-
this.unsubscribe()
72+
this.unsubscribePlanet()
73+
this.unsubscribeAuth()
7174
},
7275
componentDidUpdate: function () {
7376
if (this.state.currentPlanet == null || this.state.currentPlanet.name !== this.props.params.planetName || this.state.currentPlanet.userName !== this.props.params.userName) {
@@ -161,6 +164,19 @@ module.exports = React.createClass({
161164
React.findDOMNode(this).querySelector('.PlanetHeader .searchInput input').focus()
162165
}
163166
},
167+
onListenAuth: function (res) {
168+
if (res.status === 'userProfileUpdated') {
169+
if (this.state.currentPlanet != null) {
170+
res.data.Planets.some(function (planet) {
171+
if (planet.id === this.state.currentPlanet.id) {
172+
this.transitionTo('planet', {userName: planet.userName, planetName: planet.name})
173+
return true
174+
}
175+
return false
176+
}.bind(this))
177+
}
178+
}
179+
},
164180
onFetched: function (res) {
165181
if (res == null) {
166182
return
@@ -396,8 +412,7 @@ module.exports = React.createClass({
396412

397413
},
398414
render: function () {
399-
var user = AuthStore.getUser()
400-
if (user == null) return (<div/>)
415+
if (this.state.currentUser == null) return (<div/>)
401416
if (this.state.currentPlanet == null) return (<div/>)
402417

403418
var localId = parseInt(this.props.params.localId, 10)

0 commit comments

Comments
 (0)