1
0
mirror of https://github.com/BoostIo/Boostnote synced 2025-12-13 01:36:22 +00:00

usernavigator done

This commit is contained in:
Rokt33r
2015-10-12 15:52:54 +09:00
parent 1690e6420f
commit a9e12e4384
8 changed files with 214 additions and 46 deletions

View File

@@ -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>
))

View File

@@ -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)
}

View File

@@ -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}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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;

View File

@@ -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']