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