mirror of
https://github.com/BoostIo/Boostnote
synced 2025-12-14 10:16:26 +00:00
on Refactor... #4
This commit is contained in:
@@ -11,20 +11,20 @@ var UserStore = require('../Stores/UserStore')
|
|||||||
module.exports = React.createClass({
|
module.exports = React.createClass({
|
||||||
mixins: [LinkedState],
|
mixins: [LinkedState],
|
||||||
propTypes: {
|
propTypes: {
|
||||||
targetUser: React.PropTypes.shape({
|
user: React.PropTypes.shape({
|
||||||
name: React.PropTypes.string,
|
name: React.PropTypes.string,
|
||||||
profileName: React.PropTypes.string,
|
profileName: React.PropTypes.string,
|
||||||
email: React.PropTypes.string
|
email: React.PropTypes.string
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
getInitialState: function () {
|
getInitialState: function () {
|
||||||
var targetUser = this.props.targetUser
|
var user = this.props.user
|
||||||
return {
|
return {
|
||||||
currentTab: 'userInfo',
|
currentTab: 'userInfo',
|
||||||
user: {
|
user: {
|
||||||
name: targetUser.name,
|
name: user.name,
|
||||||
profileName: targetUser.profileName,
|
profileName: user.profileName,
|
||||||
email: targetUser.email
|
email: user.email
|
||||||
},
|
},
|
||||||
userSubmitStatus: null,
|
userSubmitStatus: null,
|
||||||
password: {
|
password: {
|
||||||
@@ -44,7 +44,7 @@ module.exports = React.createClass({
|
|||||||
this.setState({
|
this.setState({
|
||||||
userSubmitStatus: 'sending'
|
userSubmitStatus: 'sending'
|
||||||
}, function () {
|
}, function () {
|
||||||
Hq.updateUser(this.props.targetUser.name, this.state.user)
|
Hq.updateUser(this.props.user.name, this.state.user)
|
||||||
.then(function (res) {
|
.then(function (res) {
|
||||||
this.setState({userSubmitStatus: 'done'}, function () {
|
this.setState({userSubmitStatus: 'done'}, function () {
|
||||||
localStorage.setItem('currentUser', JSON.stringify(res.body))
|
localStorage.setItem('currentUser', JSON.stringify(res.body))
|
||||||
@@ -138,7 +138,7 @@ module.exports = React.createClass({
|
|||||||
},
|
},
|
||||||
renderPasswordTab: function () {
|
renderPasswordTab: function () {
|
||||||
return (
|
return (
|
||||||
<div className='paswordTab'>
|
<div className='passwordTab'>
|
||||||
<div className='formField'>
|
<div className='formField'>
|
||||||
<label>Current password</label>
|
<label>Current password</label>
|
||||||
<input valueLink={this.linkState('password.currentPassword')}/>
|
<input valueLink={this.linkState('password.currentPassword')}/>
|
||||||
|
|||||||
@@ -27,8 +27,36 @@ module.exports = React.createClass({
|
|||||||
onUserChange: function (res) {
|
onUserChange: function (res) {
|
||||||
switch (res.status) {
|
switch (res.status) {
|
||||||
case 'userUpdated':
|
case 'userUpdated':
|
||||||
if (this.state.currentUser.id === res.data.id) {
|
var user = res.data
|
||||||
this.setState({currentUser: res.data})
|
var currentUser = this.state.currentUser
|
||||||
|
if (currentUser.id === user.id) {
|
||||||
|
this.setState({currentUser: user})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (user.userType === 'team') {
|
||||||
|
var isMyTeam = user.Members.some(function (member) {
|
||||||
|
if (currentUser.id === member.id) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
|
||||||
|
if (isMyTeam) {
|
||||||
|
var isNew = !currentUser.Teams.some(function (team, index) {
|
||||||
|
if (user.id === team.id) {
|
||||||
|
currentUser.Teams.splice(index, 1, user)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
|
||||||
|
if (isNew) {
|
||||||
|
currentUser.Teams.push(user)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState({currentUser: currentUser})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -104,7 +132,10 @@ module.exports = React.createClass({
|
|||||||
<ul className='planetList'>
|
<ul className='planetList'>
|
||||||
{planets}
|
{planets}
|
||||||
</ul>
|
</ul>
|
||||||
<button onClick={this.openPlanetCreateModal} className='newPlanet'><i className='fa fa-plus'/></button>
|
<button onClick={this.openPlanetCreateModal} className='newPlanet'>
|
||||||
|
<i className='fa fa-plus'/>
|
||||||
|
<div className='newPlanetTooltip'>Create new planet</div>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,30 +1,30 @@
|
|||||||
/* global localStorage */
|
/* global localStorage */
|
||||||
|
|
||||||
var React = require('react/addons')
|
var React = require('react/addons')
|
||||||
var Select = require('react-select')
|
|
||||||
|
|
||||||
var Hq = require('../Services/Hq')
|
var Hq = require('../Services/Hq')
|
||||||
|
|
||||||
var LinkedState = require('../Mixins/LinkedState')
|
var LinkedState = require('../Mixins/LinkedState')
|
||||||
|
|
||||||
var UserStore = require('../Stores/UserStore')
|
|
||||||
var PlanetStore = require('../Stores/PlanetStore')
|
var PlanetStore = require('../Stores/PlanetStore')
|
||||||
|
|
||||||
module.exports = React.createClass({
|
module.exports = React.createClass({
|
||||||
mixins: [LinkedState],
|
mixins: [LinkedState],
|
||||||
propTypes: {
|
propTypes: {
|
||||||
|
ownerName: React.PropTypes.string,
|
||||||
transitionTo: React.PropTypes.func,
|
transitionTo: React.PropTypes.func,
|
||||||
close: React.PropTypes.func
|
close: React.PropTypes.func
|
||||||
},
|
},
|
||||||
getInitialState: function () {
|
getInitialState: function () {
|
||||||
var currentUser = JSON.parse(localStorage.getItem('currentUser'))
|
var currentUser = JSON.parse(localStorage.getItem('currentUser'))
|
||||||
|
var ownerName = this.props.ownerName != null ? this.props.ownerName : currentUser.name
|
||||||
return {
|
return {
|
||||||
user: currentUser,
|
user: currentUser,
|
||||||
planet: {
|
planet: {
|
||||||
name: '',
|
name: '',
|
||||||
public: true
|
public: true
|
||||||
},
|
},
|
||||||
ownerName: currentUser.name
|
ownerName: ownerName
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
componentDidMount: function () {
|
componentDidMount: function () {
|
||||||
@@ -42,7 +42,10 @@ module.exports = React.createClass({
|
|||||||
|
|
||||||
PlanetStore.Actions.update(planet)
|
PlanetStore.Actions.update(planet)
|
||||||
|
|
||||||
|
if (this.props.transitionTo != null) {
|
||||||
this.props.transitionTo('planetHome', {userName: planet.userName, planetName: planet.name})
|
this.props.transitionTo('planetHome', {userName: planet.userName, planetName: planet.name})
|
||||||
|
}
|
||||||
|
|
||||||
this.props.close()
|
this.props.close()
|
||||||
}.bind(this))
|
}.bind(this))
|
||||||
.catch(function (err) {
|
.catch(function (err) {
|
||||||
@@ -52,7 +55,7 @@ module.exports = React.createClass({
|
|||||||
render: function () {
|
render: function () {
|
||||||
var teamOptions = this.state.user.Teams.map(function (team) {
|
var teamOptions = this.state.user.Teams.map(function (team) {
|
||||||
return (
|
return (
|
||||||
<option value={team.name}>{team.profileName} ({team.name})</option>
|
<option key={'user-' + team.id} value={team.name}>{team.profileName} ({team.name})</option>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -33,7 +33,10 @@ module.exports = React.createClass({
|
|||||||
currentUser.Teams.push(team)
|
currentUser.Teams.push(team)
|
||||||
localStorage.setItem('currentUser', JSON.stringify(currentUser))
|
localStorage.setItem('currentUser', JSON.stringify(currentUser))
|
||||||
UserStore.Actions.update(currentUser)
|
UserStore.Actions.update(currentUser)
|
||||||
|
|
||||||
|
if (this.props.transitionTo != null) {
|
||||||
this.props.transitionTo('userHome', {userName: team.name})
|
this.props.transitionTo('userHome', {userName: team.name})
|
||||||
|
}
|
||||||
this.props.close()
|
this.props.close()
|
||||||
}.bind(this))
|
}.bind(this))
|
||||||
.catch(function (err) {
|
.catch(function (err) {
|
||||||
|
|||||||
108
browser/main/Components/TeamSettingsModal.jsx
Normal file
108
browser/main/Components/TeamSettingsModal.jsx
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
/* global localStorage */
|
||||||
|
|
||||||
|
var React = require('react/addons')
|
||||||
|
|
||||||
|
var Hq = require('../Services/Hq')
|
||||||
|
|
||||||
|
var LinkedState = require('../Mixins/LinkedState')
|
||||||
|
|
||||||
|
var UserStore = require('../Stores/UserStore')
|
||||||
|
|
||||||
|
module.exports = React.createClass({
|
||||||
|
mixins: [LinkedState],
|
||||||
|
propTypes: {
|
||||||
|
team: React.PropTypes.shape({
|
||||||
|
name: React.PropTypes.string,
|
||||||
|
profileName: React.PropTypes.string,
|
||||||
|
email: React.PropTypes.string
|
||||||
|
})
|
||||||
|
},
|
||||||
|
getInitialState: function () {
|
||||||
|
var team = this.props.team
|
||||||
|
return {
|
||||||
|
currentTab: 'teamInfo',
|
||||||
|
team: {
|
||||||
|
name: team.name,
|
||||||
|
profileName: team.profileName
|
||||||
|
},
|
||||||
|
userSubmitStatus: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
selectTab: function (tabName) {
|
||||||
|
return function () {
|
||||||
|
this.setState({currentTab: tabName})
|
||||||
|
}.bind(this)
|
||||||
|
},
|
||||||
|
saveUserInfo: function () {
|
||||||
|
this.setState({
|
||||||
|
userSubmitStatus: 'sending'
|
||||||
|
}, function () {
|
||||||
|
Hq.updateUser(this.props.team.name, this.state.team)
|
||||||
|
.then(function (res) {
|
||||||
|
this.setState({userSubmitStatus: 'done'}, function () {
|
||||||
|
UserStore.Actions.update(res.body)
|
||||||
|
})
|
||||||
|
}.bind(this))
|
||||||
|
.catch(function (err) {
|
||||||
|
console.error(err)
|
||||||
|
this.setState({userSubmitStatus: 'error'})
|
||||||
|
}.bind(this))
|
||||||
|
})
|
||||||
|
},
|
||||||
|
render: function () {
|
||||||
|
var content
|
||||||
|
|
||||||
|
switch (this.state.currentTab) {
|
||||||
|
case 'teamInfo':
|
||||||
|
content = this.renderTeamInfoTab()
|
||||||
|
break
|
||||||
|
case 'members':
|
||||||
|
content = this.renderMembersTab()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='EditProfileModal modal tabModal'>
|
||||||
|
<div className='leftPane'>
|
||||||
|
<div className='tabLabel'>Team settings</div>
|
||||||
|
<div className='tabList'>
|
||||||
|
<button className={this.state.currentTab === 'teamInfo' ? 'active' : ''} onClick={this.selectTab('teamInfo')}><i className='fa fa-info-circle fa-fw'/> Team Info</button>
|
||||||
|
<button className={this.state.currentTab === 'members' ? 'active' : ''} onClick={this.selectTab('members')}><i className='fa fa-users fa-fw'/> Members</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className='rightPane'>
|
||||||
|
{content}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
renderTeamInfoTab: function () {
|
||||||
|
return (
|
||||||
|
<div className='userInfoTab'>
|
||||||
|
<div className='formField'>
|
||||||
|
<label>Profile Name</label>
|
||||||
|
<input valueLink={this.linkState('team.profileName')}/>
|
||||||
|
</div>
|
||||||
|
<div className='formField'>
|
||||||
|
<label>Name</label>
|
||||||
|
<input valueLink={this.linkState('team.name')}/>
|
||||||
|
</div>
|
||||||
|
<div className='formConfirm'>
|
||||||
|
<button disabled={this.state.userSubmitStatus === 'sending'} onClick={this.saveUserInfo}>Save</button>
|
||||||
|
|
||||||
|
<div className={'alertInfo' + (this.state.userSubmitStatus === 'sending' ? '' : ' hide')}>on Sending...</div>
|
||||||
|
|
||||||
|
<div className={'alertError' + (this.state.userSubmitStatus === 'error' ? '' : ' hide')}>Connection failed.. Try again.</div>
|
||||||
|
|
||||||
|
<div className={'alertSuccess' + (this.state.userSubmitStatus === 'done' ? '' : ' hide')}>Successfully done!!</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
renderMembersTab: function () {
|
||||||
|
return (
|
||||||
|
<div className='membersTab'>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
@@ -76,17 +76,6 @@ module.exports = React.createClass({
|
|||||||
|
|
||||||
<nav className='authNavigator text-center'><Link to='login'>Log In</Link> / <Link to='signup'>Sign Up</Link></nav>
|
<nav className='authNavigator text-center'><Link to='login'>Log In</Link> / <Link to='signup'>Sign Up</Link></nav>
|
||||||
|
|
||||||
<div className='socialControl'>
|
|
||||||
<p>Connect with</p>
|
|
||||||
<button className='facebookBtn'><i className='fa fa-facebook fa-fw'/></button>
|
|
||||||
<button className='githubBtn'><i className='fa fa-github fa-fw'/></button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className='divider'>
|
|
||||||
<hr/>
|
|
||||||
<div className='dividerLabel'>or</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<form onSubmit={this.handleSubmit}>
|
<form onSubmit={this.handleSubmit}>
|
||||||
<div className='form-group'>
|
<div className='form-group'>
|
||||||
<input className='stripInput' valueLink={this.linkState('user.email')} type='text' placeholder='E-mail'/>
|
<input className='stripInput' valueLink={this.linkState('user.email')} type='text' placeholder='E-mail'/>
|
||||||
|
|||||||
@@ -49,13 +49,16 @@ module.exports = React.createClass({
|
|||||||
|
|
||||||
Hq.getUser()
|
Hq.getUser()
|
||||||
.then(function (res) {
|
.then(function (res) {
|
||||||
|
console.log(res.body)
|
||||||
localStorage.setItem('currentUser', JSON.stringify(res.body))
|
localStorage.setItem('currentUser', JSON.stringify(res.body))
|
||||||
UserStore.Actions.update(res.body)
|
UserStore.Actions.update(res.body)
|
||||||
})
|
})
|
||||||
.catch(function (err) {
|
.catch(function (err) {
|
||||||
if (err.status === 401) {
|
if (err.status === 401) {
|
||||||
|
console.log('Not logged in yet')
|
||||||
localStorage.removeItem('currentUser')
|
localStorage.removeItem('currentUser')
|
||||||
this.transitionTo('login')
|
this.transitionTo('login')
|
||||||
|
return
|
||||||
}
|
}
|
||||||
console.error(err)
|
console.error(err)
|
||||||
}.bind(this))
|
}.bind(this))
|
||||||
|
|||||||
@@ -30,7 +30,6 @@ module.exports = React.createClass({
|
|||||||
}, function () {
|
}, function () {
|
||||||
Hq.signup(this.state.user)
|
Hq.signup(this.state.user)
|
||||||
.then(function (res) {
|
.then(function (res) {
|
||||||
console.log(res.body)
|
|
||||||
localStorage.setItem('token', res.body.token)
|
localStorage.setItem('token', res.body.token)
|
||||||
localStorage.setItem('currentUser', JSON.stringify(res.body.user))
|
localStorage.setItem('currentUser', JSON.stringify(res.body.user))
|
||||||
|
|
||||||
@@ -91,11 +90,6 @@ module.exports = React.createClass({
|
|||||||
|
|
||||||
<nav className='authNavigator text-center'><Link to='login'>Log In</Link> / <Link to='signup'>Sign Up</Link></nav>
|
<nav className='authNavigator text-center'><Link to='login'>Log In</Link> / <Link to='signup'>Sign Up</Link></nav>
|
||||||
|
|
||||||
<div className='divider'>
|
|
||||||
<hr/>
|
|
||||||
<div className='dividerLabel'>or</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<form onSubmit={this.handleSubmit}>
|
<form onSubmit={this.handleSubmit}>
|
||||||
<div className='form-group'>
|
<div className='form-group'>
|
||||||
<input className='stripInput' valueLink={this.linkState('user.email')} type='text' placeholder='E-mail'/>
|
<input className='stripInput' valueLink={this.linkState('user.email')} type='text' placeholder='E-mail'/>
|
||||||
|
|||||||
@@ -1,21 +1,30 @@
|
|||||||
|
/* global localStorage */
|
||||||
|
|
||||||
var React = require('react/addons')
|
var React = require('react/addons')
|
||||||
var ReactRouter = require('react-router')
|
var ReactRouter = require('react-router')
|
||||||
|
var Navigation = ReactRouter.Navigation
|
||||||
|
var State = ReactRouter.State
|
||||||
var RouteHandler = ReactRouter.RouteHandler
|
var RouteHandler = ReactRouter.RouteHandler
|
||||||
var Link = ReactRouter.Link
|
var Link = ReactRouter.Link
|
||||||
var Reflux = require('reflux')
|
var Reflux = require('reflux')
|
||||||
|
|
||||||
var LinkedState = require('../Mixins/LinkedState')
|
var LinkedState = require('../Mixins/LinkedState')
|
||||||
var Modal = require('../Mixins/Modal')
|
var Modal = require('../Mixins/Modal')
|
||||||
|
var Helper = require('../Mixins/Helper')
|
||||||
|
|
||||||
var Hq = require('../Services/Hq')
|
var Hq = require('../Services/Hq')
|
||||||
|
|
||||||
var ProfileImage = require('../Components/ProfileImage')
|
var ProfileImage = require('../Components/ProfileImage')
|
||||||
var EditProfileModal = require('../Components/EditProfileModal')
|
var EditProfileModal = require('../Components/EditProfileModal')
|
||||||
|
var TeamSettingsModal = require('../Components/TeamSettingsModal')
|
||||||
|
var PlanetCreateModal = require('../Components/PlanetCreateModal')
|
||||||
|
var TeamCreateModal = require('../Components/TeamCreateModal')
|
||||||
|
|
||||||
var UserStore = require('../Stores/UserStore')
|
var UserStore = require('../Stores/UserStore')
|
||||||
|
var PlanetStore = require('../Stores/PlanetStore')
|
||||||
|
|
||||||
module.exports = React.createClass({
|
module.exports = React.createClass({
|
||||||
mixins: [LinkedState, ReactRouter.State, Modal, Reflux.listenTo(UserStore, 'onUserChange')],
|
mixins: [LinkedState, State, Navigation, Modal, Reflux.listenTo(UserStore, 'onUserChange'), Reflux.listenTo(PlanetStore, 'onPlanetChange'), Helper],
|
||||||
propTypes: {
|
propTypes: {
|
||||||
params: React.PropTypes.shape({
|
params: React.PropTypes.shape({
|
||||||
userName: React.PropTypes.string,
|
userName: React.PropTypes.string,
|
||||||
@@ -55,6 +64,67 @@ module.exports = React.createClass({
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
onPlanetChange: function (res) {
|
||||||
|
if (this.state.user == null) return
|
||||||
|
|
||||||
|
var currentUser, planet, isOwner, team
|
||||||
|
switch (res.status) {
|
||||||
|
case 'updated':
|
||||||
|
// if state.user is currentUser, planet will be fetched by UserStore
|
||||||
|
currentUser = JSON.parse(localStorage.getItem('currentUser'))
|
||||||
|
if (currentUser.id === this.state.user.id) return
|
||||||
|
|
||||||
|
planet = res.data
|
||||||
|
isOwner = planet.Owner.id === this.state.user.id
|
||||||
|
if (isOwner) {
|
||||||
|
this.state.user.Planets = this.updateItemToTargetArray(planet, this.state.user.Planets)
|
||||||
|
this.setState({user: this.state.user})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// check if team of user has this planet
|
||||||
|
team = null
|
||||||
|
this.state.user.userType !== 'team' && this.state.user.Teams.some(function (_team) {
|
||||||
|
if (planet.Owner.id === _team.id) {
|
||||||
|
team = _team
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
if (team != null) {
|
||||||
|
team.Planets = this.updateItemToTargetArray(planet, team.Planets)
|
||||||
|
this.setState({user: this.state.user})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
break
|
||||||
|
case 'destroyed':
|
||||||
|
// if state.user is currentUser, planet will be fetched by UserStore
|
||||||
|
currentUser = JSON.parse(localStorage.getItem('currentUser'))
|
||||||
|
if (currentUser.id === this.state.user.id) return
|
||||||
|
|
||||||
|
planet = res.data
|
||||||
|
isOwner = planet.Owner.id === this.state.user.id
|
||||||
|
if (isOwner) {
|
||||||
|
this.state.user.Planets = this.deleteItemFromTargetArray(planet, this.state.user.Planets)
|
||||||
|
this.setState({user: this.state.user})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// check if team of user has this planet
|
||||||
|
team = null
|
||||||
|
this.state.user.userType !== 'team' && this.state.user.Teams.some(function (_team) {
|
||||||
|
if (planet.Owner.id === _team.id) {
|
||||||
|
team = _team
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
if (team != null) {
|
||||||
|
team.Planets = this.deleteItemFromTargetArray(planet, team.Planets)
|
||||||
|
this.setState({user: this.state.user})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
fetchUser: function (userName) {
|
fetchUser: function (userName) {
|
||||||
if (userName == null) userName = this.props.params.userName
|
if (userName == null) userName = this.props.params.userName
|
||||||
|
|
||||||
@@ -67,11 +137,27 @@ module.exports = React.createClass({
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
openEditProfileModal: function () {
|
openEditProfileModal: function () {
|
||||||
this.openModal(EditProfileModal, {targetUser: this.state.user})
|
this.openModal(EditProfileModal, {user: this.state.user})
|
||||||
|
},
|
||||||
|
openTeamSettingsModal: function () {
|
||||||
|
this.openModal(TeamSettingsModal, {team: this.state.user})
|
||||||
|
},
|
||||||
|
openAddUserModal: function () {
|
||||||
|
|
||||||
|
},
|
||||||
|
openTeamCreateModal: function () {
|
||||||
|
this.openModal(TeamCreateModal, {user: this.state.user})
|
||||||
|
},
|
||||||
|
openPlanetCreateModalWithOwnerName: function (name) {
|
||||||
|
return function () {
|
||||||
|
this.openModal(PlanetCreateModal, {ownerName: name})
|
||||||
|
}.bind(this)
|
||||||
},
|
},
|
||||||
render: function () {
|
render: function () {
|
||||||
var user = this.state.user
|
var user = this.state.user
|
||||||
|
|
||||||
|
var currentUser = JSON.parse(localStorage.getItem('currentUser'))
|
||||||
|
|
||||||
if (this.isActive('userHome')) {
|
if (this.isActive('userHome')) {
|
||||||
if (user == null) {
|
if (user == null) {
|
||||||
return (
|
return (
|
||||||
@@ -80,9 +166,9 @@ module.exports = React.createClass({
|
|||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
} else if (user.userType === 'team') {
|
} else if (user.userType === 'team') {
|
||||||
return this.renderTeamHome()
|
return this.renderTeamHome(currentUser)
|
||||||
} else {
|
} else {
|
||||||
return this.renderUserHome()
|
return this.renderUserHome(currentUser)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
@@ -92,13 +178,16 @@ module.exports = React.createClass({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
renderTeamHome: function () {
|
renderTeamHome: function (currentUser) {
|
||||||
var user = this.state.user
|
var user = this.state.user
|
||||||
|
|
||||||
|
var isOwner = true
|
||||||
|
|
||||||
var userPlanets = user.Planets.map(function (planet) {
|
var userPlanets = user.Planets.map(function (planet) {
|
||||||
return (
|
return (
|
||||||
<li key={'planet-' + planet.id}>
|
<li key={'planet-' + planet.id}>
|
||||||
<Link to='planet' params={{userName: planet.userName, planetName: planet.name}}>{planet.userName}/{planet.name}</Link>
|
<Link to='planet' params={{userName: planet.userName, planetName: planet.name}}>{planet.userName}/{planet.name}</Link>
|
||||||
|
{!planet.public ? (<i className='fa fa-lock'/>) : null}
|
||||||
</li>
|
</li>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
@@ -107,6 +196,7 @@ module.exports = React.createClass({
|
|||||||
return (
|
return (
|
||||||
<li key={'user-' + member.id}>
|
<li key={'user-' + member.id}>
|
||||||
<Link to='userHome' params={{userName: member.name}}>{member.profileName} ({member.name})</Link>
|
<Link to='userHome' params={{userName: member.name}}>{member.profileName} ({member.name})</Link>
|
||||||
|
<div className='role'>{member.TeamMember.role}</div>
|
||||||
</li>
|
</li>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
@@ -119,7 +209,7 @@ module.exports = React.createClass({
|
|||||||
<div className='userName'>{user.name}</div>
|
<div className='userName'>{user.name}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button onClick={this.openEditProfileModal} className='editProfileButton'>Edit profile</button>
|
<button onClick={this.openTeamSettingsModal} className='editProfileButton'>Team settings</button>
|
||||||
</div>
|
</div>
|
||||||
<div className='memberList'>
|
<div className='memberList'>
|
||||||
<div className='memberLabel'>{members.length} {members.length > 0 ? 'Members' : 'Member'}</div>
|
<div className='memberLabel'>{members.length} {members.length > 0 ? 'Members' : 'Member'}</div>
|
||||||
@@ -132,15 +222,18 @@ module.exports = React.createClass({
|
|||||||
<div className='planetGroup'>
|
<div className='planetGroup'>
|
||||||
<ul className='planets'>
|
<ul className='planets'>
|
||||||
{userPlanets}
|
{userPlanets}
|
||||||
|
{isOwner ? (<li><button onClick={this.openPlanetCreateModalWithOwnerName(user.name)} className='createPlanetButton'><i className='fa fa-plus-square-o'/> Create new planet</button></li>) : null}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
renderUserHome: function () {
|
renderUserHome: function (currentUser) {
|
||||||
var user = this.state.user
|
var user = this.state.user
|
||||||
|
|
||||||
|
var isOwner = currentUser.id === user.id
|
||||||
|
|
||||||
var userPlanets = user.Planets.map(function (planet) {
|
var userPlanets = user.Planets.map(function (planet) {
|
||||||
return (
|
return (
|
||||||
<li key={'planet-' + planet.id}>
|
<li key={'planet-' + planet.id}>
|
||||||
@@ -159,7 +252,7 @@ module.exports = React.createClass({
|
|||||||
})
|
})
|
||||||
|
|
||||||
var teamPlanets = user.Teams == null ? [] : user.Teams.map(function (team) {
|
var teamPlanets = user.Teams == null ? [] : user.Teams.map(function (team) {
|
||||||
var planets = team.Planets.map(function (planet) {
|
var planets = (team.Planets == null ? [] : team.Planets).map(function (planet) {
|
||||||
return (
|
return (
|
||||||
<li key={'planet-' + planet.id}>
|
<li key={'planet-' + planet.id}>
|
||||||
<Link to='planet' params={{userName: planet.userName, planetName: planet.name}}>{planet.userName}/{planet.name}</Link>
|
<Link to='planet' params={{userName: planet.userName, planetName: planet.name}}>{planet.userName}/{planet.name}</Link>
|
||||||
@@ -172,10 +265,11 @@ module.exports = React.createClass({
|
|||||||
<div className='planetGroupLabel'>{team.name}</div>
|
<div className='planetGroupLabel'>{team.name}</div>
|
||||||
<ul className='planets'>
|
<ul className='planets'>
|
||||||
{planets}
|
{planets}
|
||||||
|
{isOwner ? (<li><button onClick={this.openPlanetCreateModalWithOwnerName(team.name)} className='createPlanetButton'><i className='fa fa-plus-square-o'/> Create new planet</button></li>) : null}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
})
|
}.bind(this))
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='UserContainer'>
|
<div className='UserContainer'>
|
||||||
@@ -186,20 +280,25 @@ module.exports = React.createClass({
|
|||||||
<div className='userName'>{user.name}</div>
|
<div className='userName'>{user.name}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button onClick={this.openEditProfileModal} className='editProfileButton'>Edit profile</button>
|
{isOwner ? (
|
||||||
|
<button onClick={this.openEditProfileModal} className='editProfileButton'>Edit profile</button>) : null}
|
||||||
</div>
|
</div>
|
||||||
<div className='teamList'>
|
<div className='teamList'>
|
||||||
<div className='teamLabel'>{teams.length} {teams.length > 0 ? 'Teams' : 'Team'}</div>
|
<div className='teamLabel'>{teams.length} {teams.length > 0 ? 'Teams' : 'Team'}</div>
|
||||||
<ul className='teams'>
|
<ul className='teams'>
|
||||||
{teams}
|
{teams}
|
||||||
|
{isOwner ? (<li><button onClick={this.openTeamCreateModal} className='createTeamButton'><i className='fa fa-plus-square-o'/> Create new team</button></li>) : null}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div className='planetList'>
|
<div className='planetList'>
|
||||||
<div className='planetLabel'>{userPlanets.length} {userPlanets.length > 0 ? 'Planets' : 'Planet'}</div>
|
<div className='planetLabel'>{userPlanets.length + user.Teams.reduce(function (sum, team) {
|
||||||
|
return sum + (team.Planets != null ? team.Planets.length : 0)
|
||||||
|
}, 0)} {userPlanets.length > 0 ? 'Planets' : 'Planet'}</div>
|
||||||
<div className='planetGroup'>
|
<div className='planetGroup'>
|
||||||
<div className='planetGroupLabel'>{user.profileName}</div>
|
<div className='planetGroupLabel'>{user.profileName}</div>
|
||||||
<ul className='planets'>
|
<ul className='planets'>
|
||||||
{userPlanets}
|
{userPlanets}
|
||||||
|
{isOwner ? (<li><button onClick={this.openPlanetCreateModalWithOwnerName(user.name)} className='createPlanetButton'><i className='fa fa-plus-square-o'/> Create new planet</button></li>) : null}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
{teamPlanets}
|
{teamPlanets}
|
||||||
|
|||||||
30
browser/main/Mixins/Helper.js
Normal file
30
browser/main/Mixins/Helper.js
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
function deleteItemFromTargetArray (item, targetArray) {
|
||||||
|
targetArray.some(function (_item, index) {
|
||||||
|
if (_item.id === item.id) {
|
||||||
|
targetArray.splice(index, 1)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
|
||||||
|
return targetArray
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateItemToTargetArray (item, targetArray) {
|
||||||
|
var isNew = !targetArray.some(function (_item, index) {
|
||||||
|
if (_item.id === item.id) {
|
||||||
|
targetArray.splice(index, 1, item)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
|
||||||
|
if (isNew) targetArray.push(item)
|
||||||
|
|
||||||
|
return targetArray
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
deleteItemFromTargetArray: deleteItemFromTargetArray,
|
||||||
|
updateItemToTargetArray: updateItemToTargetArray
|
||||||
|
}
|
||||||
@@ -4,6 +4,8 @@ var Reflux = require('reflux')
|
|||||||
|
|
||||||
var UserStore = require('./UserStore')
|
var UserStore = require('./UserStore')
|
||||||
|
|
||||||
|
var Helper = require('../Mixins/Helper')
|
||||||
|
|
||||||
var actions = Reflux.createActions([
|
var actions = Reflux.createActions([
|
||||||
'update',
|
'update',
|
||||||
'destroy',
|
'destroy',
|
||||||
@@ -13,33 +15,8 @@ var actions = Reflux.createActions([
|
|||||||
'destroyNote'
|
'destroyNote'
|
||||||
])
|
])
|
||||||
|
|
||||||
function deleteItemFromTargetArray (item, targetArray) {
|
|
||||||
targetArray.some(function (_item, index) {
|
|
||||||
if (_item.id === item.id) {
|
|
||||||
targetArray.splice(index, 1)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
})
|
|
||||||
|
|
||||||
return targetArray
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateItemToTargetArray (item, targetArray) {
|
|
||||||
var isNew = !targetArray.some(function (_item, index) {
|
|
||||||
if (_item.id === item.id) {
|
|
||||||
targetArray.splice(index, 1, item)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
})
|
|
||||||
|
|
||||||
if (isNew) targetArray.push(item)
|
|
||||||
|
|
||||||
return targetArray
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = Reflux.createStore({
|
module.exports = Reflux.createStore({
|
||||||
|
mixins: [Helper],
|
||||||
listenables: [actions],
|
listenables: [actions],
|
||||||
Actions: actions,
|
Actions: actions,
|
||||||
onUpdate: function (planet) {
|
onUpdate: function (planet) {
|
||||||
@@ -54,7 +31,7 @@ module.exports = Reflux.createStore({
|
|||||||
var ownedByCurrentUser = currentUser.id === aPlanet.OwnerId
|
var ownedByCurrentUser = currentUser.id === aPlanet.OwnerId
|
||||||
|
|
||||||
if (ownedByCurrentUser) {
|
if (ownedByCurrentUser) {
|
||||||
currentUser.Planets = updateItemToTargetArray(aPlanet, currentUser.Planets)
|
currentUser.Planets = this.updateItemToTargetArray(aPlanet, currentUser.Planets)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ownedByCurrentUser) {
|
if (!ownedByCurrentUser) {
|
||||||
@@ -68,7 +45,7 @@ module.exports = Reflux.createStore({
|
|||||||
})
|
})
|
||||||
|
|
||||||
if (team) {
|
if (team) {
|
||||||
team.Planets = updateItemToTargetArray(aPlanet, team.Planets)
|
team.Planets = this.updateItemToTargetArray(aPlanet, team.Planets)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,7 +68,7 @@ module.exports = Reflux.createStore({
|
|||||||
var ownedByCurrentUser = currentUser.id === planet.OwnerId
|
var ownedByCurrentUser = currentUser.id === planet.OwnerId
|
||||||
|
|
||||||
if (ownedByCurrentUser) {
|
if (ownedByCurrentUser) {
|
||||||
currentUser.Planets = deleteItemFromTargetArray(planet, currentUser.Planets)
|
currentUser.Planets = this.deleteItemFromTargetArray(planet, currentUser.Planets)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ownedByCurrentUser) {
|
if (!ownedByCurrentUser) {
|
||||||
@@ -105,7 +82,7 @@ module.exports = Reflux.createStore({
|
|||||||
})
|
})
|
||||||
|
|
||||||
if (team) {
|
if (team) {
|
||||||
team.Planets = deleteItemFromTargetArray(planet, team.Planets)
|
team.Planets = this.deleteItemFromTargetArray(planet, team.Planets)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,7 +103,7 @@ module.exports = Reflux.createStore({
|
|||||||
|
|
||||||
var planet = JSON.parse(localStorage.getItem('planet-' + code.PlanetId))
|
var planet = JSON.parse(localStorage.getItem('planet-' + code.PlanetId))
|
||||||
if (planet != null) {
|
if (planet != null) {
|
||||||
planet.Codes = updateItemToTargetArray(code, planet.Codes)
|
planet.Codes = this.updateItemToTargetArray(code, planet.Codes)
|
||||||
|
|
||||||
localStorage.setItem('planet-' + code.PlanetId, JSON.stringify(planet))
|
localStorage.setItem('planet-' + code.PlanetId, JSON.stringify(planet))
|
||||||
}
|
}
|
||||||
@@ -139,7 +116,7 @@ module.exports = Reflux.createStore({
|
|||||||
onDestroyCode: function (code) {
|
onDestroyCode: function (code) {
|
||||||
var planet = JSON.parse(localStorage.getItem('planet-' + code.PlanetId))
|
var planet = JSON.parse(localStorage.getItem('planet-' + code.PlanetId))
|
||||||
if (planet != null) {
|
if (planet != null) {
|
||||||
planet.Codes = deleteItemFromTargetArray(code, planet.Codes)
|
planet.Codes = this.deleteItemFromTargetArray(code, planet.Codes)
|
||||||
|
|
||||||
localStorage.setItem('planet-' + code.PlanetId, JSON.stringify(planet))
|
localStorage.setItem('planet-' + code.PlanetId, JSON.stringify(planet))
|
||||||
}
|
}
|
||||||
@@ -155,7 +132,7 @@ module.exports = Reflux.createStore({
|
|||||||
|
|
||||||
var planet = JSON.parse(localStorage.getItem('planet-' + note.PlanetId))
|
var planet = JSON.parse(localStorage.getItem('planet-' + note.PlanetId))
|
||||||
if (planet != null) {
|
if (planet != null) {
|
||||||
planet.Notes = updateItemToTargetArray(note, planet.Notes)
|
planet.Notes = this.updateItemToTargetArray(note, planet.Notes)
|
||||||
|
|
||||||
localStorage.setItem('planet-' + note.PlanetId, JSON.stringify(planet))
|
localStorage.setItem('planet-' + note.PlanetId, JSON.stringify(planet))
|
||||||
}
|
}
|
||||||
@@ -168,7 +145,7 @@ module.exports = Reflux.createStore({
|
|||||||
onDestroyNote: function (note) {
|
onDestroyNote: function (note) {
|
||||||
var planet = JSON.parse(localStorage.getItem('planet-' + note.PlanetId))
|
var planet = JSON.parse(localStorage.getItem('planet-' + note.PlanetId))
|
||||||
if (planet != null) {
|
if (planet != null) {
|
||||||
planet.Notes = deleteItemFromTargetArray(note, planet.Notes)
|
planet.Notes = this.deleteItemFromTargetArray(note, planet.Notes)
|
||||||
|
|
||||||
localStorage.setItem('planet-' + note.PlanetId, JSON.stringify(planet))
|
localStorage.setItem('planet-' + note.PlanetId, JSON.stringify(planet))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
/* global localStorage */
|
||||||
|
|
||||||
var Reflux = require('reflux')
|
var Reflux = require('reflux')
|
||||||
|
|
||||||
var actions = Reflux.createActions([
|
var actions = Reflux.createActions([
|
||||||
@@ -8,6 +10,36 @@ var actions = Reflux.createActions([
|
|||||||
module.exports = Reflux.createStore({
|
module.exports = Reflux.createStore({
|
||||||
listenables: [actions],
|
listenables: [actions],
|
||||||
onUpdate: function (user) {
|
onUpdate: function (user) {
|
||||||
|
var currentUser = JSON.parse(localStorage.getItem('currentUser'))
|
||||||
|
|
||||||
|
if (currentUser.id === user.id) {
|
||||||
|
localStorage.setItem('currentUser', JSON.stringify(user))
|
||||||
|
}
|
||||||
|
|
||||||
|
if (user.userType === 'team') {
|
||||||
|
var isMyTeam = user.Members.some(function (member) {
|
||||||
|
if (currentUser.id === member.id) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
|
||||||
|
if (isMyTeam) {
|
||||||
|
var isNew = !currentUser.Teams.some(function (team, index) {
|
||||||
|
if (user.id === team.id) {
|
||||||
|
currentUser.Teams.splice(index, 1, user)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
|
||||||
|
if (isNew) {
|
||||||
|
currentUser.Teams.push(user)
|
||||||
|
}
|
||||||
|
localStorage.setItem('currentUser', JSON.stringify(currentUser))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.trigger({
|
this.trigger({
|
||||||
status: 'userUpdated',
|
status: 'userUpdated',
|
||||||
data: user
|
data: user
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
display block
|
display block
|
||||||
margin 0 auto
|
margin 0 auto
|
||||||
.authNavigator
|
.authNavigator
|
||||||
margin 15px 0
|
margin 15px 0 25px
|
||||||
a
|
a
|
||||||
font-size 1.5em
|
font-size 1.5em
|
||||||
text-decoration none
|
text-decoration none
|
||||||
@@ -47,7 +47,8 @@
|
|||||||
.dividerLabel
|
.dividerLabel
|
||||||
text-align center
|
text-align center
|
||||||
position relative
|
position relative
|
||||||
top -35px
|
top -27px
|
||||||
|
font-size 1.3em
|
||||||
background-color backgroundColor
|
background-color backgroundColor
|
||||||
margin 0 auto
|
margin 0 auto
|
||||||
width 50px
|
width 50px
|
||||||
|
|||||||
@@ -166,6 +166,23 @@
|
|||||||
border-color darken(brandBorderColor, 10%)
|
border-color darken(brandBorderColor, 10%)
|
||||||
background-color brandColor
|
background-color brandColor
|
||||||
color white
|
color white
|
||||||
|
.newPlanetTooltip
|
||||||
|
position fixed
|
||||||
|
z-index 500
|
||||||
|
background-color transparentify(invBackgroundColor, 80%)
|
||||||
|
color invTextColor
|
||||||
|
padding 10px
|
||||||
|
line-height 1em
|
||||||
|
border-radius 5px
|
||||||
|
margin-top -23px
|
||||||
|
margin-left 33px
|
||||||
|
white-space nowrap
|
||||||
|
font-size 1.1em
|
||||||
|
opacity 0
|
||||||
|
transition 0.1s
|
||||||
|
pointer-events none
|
||||||
|
&:hover .newPlanetTooltip
|
||||||
|
opacity 1
|
||||||
.UserContainer
|
.UserContainer
|
||||||
absolute top bottom right
|
absolute top bottom right
|
||||||
left 55px
|
left 55px
|
||||||
@@ -208,6 +225,13 @@
|
|||||||
li
|
li
|
||||||
margin-bottom 10px
|
margin-bottom 10px
|
||||||
font-size 1.1em
|
font-size 1.1em
|
||||||
|
.createTeamButton, .addMemberButton
|
||||||
|
btnStripDefault()
|
||||||
|
.members .role
|
||||||
|
margin-left 7px
|
||||||
|
margin-top 2px
|
||||||
|
color inactiveTextColor
|
||||||
|
font-size 0.85em
|
||||||
.planetList
|
.planetList
|
||||||
absolute right bottom
|
absolute right bottom
|
||||||
top 125px
|
top 125px
|
||||||
@@ -226,3 +250,5 @@
|
|||||||
margin-left 15px
|
margin-left 15px
|
||||||
li
|
li
|
||||||
margin-bottom 10px
|
margin-bottom 10px
|
||||||
|
.createPlanetButton
|
||||||
|
btnStripDefault()
|
||||||
|
|||||||
@@ -1,33 +0,0 @@
|
|||||||
.UserSettingContainer
|
|
||||||
absolute top bottom right
|
|
||||||
left 50px
|
|
||||||
.UserSettingNavigation
|
|
||||||
absolute top bottom left
|
|
||||||
width 200px
|
|
||||||
padding 15px
|
|
||||||
box-sizing border-box
|
|
||||||
border-right solid 1px borderColor
|
|
||||||
.userName
|
|
||||||
font-size 2.0em
|
|
||||||
margin 10px 0
|
|
||||||
color brandColor
|
|
||||||
a
|
|
||||||
display block
|
|
||||||
color textColor
|
|
||||||
width 100%
|
|
||||||
padding 15px
|
|
||||||
margin-bottom 5px
|
|
||||||
border-radius 10px
|
|
||||||
box-sizing border-box
|
|
||||||
cursor pointer
|
|
||||||
&:hover, &.hover
|
|
||||||
color brandColor
|
|
||||||
background-color hoverBackgroundColor
|
|
||||||
&:active, &.active
|
|
||||||
color brandColor
|
|
||||||
|
|
||||||
.UserSettingMain
|
|
||||||
absolute top bottom right
|
|
||||||
left 200px
|
|
||||||
padding 10px
|
|
||||||
box-sizing border-box
|
|
||||||
@@ -58,7 +58,7 @@
|
|||||||
padding 15px
|
padding 15px
|
||||||
|
|
||||||
.EditProfileModal, .PlanetSettingModal
|
.EditProfileModal, .PlanetSettingModal
|
||||||
.userInfoTab, .paswordTab, .planetProfileTab
|
.userInfoTab, .passwordTab, .planetProfileTab, .userInfoTab, .membersTab
|
||||||
padding-top 45px
|
padding-top 45px
|
||||||
.formField
|
.formField
|
||||||
position relative
|
position relative
|
||||||
|
|||||||
Reference in New Issue
Block a user