Use Route in TeamManager.tsx

This commit is contained in:
Jerko Steiner 2019-03-25 17:19:09 +08:00
parent 7b063c5a09
commit fbeea5ad3e
5 changed files with 164 additions and 162 deletions

View File

@ -4,7 +4,6 @@ import {ITeamState} from './TeamReducer'
import {TeamActions} from './TeamActions'
import {TeamManager} from './TeamManager'
import {bindActionCreators} from 'redux'
import {withRouter} from 'react-router-dom'
export class TeamConnector extends Connector<ITeamState> {
constructor(protected readonly teamActions: TeamActions) {
@ -32,6 +31,6 @@ export class TeamConnector extends Connector<ITeamState> {
TeamManager,
)
return withRouter(Component)
return Component
}
}

View File

@ -0,0 +1,88 @@
import React from 'react'
import {Button, Control, Heading, Input} from 'bloomer'
import {ITeam} from '@rondo/common'
import {TeamActions} from './TeamActions'
import {FaPlusSquare, FaCheck, FaEdit} from 'react-icons/fa'
export type ITeamEditorProps = {
type: 'add'
onAddTeam: TeamActions['createTeam']
} | {
type: 'update'
onUpdateTeam: TeamActions['updateTeam']
team: ITeam
}
export interface ITeamEditorState {
name: string
}
export class TeamEditor
extends React.PureComponent<ITeamEditorProps, ITeamEditorState> {
constructor(props: ITeamEditorProps) {
super(props)
this.state = {
name: props.type === 'update' ? this.getName(props.team) : '',
}
}
getName(team?: ITeam) {
return team ? team.name : ''
}
componentWillReceiveProps(nextProps: ITeamEditorProps) {
if (nextProps.type === 'update') {
const {team} = nextProps
if (team !== (this.props as any).team) {
this.setState({
name: this.getName(team),
})
}
}
}
handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const name = event.target.value
this.setState({name})
}
handleSubmit = async (event: React.FormEvent) => {
event.preventDefault()
const {name} = this.state
if (this.props.type === 'update') {
const {team} = this.props
await this.props.onUpdateTeam({id: team.id, name})
} else {
await this.props.onAddTeam({name})
}
this.setState({name: ''})
}
render() {
return (
<form
autoComplete='off'
className='team-add'
onSubmit={this.handleSubmit}>
<Heading>
{this.props.type === 'update' ? 'Edit team' : 'Add team'}
</Heading>
<Control hasIcons='left'>
<Input
placeholder='Team Name'
type='text'
value={this.state.name}
onChange={this.handleChange}
/>
<span className='icon is-left'>
{this.props.type === 'update' ? <FaEdit /> : <FaPlusSquare />}
</span>
</Control>
<div className='text-right mt-1'>
<Button
isColor='dark'
className='button'
type='submit'
>
<FaCheck className='mr-1' /> Save
</Button>
</div>
</form>
)
}
}

View File

