179 lines
4.6 KiB
TypeScript
179 lines
4.6 KiB
TypeScript
import { IUser, IUserInTeam, TReadonlyRecord, TeamActions, UserActions, Team } from '@rondo.dev/common'
|
|
import { Button, Control, Heading, Help, Input, Panel, PanelBlock, PanelHeading } from 'bloomer'
|
|
import React from 'react'
|
|
import { FaCheck, FaTimes, FaUser } from 'react-icons/fa'
|
|
|
|
const EMPTY_ARRAY: ReadonlyArray<string> = []
|
|
|
|
export interface ITeamUsersProps {
|
|
// fetchMyTeams: () => void,
|
|
fetchUsersInTeam: TeamActions['findUsers']
|
|
findUserByEmail: UserActions['findUserByEmail']
|
|
|
|
onAddUser: TeamActions['addUser']
|
|
onRemoveUser: TeamActions['removeUser']
|
|
|
|
team: Team
|
|
userKeysByTeamId: TReadonlyRecord<number, ReadonlyArray<string>>
|
|
usersByKey: TReadonlyRecord<string, IUserInTeam>
|
|
}
|
|
|
|
export interface ITeamUserProps {
|
|
onRemoveUser: (
|
|
params: {userId: number, teamId: number, roleId: number}) => void
|
|
user: IUserInTeam
|
|
}
|
|
|
|
export interface IAddUserProps {
|
|
onAddUser: TeamActions['addUser']
|
|
onSearchUser: UserActions['findUserByEmail']
|
|
teamId: number
|
|
}
|
|
|
|
export interface IAddUserState {
|
|
error: string
|
|
email: string
|
|
user?: IUser
|
|
}
|
|
|
|
export class TeamUser extends React.PureComponent<ITeamUserProps> {
|
|
handleRemoveUser = async () => {
|
|
const {onRemoveUser, user} = this.props
|
|
await onRemoveUser({...user, roleId: 1})
|
|
}
|
|
render() {
|
|
const {user} = this.props
|
|
// TODO style
|
|
return (
|
|
<React.Fragment>
|
|
<div className='user'>
|
|
{user.displayName}
|
|
</div>
|
|
<div className='ml-auto'>
|
|
<Button
|
|
aria-label='Remove'
|
|
isColor='danger'
|
|
isInverted
|
|
className='team-user-remove'
|
|
onClick={this.handleRemoveUser}
|
|
>
|
|
<FaTimes />
|
|
</Button>
|
|
</div>
|
|
</React.Fragment>
|
|
)
|
|
}
|
|
}
|
|
|
|
export class AddUser extends React.PureComponent<IAddUserProps, IAddUserState> {
|
|
constructor(props: IAddUserProps) {
|
|
super(props)
|
|
this.state = {
|
|
error: '',
|
|
email: '',
|
|
user: undefined,
|
|
}
|
|
}
|
|
handleChangeEmail = (event: React.ChangeEvent<HTMLInputElement>) => {
|
|
const email = event.target.value
|
|
this.setState({email})
|
|
}
|
|
handleAddUser = async (event: React.FormEvent) => {
|
|
event.preventDefault()
|
|
const {teamId} = this.props
|
|
const {email} = this.state
|
|
const user = await this.props.onSearchUser(email).payload
|
|
if (!user) {
|
|
// TODO handle this better via 404 status code
|
|
this.setState({error: 'No user found'})
|
|
return
|
|
}
|
|
await this.props.onAddUser({
|
|
teamId,
|
|
userId: user.id,
|
|
roleId: 1,
|
|
})
|
|
|
|
this.setState({error: '', email: '', user: undefined})
|
|
}
|
|
render() {
|
|
const {error} = this.state
|
|
|
|
return (
|
|
<form autoComplete='off' onSubmit={this.handleAddUser}>
|
|
<Heading>Add User</Heading>
|
|
<Control hasIcons='left'>
|
|
<Input
|
|
isColor={error ? 'danger' : ''}
|
|
onChange={this.handleChangeEmail}
|
|
placeholder='Email'
|
|
type='email'
|
|
value={this.state.email}
|
|
/>
|
|
<span className='icon is-left'>
|
|
<FaUser />
|
|
</span>
|
|
{error && (
|
|
<Help isColor='danger'>{error}</Help>
|
|
)}
|
|
</Control>
|
|
<div className='mt-1 text-right'>
|
|
<Button
|
|
isColor='dark'
|
|
type='submit'
|
|
>
|
|
<FaCheck className='mr-1' />
|
|
Add
|
|
</Button>
|
|
</div>
|
|
</form>
|
|
)
|
|
}
|
|
}
|
|
|
|
export class TeamUserList extends React.PureComponent<ITeamUsersProps> {
|
|
async componentDidMount() {
|
|
await this.fetchUsersInTeam(this.props.team.id)
|
|
} async componentWillReceiveProps(nextProps: ITeamUsersProps) {
|
|
const {team} = nextProps
|
|
if (team.id !== this.props.team.id) {
|
|
this.fetchUsersInTeam(team.id)
|
|
}
|
|
}
|
|
async fetchUsersInTeam(teamId: number) {
|
|
if (teamId) {
|
|
await this.props.fetchUsersInTeam(teamId)
|
|
}
|
|
}
|
|
render() {
|
|
const userKeysByTeamId = this.props.userKeysByTeamId[this.props.team.id]
|
|
|| EMPTY_ARRAY
|
|
|
|
return (
|
|
<Panel>
|
|
<PanelHeading>Users in Team</PanelHeading>
|
|
{userKeysByTeamId.map(key => {
|
|
const user = this.props.usersByKey[key]
|
|
return (
|
|
<PanelBlock key={key}>
|
|
<TeamUser
|
|
key={key}
|
|
user={user}
|
|
onRemoveUser={this.props.onRemoveUser}
|
|
/>
|
|
</PanelBlock>
|
|
)
|
|
})}
|
|
|
|
<PanelBlock isDisplay='block'>
|
|
<AddUser
|
|
onAddUser={this.props.onAddUser}
|
|
onSearchUser={this.props.findUserByEmail}
|
|
teamId={this.props.team.id}
|
|
/>
|
|
</PanelBlock>
|
|
</Panel>
|
|
)
|
|
}
|
|
}
|