mirror of
https://github.com/BoostIo/Boostnote
synced 2025-12-14 02:06:29 +00:00
usernavigator done
This commit is contained in:
@@ -20,7 +20,7 @@ export default class UserNavigator extends Component {
|
|||||||
<Link to={'/users/' + user.id} activeClassName='active'>
|
<Link to={'/users/' + user.id} activeClassName='active'>
|
||||||
<ProfileImage email={user.email} size='44'/>
|
<ProfileImage email={user.email} size='44'/>
|
||||||
<div className='userTooltip'>{user.name}</div>
|
<div className='userTooltip'>{user.name}</div>
|
||||||
<div className='keyLabel'>{'⌘' + (index + 1)}</div>
|
{index < 9 ? <div className='keyLabel'>{'⌘' + (index + 1)}</div> : null}
|
||||||
</Link>
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
))
|
))
|
||||||
|
|||||||
@@ -9,3 +9,27 @@ export function createTeam (input) {
|
|||||||
})
|
})
|
||||||
.send(input)
|
.send(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function searchUser (key) {
|
||||||
|
return request
|
||||||
|
.get(apiUrl + 'search/users')
|
||||||
|
.query({key: key})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setMember (teamId, input) {
|
||||||
|
return request
|
||||||
|
.post(apiUrl + 'teams/' + teamId + '/members')
|
||||||
|
.set({
|
||||||
|
Authorization: 'Bearer ' + localStorage.getItem('token')
|
||||||
|
})
|
||||||
|
.send(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function deleteMember (teamId, input) {
|
||||||
|
return request
|
||||||
|
.del(apiUrl + 'teams/' + teamId + '/members')
|
||||||
|
.set({
|
||||||
|
Authorization: 'Bearer ' + localStorage.getItem('token')
|
||||||
|
})
|
||||||
|
.send(input)
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,7 +1,25 @@
|
|||||||
import React, { PropTypes } from 'react'
|
import React, { PropTypes } from 'react'
|
||||||
import ProfileImage from '../../../components/ProfileImage'
|
import ProfileImage from '../../../components/ProfileImage'
|
||||||
import { createTeam } from '../api'
|
import { searchUser, createTeam, setMember, deleteMember } from '../api'
|
||||||
import linkState from '../../../helpers/linkState'
|
import linkState from '../../../helpers/linkState'
|
||||||
|
import Select from 'react-select'
|
||||||
|
|
||||||
|
function getUsers (input, cb) {
|
||||||
|
searchUser(input)
|
||||||
|
.then(function (res) {
|
||||||
|
let users = res.body
|
||||||
|
|
||||||
|
cb(null, {
|
||||||
|
options: users.map(user => {
|
||||||
|
return { value: user.name, label: user.name }
|
||||||
|
}),
|
||||||
|
complete: false
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.catch(function (err) {
|
||||||
|
console.error(err)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
export default class CreateNewTeam extends React.Component {
|
export default class CreateNewTeam extends React.Component {
|
||||||
constructor (props) {
|
constructor (props) {
|
||||||
@@ -12,16 +30,12 @@ export default class CreateNewTeam extends React.Component {
|
|||||||
alert: null
|
alert: null
|
||||||
},
|
},
|
||||||
select: {
|
select: {
|
||||||
team: {"name":"test123",
|
team: null,
|
||||||
"profileName":"test123",
|
newMember: null,
|
||||||
"userType":"team",
|
|
||||||
"updatedAt":"2015-10-11T09:01:01.277Z",
|
|
||||||
"createdAt":"2015-10-11T09:01:01.277Z",
|
|
||||||
"id":220,"Members":[{"id":213,"email":"fluke8259@gmail.com","name":"rokt33r","profileName":"Rokt33r","userType":"person","createdAt":"2015-10-05T09:01:30.000Z","updatedAt":"2015-10-05T09:01:30.000Z","_pivot_TeamId":220,"_pivot_MemberId":213,"_pivot_role":"owner"}]
|
|
||||||
},
|
|
||||||
alert: null
|
alert: null
|
||||||
},
|
},
|
||||||
currentTab: 'select'
|
currentTab: 'create',
|
||||||
|
currentUser: JSON.parse(localStorage.getItem('currentUser'))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,13 +70,13 @@ export default class CreateNewTeam extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function onError (err) {
|
function onError (err) {
|
||||||
let errorMessage = err.response != null ? err.response.body.message : err.message
|
let errorMessage = err.response != null ? err.response.body.message : 'Can\'t connect to API server.'
|
||||||
|
|
||||||
let createState = this.state.create
|
let createState = this.state.create
|
||||||
createState.isSending = false
|
createState.isSending = false
|
||||||
createState.alert = {
|
createState.alert = {
|
||||||
type: 'error',
|
type: 'error',
|
||||||
message: 'Can\'t connect to API server.'
|
message: errorMessage
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
@@ -91,11 +105,98 @@ export default class CreateNewTeam extends React.Component {
|
|||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
handleNewMemberChange (value) {
|
||||||
|
let selectState = this.state.select
|
||||||
|
selectState.newMember = value
|
||||||
|
this.setState({select: selectState})
|
||||||
|
}
|
||||||
|
|
||||||
|
handleClickAddMemberButton (e) {
|
||||||
|
let selectState = this.state.select
|
||||||
|
let input = {
|
||||||
|
name: selectState.newMember,
|
||||||
|
role: 'member'
|
||||||
|
}
|
||||||
|
|
||||||
|
setMember(selectState.team.id, input)
|
||||||
|
.then(res => {
|
||||||
|
let selectState = this.state.select
|
||||||
|
let team = res.body
|
||||||
|
team.Members = team.Members.sort((a, b) => {
|
||||||
|
return new Date(a._pivot_createdAt) - new Date(b._pivot_createdAt)
|
||||||
|
})
|
||||||
|
selectState.team = team
|
||||||
|
selectState.newMember = ''
|
||||||
|
|
||||||
|
this.setState({select: selectState})
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
if (err.status != null) throw err
|
||||||
|
else console.error(err)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
handleMemberDeleteButtonClick (name) {
|
||||||
|
let selectState = this.state.select
|
||||||
|
let input = {
|
||||||
|
name: name,
|
||||||
|
role: 'member'
|
||||||
|
}
|
||||||
|
|
||||||
|
return function (e) {
|
||||||
|
deleteMember(selectState.team.id, input)
|
||||||
|
.then(res => {
|
||||||
|
let selectState = this.state.select
|
||||||
|
let team = res.body
|
||||||
|
team.Members = team.Members.sort((a, b) => {
|
||||||
|
return new Date(a._pivot_createdAt) - new Date(b._pivot_createdAt)
|
||||||
|
})
|
||||||
|
selectState.team = team
|
||||||
|
selectState.newMember = ''
|
||||||
|
|
||||||
|
this.setState({select: selectState})
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.log(err, err.response)
|
||||||
|
if (err.status != null) throw err
|
||||||
|
else console.error(err)
|
||||||
|
})
|
||||||
|
}.bind(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
handleMemberRoleChange (name) {
|
||||||
|
return function (e) {
|
||||||
|
let selectState = this.state.select
|
||||||
|
let input = {
|
||||||
|
name: name,
|
||||||
|
role: e.target.value
|
||||||
|
}
|
||||||
|
|
||||||
|
setMember(selectState.team.id, input)
|
||||||
|
.then(res => {
|
||||||
|
let selectState = this.state.select
|
||||||
|
let team = res.body
|
||||||
|
team.Members = team.Members.sort((a, b) => {
|
||||||
|
return new Date(a._pivot_createdAt) - new Date(b._pivot_createdAt)
|
||||||
|
})
|
||||||
|
selectState.team = team
|
||||||
|
selectState.newMember = ''
|
||||||
|
|
||||||
|
this.setState({select: selectState})
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
if (err.status != null) throw err
|
||||||
|
else console.error(err)
|
||||||
|
})
|
||||||
|
}.bind(this)
|
||||||
|
}
|
||||||
|
|
||||||
renderSelectTab () {
|
renderSelectTab () {
|
||||||
let selectState = this.state.select
|
let selectState = this.state.select
|
||||||
console.log(selectState)
|
|
||||||
let membersEl = selectState.team.Members.map(member => {
|
let membersEl = selectState.team.Members.map(member => {
|
||||||
|
let isCurrentUser = this.state.currentUser.id === member.id
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<li key={'user-' + member.id}>
|
<li key={'user-' + member.id}>
|
||||||
<ProfileImage className='userPhoto' email={member.email} size='30'/>
|
<ProfileImage className='userPhoto' email={member.email} size='30'/>
|
||||||
@@ -103,12 +204,13 @@ export default class CreateNewTeam extends React.Component {
|
|||||||
<div className='userName'>{`${member.profileName} (${member.name})`}</div>
|
<div className='userName'>{`${member.profileName} (${member.name})`}</div>
|
||||||
<div className='userEmail'>{member.email}</div>
|
<div className='userEmail'>{member.email}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='userControl'>
|
<div className='userControl'>
|
||||||
<select value={member._pivot_role} className='userRole'>
|
<select onChange={e => this.handleMemberRoleChange(member.name)(e)} disabled={isCurrentUser} value={member._pivot_role} className='userRole'>
|
||||||
<option value='owner'>Owner</option>
|
<option value='owner'>Owner</option>
|
||||||
<option value='member'>Member</option>
|
<option value='member'>Member</option>
|
||||||
</select>
|
</select>
|
||||||
<button><i className='fa fa-times fa-fw'/></button>
|
<button onClick={e => this.handleMemberDeleteButtonClick(member.name)(e)} disabled={isCurrentUser}><i className='fa fa-times fa-fw'/></button>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
)
|
)
|
||||||
@@ -117,9 +219,15 @@ export default class CreateNewTeam extends React.Component {
|
|||||||
return (
|
return (
|
||||||
<div className='selectTab'>
|
<div className='selectTab'>
|
||||||
<div className='title'>Select member</div>
|
<div className='title'>Select member</div>
|
||||||
<div className='ipt'>
|
<div className='memberForm'>
|
||||||
<input type='text' placeholder='Enter user name or e-mail'/>
|
<Select
|
||||||
<button>add</button>
|
className='memberName'
|
||||||
|
autoload={false}
|
||||||
|
asyncOptions={getUsers}
|
||||||
|
onChange={val => this.handleNewMemberChange(val)}
|
||||||
|
value={selectState.newMember}
|
||||||
|
/>
|
||||||
|
<button onClick={e => this.handleClickAddMemberButton(e)} className='addMemberBtn'>add</button>
|
||||||
</div>
|
</div>
|
||||||
<ul className='memberList'>
|
<ul className='memberList'>
|
||||||
{membersEl}
|
{membersEl}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
bgColor = #E6E6E6
|
bgColor = #E6E6E6
|
||||||
inputBgColor = white
|
inputBgColor = white
|
||||||
|
iptFocusBorderColor = #369DCD
|
||||||
|
|
||||||
refreshBtColor = #B3B3B3
|
refreshBtColor = #B3B3B3
|
||||||
refreshBtnActiveColor = #3A3A3A
|
refreshBtnActiveColor = #3A3A3A
|
||||||
@@ -22,31 +23,32 @@ infoBtnActiveBgColor = #3A3A3A
|
|||||||
margin-top 13.5px
|
margin-top 13.5px
|
||||||
margin-left 15px
|
margin-left 15px
|
||||||
width 350px
|
width 350px
|
||||||
border-radius 22px
|
|
||||||
background-color inputBgColor
|
|
||||||
padding 5px 15px
|
padding 5px 15px
|
||||||
transition 0.1s
|
transition 0.1s
|
||||||
font-size 16px
|
font-size 16px
|
||||||
border 1px solid transparent
|
border 1px solid transparent
|
||||||
border-color transparent
|
|
||||||
&.focus
|
|
||||||
border-color brandBorderColor
|
|
||||||
input
|
input
|
||||||
absolute top right
|
absolute top left
|
||||||
left 35px
|
width 350px
|
||||||
width 300px
|
border-radius 16.5px
|
||||||
|
background-color inputBgColor
|
||||||
|
border 1px solid transparent
|
||||||
|
padding-left 35px
|
||||||
outline none
|
outline none
|
||||||
font-size 14px
|
font-size 14px
|
||||||
border none
|
|
||||||
height 33px
|
height 33px
|
||||||
line-height 33px
|
line-height 33px
|
||||||
background-color transparent
|
z-index 0
|
||||||
|
&:focus
|
||||||
|
border-color iptFocusBorderColor
|
||||||
i.fa
|
i.fa
|
||||||
position absolute
|
position absolute
|
||||||
display block
|
display block
|
||||||
top 0
|
top 0
|
||||||
left 10px
|
left 10px
|
||||||
line-height 33px
|
line-height 33px
|
||||||
|
z-index 1
|
||||||
|
pointer-events none
|
||||||
&>.refreshBtn
|
&>.refreshBtn
|
||||||
float left
|
float left
|
||||||
width 33px
|
width 33px
|
||||||
|
|||||||
@@ -13,7 +13,12 @@ userAnchorActiveBgColor = white
|
|||||||
text-align center
|
text-align center
|
||||||
box-sizing border-box
|
box-sizing border-box
|
||||||
ul.userList
|
ul.userList
|
||||||
margin-top 25px
|
position absolute
|
||||||
|
top 25px
|
||||||
|
left 0
|
||||||
|
right 0
|
||||||
|
bottom 70px
|
||||||
|
// overflow-y auto
|
||||||
&>li
|
&>li
|
||||||
a
|
a
|
||||||
display block
|
display block
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ stripBtnColor = lighten(stripHoverBtnColor, 35%)
|
|||||||
background-color transparent
|
background-color transparent
|
||||||
border none
|
border none
|
||||||
color stripBtnColor
|
color stripBtnColor
|
||||||
&hover
|
&:hover
|
||||||
color stripHoverBtnColor
|
color stripHoverBtnColor
|
||||||
.title
|
.title
|
||||||
font-size 32px
|
font-size 32px
|
||||||
@@ -36,7 +36,7 @@ stripBtnColor = lighten(stripHoverBtnColor, 35%)
|
|||||||
border-radius 5px
|
border-radius 5px
|
||||||
border solid 1px borderColor
|
border solid 1px borderColor
|
||||||
outline none
|
outline none
|
||||||
&focus
|
&:focus
|
||||||
border-color iptFocusBorderColor
|
border-color iptFocusBorderColor
|
||||||
.alert
|
.alert
|
||||||
padding 0 15px
|
padding 0 15px
|
||||||
@@ -47,6 +47,8 @@ stripBtnColor = lighten(stripHoverBtnColor, 35%)
|
|||||||
border-radius 5px
|
border-radius 5px
|
||||||
color infoTextColor
|
color infoTextColor
|
||||||
background-color infoBackgroundColor
|
background-color infoBackgroundColor
|
||||||
|
white-space nowrap
|
||||||
|
overflow-x auto
|
||||||
&.error
|
&.error
|
||||||
color errorTextColor
|
color errorTextColor
|
||||||
background-color errorBackgroundColor
|
background-color errorBackgroundColor
|
||||||
@@ -87,31 +89,56 @@ stripBtnColor = lighten(stripHoverBtnColor, 35%)
|
|||||||
.ipt
|
.ipt
|
||||||
margin 105px auto 15px
|
margin 105px auto 15px
|
||||||
.selectTab
|
.selectTab
|
||||||
.ipt
|
.memberForm
|
||||||
|
display block
|
||||||
margin 25px auto 15px
|
margin 25px auto 15px
|
||||||
|
width 330px
|
||||||
clearfix()
|
clearfix()
|
||||||
padding 0
|
padding 0
|
||||||
input
|
font-size 14px
|
||||||
|
height 44px
|
||||||
|
line-height 44px
|
||||||
|
outline none
|
||||||
|
.Select.memberName
|
||||||
display block
|
display block
|
||||||
margin 0
|
margin 0
|
||||||
float left
|
float left
|
||||||
width 280px
|
width 280px
|
||||||
height 42px
|
height 44px
|
||||||
padding 0 0 0 15px
|
|
||||||
font-size 14px
|
font-size 14px
|
||||||
border none
|
border none
|
||||||
line-height 44px
|
line-height 44px
|
||||||
background-color transparent
|
background-color transparent
|
||||||
outline none
|
outline none
|
||||||
&:hover
|
&.is-focus
|
||||||
|
.Select-control
|
||||||
|
border-color iptFocusBorderColor
|
||||||
|
.Select-control
|
||||||
|
height 44px
|
||||||
|
line-height 44px
|
||||||
|
padding 0 0 0 15px
|
||||||
|
border-radius 5px 0 0 5px
|
||||||
|
border 1px solid borderColor
|
||||||
|
border-right none
|
||||||
|
.Select-placeholder
|
||||||
|
padding 0 0 0 15px
|
||||||
|
.Seleect-arrow
|
||||||
|
top 21px
|
||||||
|
.Select-clear
|
||||||
|
padding 0 10px
|
||||||
|
.Select-noresults, .Select-option
|
||||||
|
line-height 44px
|
||||||
|
padding 0 0 0 15px
|
||||||
|
|
||||||
|
&:focus, &.focus
|
||||||
border-color iptFocusBorderColor
|
border-color iptFocusBorderColor
|
||||||
button
|
button
|
||||||
font-weight 400
|
font-weight 400
|
||||||
height 42px
|
height 44px
|
||||||
cursor pointer
|
cursor pointer
|
||||||
margin 0
|
margin 0
|
||||||
padding 0
|
padding 0
|
||||||
width 48px
|
width 50px
|
||||||
float right
|
float right
|
||||||
border none
|
border none
|
||||||
background-color brandColor
|
background-color brandColor
|
||||||
@@ -158,9 +185,9 @@ stripBtnColor = lighten(stripHoverBtnColor, 35%)
|
|||||||
margin-right 35px
|
margin-right 35px
|
||||||
outline none
|
outline none
|
||||||
cursor pointer
|
cursor pointer
|
||||||
&hover
|
&:hover
|
||||||
border-color borderColor
|
border-color borderColor
|
||||||
&focus
|
&:focus
|
||||||
border-color iptFocusBorderColor
|
border-color iptFocusBorderColor
|
||||||
button
|
button
|
||||||
border none
|
border none
|
||||||
@@ -168,5 +195,5 @@ stripBtnColor = lighten(stripHoverBtnColor, 35%)
|
|||||||
margin-top 7px
|
margin-top 7px
|
||||||
background-color transparent
|
background-color transparent
|
||||||
color stripBtnColor
|
color stripBtnColor
|
||||||
&hover
|
&:hover
|
||||||
color stripHoverBtnColor
|
color stripHoverBtnColor
|
||||||
|
|||||||
@@ -141,8 +141,8 @@
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
.Select-menu-outer {
|
.Select-menu-outer {
|
||||||
border-bottom-right-radius: 4px;
|
border-bottom-right-radius: 5px;
|
||||||
border-bottom-left-radius: 4px;
|
border-bottom-left-radius: 5px;
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
border: 1px solid #cccccc;
|
border: 1px solid #cccccc;
|
||||||
border-top-color: #e6e6e6;
|
border-top-color: #e6e6e6;
|
||||||
@@ -168,8 +168,8 @@
|
|||||||
padding: 8px 10px;
|
padding: 8px 10px;
|
||||||
}
|
}
|
||||||
.Select-option:last-child {
|
.Select-option:last-child {
|
||||||
border-bottom-right-radius: 4px;
|
border-bottom-right-radius: 5px;
|
||||||
border-bottom-left-radius: 4px;
|
border-bottom-left-radius: 5px;
|
||||||
}
|
}
|
||||||
.Select-option.is-focused {
|
.Select-option.is-focused {
|
||||||
background-color: #f2f9fc;
|
background-color: #f2f9fc;
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
output: {
|
output: {
|
||||||
filename: '[name].js',
|
filename: '[name].js',
|
||||||
|
sourceMapFilename: '[name].map',
|
||||||
publicPath: 'http://localhost:8090/assets',
|
publicPath: 'http://localhost:8090/assets',
|
||||||
libraryTarget: 'commonjs2'
|
libraryTarget: 'commonjs2'
|
||||||
},
|
},
|
||||||
@@ -41,7 +42,8 @@ module.exports = {
|
|||||||
'react-transform-hmr',
|
'react-transform-hmr',
|
||||||
'react-transform-catch-errors',
|
'react-transform-catch-errors',
|
||||||
'redux-devtools',
|
'redux-devtools',
|
||||||
'redux-devtools/lib/react'
|
'redux-devtools/lib/react',
|
||||||
|
'react-select'
|
||||||
],
|
],
|
||||||
resolve: {
|
resolve: {
|
||||||
extensions: ['', '.js', '.jsx', 'styl']
|
extensions: ['', '.js', '.jsx', 'styl']
|
||||||
|
|||||||
Reference in New Issue
Block a user