@ -1,12 +1,10 @@
import React from 'react'
import {Button, Panel, PanelHeading, PanelBlock} from 'bloomer'
import {FaEdit, FaTimes} from 'react-icons/fa'
import {ITeam, ReadonlyRecord} from '@rondo/common'
import {Link} from 'react-router-dom'
import {TeamActions} from './TeamActions'
import {FaPlusSquare, FaCheck, FaEdit, FaTimes} from 'react-icons/fa'
import {
Button, Control, Heading, Input, Panel, PanelHeading, PanelBlock
} from 'bloomer'
import {TeamEditor} from './TeamEditor'
export interface ITeamListProps {
teamsById: ReadonlyRecord<number, ITeam>,
@ -14,93 +12,14 @@ export interface ITeamListProps {
onAddTeam: TeamActions['createTeam']
onRemoveTeam: TeamActions['removeTeam']
onUpdateTeam: TeamActions['updateTeam']
editTeamId?: number
}
export interface ITeamProps {
team: ITeam
editTeamId?: number
onRemoveTeam: TeamActions['removeTeam']
onUpdateTeam: TeamActions['updateTeam']
}
export interface IAddTeamProps {
onAddTeam: TeamActions['createTeam']
onUpdateTeam: TeamActions['updateTeam']
team?: ITeam
}
export interface IAddTeamState {
name: string
}
export class TeamAdd extends React.PureComponent<IAddTeamProps, IAddTeamState> {
constructor(props: IAddTeamProps) {
super(props)
this.state = {
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>) => {
const name = event.target.value
this.setState({name})
}
handleSubmit = async (event: React.FormEvent) => {
event.preventDefault()
const {team, onAddTeam, onUpdateTeam} = this.props
const {name} = this.state
if (team) {
await onUpdateTeam({id: team.id, name})
} else {
await onAddTeam({name})
}
this.setState({name: ''})
}
render() {
return (
<form
autoComplete='off'
className='team-add'
onSubmit={this.handleSubmit}>
<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'>
{this.props.team ? <FaEdit /> : <FaPlusSquare />}
</span>
</Control>
<div className='text-right mt-1'>
<Button
isColor='dark'
className='button'
type='submit'
>
<FaCheck className='mr-1' /> Save
</Button>
</div>
</form>
)
}
}
export class TeamRow extends React.PureComponent<ITeamProps> {
handleRemove = async () => {
const {onRemoveTeam, team: {id}} = this.props
@ -115,7 +34,7 @@ export class TeamRow extends React.PureComponent<ITeamProps> {
</div>
<div className='ml-auto'>
<Link to={`/teams/${team.id}/users`}>
<Button aria-label='Edit'>
<Button isInverted isColor='link' aria-label='Edit'>
<FaEdit />
</Button>
</Link>
@ -124,6 +43,7 @@ export class TeamRow extends React.PureComponent<ITeamProps> {
aria-label='Remove'
onClick={this.handleRemove}
isColor='danger'
isInverted
>
<FaTimes />
</Button>
@ -135,19 +55,16 @@ export class TeamRow extends React.PureComponent<ITeamProps> {
export class TeamList extends React.PureComponent<ITeamListProps> {
render() {
const {editTeamId, teamIds, teamsById} = this.props
const {teamIds, teamsById} = this.props
return (
<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}
@ -157,23 +74,11 @@ export class TeamList extends React.PureComponent<ITeamListProps> {
})}
<PanelBlock isDisplay='block'>
<TeamAdd
<TeamEditor
type='add'
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}
/>
</PanelBlock>
)}
</Panel>
)
}

View File

@ -1,19 +1,13 @@
import React from 'react'
import {History, Location} from 'history'
import {ITeam, IUserInTeam, ReadonlyRecord} from '@rondo/common'
import {Route, Switch} from 'react-router-dom'
import {TeamActions} from './TeamActions'
import {TeamEditor} from './TeamEditor'
import {TeamList} from './TeamList'
import {TeamUserList} from './TeamUserList'
import {Title} from 'bloomer'
import {match} from 'react-router'
import {Panel, PanelBlock, PanelHeading} from 'bloomer'
export interface ITeamManagerProps {
history: History
location: Location
match: match<{
teamId: string | undefined
}>
createTeam: TeamActions['createTeam']
updateTeam: TeamActions['updateTeam']
removeTeam: TeamActions['removeTeam']
@ -36,34 +30,50 @@ export class TeamManager extends React.PureComponent<ITeamManagerProps> {
await this.props.fetchMyTeams()
}
render() {
const {teamId} = this.props.match.params
const editTeamId = teamId ? Number(teamId) : undefined
const {teamsById} = this.props
return (
<div className='team-manager'>
<Title>Teams</Title>
<Switch>
<Route exact path='/teams' render={() =>
<TeamList
editTeamId={editTeamId}
teamsById={this.props.teamsById}
teamsById={teamsById}
teamIds={this.props.teamIds}
onAddTeam={this.props.createTeam}
onRemoveTeam={this.props.removeTeam}
onUpdateTeam={this.props.updateTeam}
/>
{editTeamId && <TeamUserList
}/>
<Route exact path='/teams/:teamId/users' render={({match}) => {
const {teamId: teamIdParam} = match.params
const teamId = teamIdParam ? Number(teamIdParam) : undefined
const team = teamId ? teamsById[teamId] : undefined
return (
<React.Fragment>
<Panel>
<PanelHeading>Edit Team: {team && team.name}</PanelHeading>
<PanelBlock isDisplay='block'>
{team && <TeamEditor
type='update'
team={team}
onUpdateTeam={this.props.updateTeam}
/>}
{!team && 'No team loaded'}
</PanelBlock>
</Panel>
{team && <TeamUserList
onAddUser={this.props.addUser}
onRemoveUser={this.props.removeUser}
findUserByEmail={this.props.findUserByEmail}
fetchUsersInTeam={this.props.fetchUsersInTeam}
teamId={editTeamId}
team={team}
userKeysByTeamId={this.props.userKeysByTeamId}
usersByKey={this.props.usersByKey}
/>}
</React.Fragment>
)
}}/>
</Switch>
</div>
)
}

View File

@ -1,5 +1,5 @@
import React from 'react'
import {IUser, IUserInTeam, ReadonlyRecord} from '@rondo/common'
import {ITeam, IUser, IUserInTeam, ReadonlyRecord} from '@rondo/common'
import {TeamActions} from './TeamActions'
import {FaUser, FaCheck, FaTimes} from 'react-icons/fa'
@ -17,7 +17,7 @@ export interface ITeamUsersProps {
onAddUser: TeamActions['addUser']
onRemoveUser: TeamActions['removeUser']
teamId: number
team: ITeam
userKeysByTeamId: ReadonlyRecord<number, ReadonlyArray<string>>
usersByKey: ReadonlyRecord<string, IUserInTeam>
}
@ -136,11 +136,11 @@ export class AddUser extends React.PureComponent<IAddUserProps, IAddUserState> {
export class TeamUserList extends React.PureComponent<ITeamUsersProps> {
async componentDidMount() {
await this.fetchUsersInTeam(this.props.teamId)
await this.fetchUsersInTeam(this.props.team.id)
} async componentWillReceiveProps(nextProps: ITeamUsersProps) {
const {teamId} = nextProps
if (teamId !== this.props.teamId) {
this.fetchUsersInTeam(teamId)
const {team} = nextProps
if (team.id !== this.props.team.id) {
this.fetchUsersInTeam(team.id)
}
}
async fetchUsersInTeam(teamId: number) {
@ -149,7 +149,7 @@ export class TeamUserList extends React.PureComponent<ITeamUsersProps> {
}
}
render() {
const userKeysByTeamId = this.props.userKeysByTeamId[this.props.teamId]
const userKeysByTeamId = this.props.userKeysByTeamId[this.props.team.id]
|| EMPTY_ARRAY
return (
@ -172,7 +172,7 @@ export class TeamUserList extends React.PureComponent<ITeamUsersProps> {
<AddUser
onAddUser={this.props.onAddUser}
onSearchUser={this.props.findUserByEmail}
teamId={this.props.teamId}
teamId={this.props.team.id}
/>
</PanelBlock>
</Panel>