Style team manager
This commit is contained in:
parent
77838e8e0c
commit
3bcf9d646e
@ -2,6 +2,11 @@ import React from 'react'
|
||||
import {ITeam, ReadonlyRecord} from '@rondo/common'
|
||||
import {Link} from 'react-router-dom'
|
||||
import {TeamActions} from './TeamActions'
|
||||
import {FaPlusSquare, FaSave, FaEdit, FaTimes} from 'react-icons/fa'
|
||||
|
||||
import {
|
||||
Button, Control, Heading, Input, Panel, PanelHeading, PanelBlock
|
||||
} from 'bloomer'
|
||||
|
||||
export interface ITeamListProps {
|
||||
teamsById: ReadonlyRecord<number, ITeam>,
|
||||
@ -14,7 +19,7 @@ export interface ITeamListProps {
|
||||
|
||||
export interface ITeamProps {
|
||||
team: ITeam
|
||||
editTeamId?: number // TODO handle edits via react-router params
|
||||
editTeamId?: number
|
||||
onRemoveTeam: TeamActions['removeTeam']
|
||||
onUpdateTeam: TeamActions['updateTeam']
|
||||
}
|
||||
@ -33,7 +38,18 @@ export class TeamAdd extends React.PureComponent<IAddTeamProps, IAddTeamState> {
|
||||
constructor(props: IAddTeamProps) {
|
||||
super(props)
|
||||
this.state = {
|
||||
name: props.team ? props.team.name : '',
|
||||
name: this.getName(props.team),
|
||||
}
|
||||
}
|
||||
getName(team?: ITeam) {
|
||||
return team ? team.name : ''
|
||||
}
|
||||
componentWillReceiveProps(nextProps: IAddTeamProps) {
|
||||
const {team} = nextProps
|
||||
if (team !== this.props.team) {
|
||||
this.setState({
|
||||
name: this.getName(team),
|
||||
})
|
||||
}
|
||||
}
|
||||
handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
@ -53,16 +69,28 @@ export class TeamAdd extends React.PureComponent<IAddTeamProps, IAddTeamState> {
|
||||
render() {
|
||||
return (
|
||||
<form className='team-add' onSubmit={this.handleSubmit}>
|
||||
{this.props.team ? 'Edit team' : 'Add team'}
|
||||
<input
|
||||
type='text'
|
||||
value={this.state.name}
|
||||
onChange={this.handleChange}
|
||||
/>
|
||||
<input
|
||||
type='submit'
|
||||
value='Save'
|
||||
/>
|
||||
<Heading>
|
||||
{this.props.team ? 'Edit team' : 'Add team'}
|
||||
</Heading>
|
||||
<Control hasIcons='left'>
|
||||
<Input
|
||||
placeholder='New Team Name'
|
||||
type='text'
|
||||
value={this.state.name}
|
||||
onChange={this.handleChange}
|
||||
/>
|
||||
<span className='icon is-left'>
|
||||
<FaPlusSquare />
|
||||
</span>
|
||||
</Control>
|
||||
<div className='text-right mt-1'>
|
||||
<Button
|
||||
className='button is-primary'
|
||||
type='submit'
|
||||
>
|
||||
<FaSave className='mr-1' /> Save
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
)
|
||||
}
|
||||
@ -76,19 +104,26 @@ export class TeamRow extends React.PureComponent<ITeamProps> {
|
||||
render() {
|
||||
const {team} = this.props
|
||||
return (
|
||||
<div className='team'>
|
||||
{team.id}
|
||||
{this.props.editTeamId !== team.id
|
||||
? team.name
|
||||
: <TeamAdd
|
||||
onAddTeam={undefined as any}
|
||||
onUpdateTeam={this.props.onUpdateTeam}
|
||||
team={team}
|
||||
/>
|
||||
}
|
||||
<Link to={`/teams/${team.id}/users`}>Edit</Link>
|
||||
<button onClick={this.handleRemove}>Remove</button>
|
||||
</div>
|
||||
<React.Fragment>
|
||||
<div className='team-name'>
|
||||
{team.name}
|
||||
</div>
|
||||
<div className='ml-auto'>
|
||||
<Link to={`/teams/${team.id}/users`}>
|
||||
<Button aria-label='Edit'>
|
||||
<FaEdit />
|
||||
</Button>
|
||||
</Link>
|
||||
|
||||
<Button
|
||||
aria-label='Remove'
|
||||
onClick={this.handleRemove}
|
||||
isColor='danger'
|
||||
>
|
||||
<FaTimes />
|
||||
</Button>
|
||||
</div>
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -98,24 +133,43 @@ export class TeamList extends React.PureComponent<ITeamListProps> {
|
||||
const {editTeamId, teamIds, teamsById} = this.props
|
||||
|
||||
return (
|
||||
<div className='team-list'>
|
||||
{teamIds.map(teamId => {
|
||||
const team = teamsById[teamId]
|
||||
return (
|
||||
<TeamRow
|
||||
key={team.id}
|
||||
editTeamId={editTeamId}
|
||||
onRemoveTeam={this.props.onRemoveTeam}
|
||||
<Panel>
|
||||
{!editTeamId && (
|
||||
<React.Fragment>
|
||||
<PanelHeading>Teams</PanelHeading>
|
||||
{teamIds.map(teamId => {
|
||||
const team = teamsById[teamId]
|
||||
return (
|
||||
<PanelBlock key={team.id}>
|
||||
<TeamRow
|
||||
editTeamId={editTeamId}
|
||||
onRemoveTeam={this.props.onRemoveTeam}
|
||||
onUpdateTeam={this.props.onUpdateTeam}
|
||||
team={team}
|
||||
/>
|
||||
</PanelBlock>
|
||||
)
|
||||
})}
|
||||
|
||||
<PanelBlock isDisplay='block'>
|
||||
<TeamAdd
|
||||
onAddTeam={this.props.onAddTeam}
|
||||
onUpdateTeam={undefined as any}
|
||||
/>
|
||||
</PanelBlock>
|
||||
</React.Fragment>
|
||||
)}
|
||||
|
||||
{editTeamId && (
|
||||
<PanelBlock isDisplay='block'>
|
||||
<TeamAdd
|
||||
team={teamsById[editTeamId]}
|
||||
onAddTeam={undefined as any}
|
||||
onUpdateTeam={this.props.onUpdateTeam}
|
||||
team={team}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
<TeamAdd
|
||||
onAddTeam={this.props.onAddTeam}
|
||||
onUpdateTeam={undefined as any}
|
||||
/>
|
||||
</div>
|
||||
</PanelBlock>
|
||||
)}
|
||||
</Panel>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,10 +1,11 @@
|
||||
import React from 'react'
|
||||
import {Title} from 'bloomer'
|
||||
import {History, Location} from 'history'
|
||||
import {ITeam, IUserInTeam, ReadonlyRecord} from '@rondo/common'
|
||||
import {TeamActions} from './TeamActions'
|
||||
import {TeamList} from './TeamList'
|
||||
import {TeamUserList} from './TeamUserList'
|
||||
import {TeamActions} from './TeamActions'
|
||||
import {match} from 'react-router'
|
||||
import {History, Location} from 'history'
|
||||
|
||||
export interface ITeamManagerProps {
|
||||
history: History
|
||||
@ -35,15 +36,15 @@ export class TeamManager extends React.PureComponent<ITeamManagerProps> {
|
||||
await this.props.fetchMyTeams()
|
||||
}
|
||||
render() {
|
||||
// TODO load my teams on first launch
|
||||
// TODO use teamId from route url
|
||||
// TODO use editTeamId from route url
|
||||
// const {editTeamId} = this.props
|
||||
const editTeamId = this.props.match.params.teamId !== undefined ?
|
||||
Number(this.props.match.params.teamId) : undefined
|
||||
// TypeOrm changes BigInt fields to Strings because they can be tool
|
||||
// large...
|
||||
const editTeamId = this.props.match.params.teamId as any as
|
||||
number | undefined
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<div className='team-manager'>
|
||||
<Title>Teams</Title>
|
||||
|
||||
<TeamList
|
||||
editTeamId={editTeamId}
|
||||
teamsById={this.props.teamsById}
|
||||
@ -65,7 +66,7 @@ export class TeamManager extends React.PureComponent<ITeamManagerProps> {
|
||||
usersByKey={this.props.usersByKey}
|
||||
/>}
|
||||
|
||||
</React.Fragment>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -119,5 +119,4 @@ export function Team(state = defaultState, action: TeamActionType): ITeamState {
|
||||
default:
|
||||
return state
|
||||
}
|
||||
return state
|
||||
}
|
||||
|
||||
@ -1,6 +1,11 @@
|
||||
import React from 'react'
|
||||
import {IUser, IUserInTeam, ReadonlyRecord} from '@rondo/common'
|
||||
import {TeamActions} from './TeamActions'
|
||||
import {FaUser, FaSave, FaTimes} from 'react-icons/fa'
|
||||
|
||||
import {
|
||||
Button, Control, Heading, Input, Panel, PanelHeading, PanelBlock
|
||||
} from 'bloomer'
|
||||
|
||||
const EMPTY_ARRAY: ReadonlyArray<string> = []
|
||||
|
||||
@ -42,15 +47,21 @@ export class TeamUser extends React.PureComponent<ITeamUserProps> {
|
||||
const {user} = this.props
|
||||
// TODO style
|
||||
return (
|
||||
<div className='team-user'>
|
||||
{user.displayName}
|
||||
<button
|
||||
className='team-user-remove'
|
||||
onClick={this.handleRemoveUser}
|
||||
>
|
||||
Remove
|
||||
</button>
|
||||
</div>
|
||||
<React.Fragment>
|
||||
<div className='user'>
|
||||
{user.displayName}
|
||||
</div>
|
||||
<div className='ml-auto'>
|
||||
<Button
|
||||
aria-label='Remove'
|
||||
isColor='danger'
|
||||
className='team-user-remove'
|
||||
onClick={this.handleRemoveUser}
|
||||
>
|
||||
<FaTimes />
|
||||
</Button>
|
||||
</div>
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -89,13 +100,27 @@ export class AddUser extends React.PureComponent<IAddUserProps, IAddUserState> {
|
||||
render() {
|
||||
return (
|
||||
<form onSubmit={this.handleAddUser}>
|
||||
<input
|
||||
onChange={this.handleChangeEmail}
|
||||
placeholder='Email'
|
||||
type='email'
|
||||
value={this.state.email}
|
||||
/>
|
||||
<input type='submit' value='Add' />
|
||||
<Heading>Add User</Heading>
|
||||
<Control hasIcons='left'>
|
||||
<Input
|
||||
onChange={this.handleChangeEmail}
|
||||
placeholder='Email'
|
||||
type='email'
|
||||
value={this.state.email}
|
||||
/>
|
||||
<span className='icon is-left'>
|
||||
<FaUser />
|
||||
</span>
|
||||
</Control>
|
||||
<div className='mt-1 text-right'>
|
||||
<Button
|
||||
isColor='primary'
|
||||
type='submit'
|
||||
>
|
||||
<FaSave className='mr-1' />
|
||||
Add
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
)
|
||||
}
|
||||
@ -104,8 +129,7 @@ export class AddUser extends React.PureComponent<IAddUserProps, IAddUserState> {
|
||||
export class TeamUserList extends React.PureComponent<ITeamUsersProps> {
|
||||
async componentDidMount() {
|
||||
await this.fetchUsersInTeam(this.props.teamId)
|
||||
}
|
||||
async componentWillReceiveProps(nextProps: ITeamUsersProps) {
|
||||
} async componentWillReceiveProps(nextProps: ITeamUsersProps) {
|
||||
const {teamId} = nextProps
|
||||
if (teamId !== this.props.teamId) {
|
||||
this.fetchUsersInTeam(teamId)
|
||||
@ -121,26 +145,29 @@ export class TeamUserList extends React.PureComponent<ITeamUsersProps> {
|
||||
|| EMPTY_ARRAY
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<div className='team-user-list'>
|
||||
<Panel>
|
||||
<PanelHeading>Users in Team</PanelHeading>
|
||||
{userKeysByTeamId.map(key => {
|
||||
const user = this.props.usersByKey[key]
|
||||
return (
|
||||
<TeamUser
|
||||
key={key}
|
||||
user={user}
|
||||
onRemoveUser={this.props.onRemoveUser}
|
||||
/>
|
||||
<PanelBlock key={key}>
|
||||
<TeamUser
|
||||
key={key}
|
||||
user={user}
|
||||
onRemoveUser={this.props.onRemoveUser}
|
||||
/>
|
||||
</PanelBlock>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
|
||||
<AddUser
|
||||
onAddUser={this.props.onAddUser}
|
||||
onSearchUser={this.props.findUserByEmail}
|
||||
teamId={this.props.teamId}
|
||||
/>
|
||||
</React.Fragment>
|
||||
<PanelBlock isDisplay='block'>
|
||||
<AddUser
|
||||
onAddUser={this.props.onAddUser}
|
||||
onSearchUser={this.props.findUserByEmail}
|
||||
teamId={this.props.teamId}
|
||||
/>
|
||||
</PanelBlock>
|
||||
</Panel>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user