Style team manager

This commit is contained in:
Jerko Steiner 2019-03-23 22:50:44 +08:00
parent 77838e8e0c
commit 3bcf9d646e
4 changed files with 165 additions and 84 deletions

View File

@ -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>
&nbsp;
<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>
)
}
}

View File

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

View File

@ -119,5 +119,4 @@ export function Team(state = defaultState, action: TeamActionType): ITeamState {
default:
return state
}
return state
}

View File

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