mirror of
https://github.com/BoostIo/Boostnote
synced 2025-12-13 01:36:22 +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'>
|
||||
<ProfileImage email={user.email} size='44'/>
|
||||
<div className='userTooltip'>{user.name}</div>
|
||||
<div className='keyLabel'>{'⌘' + (index + 1)}</div>
|
||||
{index < 9 ? <div className='keyLabel'>{'⌘' + (index + 1)}</div> : null}
|
||||
</Link>
|
||||
</li>
|
||||
))
|
||||
|
||||
@@ -9,3 +9,27 @@ export function createTeam (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 ProfileImage from '../../../components/ProfileImage'
|
||||
import { createTeam } from '../api'
|
||||
import { searchUser, createTeam, setMember, deleteMember } from '../api'
|
||||
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 {
|
||||
constructor (props) {
|
||||
@@ -12,16 +30,12 @@ export default class CreateNewTeam extends React.Component {
|
||||
alert: null
|
||||
},
|
||||
select: {
|
||||
team: {"name":"test123",
|
||||
"profileName":"test123",
|
||||
"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"}]
|
||||
},
|
||||
team: null,
|
||||
newMember: 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) {
|
||||
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
|
||||
createState.isSending = false
|
||||
createState.alert = {
|
||||
type: 'error',
|
||||
message: 'Can\'t connect to API server.'
|
||||
message: errorMessage
|
||||
}
|
||||
|
||||
this.setState({
|
||||
@@ -91,11 +105,98 @@ export default class CreateNewTeam extends React.Component {
|
||||
</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 () {
|
||||
let selectState = this.state.select
|
||||
console.log(selectState)
|
||||
|
||||
let membersEl = selectState.team.Members.map(member => {
|
||||
let isCurrentUser = this.state.currentUser.id === member.id
|
||||
|
||||
return (
|
||||
<li key={'user-' + member.id}>
|
||||
<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='userEmail'>{member.email}</div>
|
||||
</div>
|
||||
|
||||
<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='member'>Member</option>
|
||||
</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>
|
||||
</li>
|
||||
)
|
||||
@@ -117,9 +219,15 @@ export default class CreateNewTeam extends React.Component {
|
||||
return (
|
||||
<div className='selectTab'>
|
||||
<div className='title'>Select member</div>
|
||||
<div className='ipt'>
|
||||
<input type='text' placeholder='Enter user name or e-mail'/>
|
||||
<button>add</button>
|
||||
<div className='memberForm'>
|
||||
<Select
|
||||
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>
|
||||
<ul className='memberList'>
|
||||
{membersEl}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
bgColor = #E6E6E6
|
||||
inputBgColor = white
|
||||
iptFocusBorderColor = #369DCD
|
||||
|
||||
refreshBtColor = #B3B3B3
|
||||
refreshBtnActiveColor = #3A3A3A
|
||||
@@ -22,31 +23,32 @@ infoBtnActiveBgColor = #3A3A3A
|
||||
margin-top 13.5px
|
||||
margin-left 15px
|
||||
width 350px
|
||||
border-radius 22px
|
||||
background-color inputBgColor
|
||||
padding 5px 15px
|
||||
transition 0.1s
|
||||
font-size 16px
|
||||
border 1px solid transparent
|
||||
border-color transparent
|
||||
&.focus
|
||||
border-color brandBorderColor
|
||||
input
|
||||
absolute top right
|
||||
left 35px
|
||||
width 300px
|
||||
absolute top left
|
||||
width 350px
|
||||
border-radius 16.5px
|
||||
background-color inputBgColor
|
||||
border 1px solid transparent
|
||||
padding-left 35px
|
||||
outline none
|
||||
font-size 14px
|
||||
border none
|
||||
height 33px
|
||||
line-height 33px
|
||||
background-color transparent
|
||||
z-index 0
|
||||
&:focus
|
||||
border-color iptFocusBorderColor
|
||||
i.fa
|
||||
position absolute
|
||||
display block
|
||||
top 0
|
||||
left 10px
|
||||
line-height 33px
|
||||
z-index 1
|
||||
pointer-events none
|
||||
&>.refreshBtn
|
||||
float left
|
||||
width 33px
|
||||
|
||||
@@ -13,7 +13,12 @@ userAnchorActiveBgColor = white
|
||||
text-align center
|
||||
box-sizing border-box
|
||||
ul.userList
|
||||
margin-top 25px
|
||||
position absolute
|
||||
top 25px
|
||||
left 0
|
||||
right 0
|
||||
bottom 70px
|
||||
// overflow-y auto
|
||||
&>li
|
||||
a
|
||||
display block
|
||||
|
||||
@@ -19,7 +19,7 @@ stripBtnColor = lighten(stripHoverBtnColor, 35%)
|
||||
background-color transparent
|
||||
border none
|
||||
color stripBtnColor
|
||||
&hover
|
||||
&:hover
|
||||
color stripHoverBtnColor
|
||||
.title
|
||||
font-size 32px
|
||||
@@ -36,7 +36,7 @@ stripBtnColor = lighten(stripHoverBtnColor, 35%)
|
||||
border-radius 5px
|
||||
border solid 1px borderColor
|
||||
outline none
|
||||
&focus
|
||||
&:focus
|
||||
border-color iptFocusBorderColor
|
||||
.alert
|
||||
padding 0 15px
|
||||
@@ -47,6 +47,8 @@ stripBtnColor = lighten(stripHoverBtnColor, 35%)
|
||||
border-radius 5px
|
||||
color infoTextColor
|
||||
background-color infoBackgroundColor
|
||||
white-space nowrap
|
||||
overflow-x auto
|
||||
&.error
|
||||
color errorTextColor
|
||||
background-color errorBackgroundColor
|
||||
@@ -87,31 +89,56 @@ stripBtnColor = lighten(stripHoverBtnColor, 35%)
|
||||
.ipt
|
||||
margin 105px auto 15px
|
||||
.selectTab
|
||||
.ipt
|
||||
.memberForm
|
||||
display block
|
||||
margin 25px auto 15px
|
||||
width 330px
|
||||
clearfix()
|
||||
padding 0
|
||||
input
|
||||
font-size 14px
|
||||
height 44px
|
||||
line-height 44px
|
||||
outline none
|
||||
.Select.memberName
|
||||
display block
|
||||
margin 0
|
||||
float left
|
||||
width 280px
|
||||
height 42px
|
||||
padding 0 0 0 15px
|
||||
height 44px
|
||||
font-size 14px
|
||||
border none
|
||||
line-height 44px
|
||||
background-color transparent
|
||||
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
|
||||
button
|
||||
font-weight 400
|
||||
height 42px
|
||||
height 44px
|
||||
cursor pointer
|
||||
margin 0
|
||||
padding 0
|
||||
width 48px
|
||||
width 50px
|
||||
float right
|
||||
border none
|
||||
background-color brandColor
|
||||
@@ -158,9 +185,9 @@ stripBtnColor = lighten(stripHoverBtnColor, 35%)
|
||||
margin-right 35px
|
||||
outline none
|
||||
cursor pointer
|
||||
&hover
|
||||
&:hover
|
||||
border-color borderColor
|
||||
&focus
|
||||
&:focus
|
||||
border-color iptFocusBorderColor
|
||||
button
|
||||
border none
|
||||
@@ -168,5 +195,5 @@ stripBtnColor = lighten(stripHoverBtnColor, 35%)
|
||||
margin-top 7px
|
||||
background-color transparent
|
||||
color stripBtnColor
|
||||
&hover
|
||||
&:hover
|
||||
color stripHoverBtnColor
|
||||
|
||||
@@ -141,8 +141,8 @@
|
||||
cursor: pointer;
|
||||
}
|
||||
.Select-menu-outer {
|
||||
border-bottom-right-radius: 4px;
|
||||
border-bottom-left-radius: 4px;
|
||||
border-bottom-right-radius: 5px;
|
||||
border-bottom-left-radius: 5px;
|
||||
background-color: #ffffff;
|
||||
border: 1px solid #cccccc;
|
||||
border-top-color: #e6e6e6;
|
||||
@@ -168,8 +168,8 @@
|
||||
padding: 8px 10px;
|
||||
}
|
||||
.Select-option:last-child {
|
||||
border-bottom-right-radius: 4px;
|
||||
border-bottom-left-radius: 4px;
|
||||
border-bottom-right-radius: 5px;
|
||||
border-bottom-left-radius: 5px;
|
||||
}
|
||||
.Select-option.is-focused {
|
||||
background-color: #f2f9fc;
|
||||
|
||||
@@ -5,6 +5,7 @@ module.exports = {
|
||||
},
|
||||
output: {
|
||||
filename: '[name].js',
|
||||
sourceMapFilename: '[name].map',
|
||||
publicPath: 'http://localhost:8090/assets',
|
||||
libraryTarget: 'commonjs2'
|
||||
},
|
||||
@@ -41,7 +42,8 @@ module.exports = {
|
||||
'react-transform-hmr',
|
||||
'react-transform-catch-errors',
|
||||
'redux-devtools',
|
||||
'redux-devtools/lib/react'
|
||||
'redux-devtools/lib/react',
|
||||
'react-select'
|
||||
],
|
||||
resolve: {
|
||||
extensions: ['', '.js', '.jsx', 'styl']
|
||||
|
||||
Reference in New Issue
Block a user