packages/client: Style TeamManager, fix error on delete

This commit is contained in:
Jerko Steiner 2019-03-25 13:28:07 +08:00
parent 3f96a128a0
commit c83fa2d6d4
6 changed files with 46 additions and 20 deletions

View File

@ -16,7 +16,7 @@ export type TeamActionType =
'TEAM_UPDATE_PENDING', 'TEAM_UPDATE_PENDING',
'TEAM_UPDATE_RESOLVED', 'TEAM_UPDATE_RESOLVED',
'TEAM_UPDATE_REJECTED'> 'TEAM_UPDATE_REJECTED'>
| IAsyncAction<{}, | IAsyncAction<{id: number},
'TEAM_REMOVE_PENDING', 'TEAM_REMOVE_PENDING',
'TEAM_REMOVE_RESOLVED', 'TEAM_REMOVE_RESOLVED',
'TEAM_REMOVE_REJECTED'> 'TEAM_REMOVE_REJECTED'>

View File

@ -2,7 +2,7 @@ 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 {FaPlusSquare, FaCheck, FaEdit, FaTimes} from 'react-icons/fa'
import { import {
Button, Control, Heading, Input, Panel, PanelHeading, PanelBlock Button, Control, Heading, Input, Panel, PanelHeading, PanelBlock
@ -65,10 +65,14 @@ export class TeamAdd extends React.PureComponent<IAddTeamProps, IAddTeamState> {
} else { } else {
await onAddTeam({name}) await onAddTeam({name})
} }
this.setState({name: ''})
} }
render() { render() {
return ( return (
<form className='team-add' onSubmit={this.handleSubmit}> <form
autoComplete='off'
className='team-add'
onSubmit={this.handleSubmit}>
<Heading> <Heading>
{this.props.team ? 'Edit team' : 'Add team'} {this.props.team ? 'Edit team' : 'Add team'}
</Heading> </Heading>
@ -80,15 +84,16 @@ export class TeamAdd extends React.PureComponent<IAddTeamProps, IAddTeamState> {
onChange={this.handleChange} onChange={this.handleChange}
/> />
<span className='icon is-left'> <span className='icon is-left'>
<FaPlusSquare /> {this.props.team ? <FaEdit /> : <FaPlusSquare />}
</span> </span>
</Control> </Control>
<div className='text-right mt-1'> <div className='text-right mt-1'>
<Button <Button
className='button is-primary' isColor='dark'
className='button'
type='submit' type='submit'
> >
<FaSave className='mr-1' /> Save <FaCheck className='mr-1' /> Save
</Button> </Button>
</div> </div>
</form> </form>

View File

@ -36,10 +36,8 @@ export class TeamManager extends React.PureComponent<ITeamManagerProps> {
await this.props.fetchMyTeams() await this.props.fetchMyTeams()
} }
render() { render() {
// TypeOrm changes BigInt fields to Strings because they can be tool const {teamId} = this.props.match.params
// large... const editTeamId = teamId ? Number(teamId) : undefined
const editTeamId = this.props.match.params.teamId as any as
number | undefined
return ( return (
<div className='team-manager'> <div className='team-manager'>

View File

@ -1,4 +1,6 @@
import {ITeam, IUserInTeam, ReadonlyRecord, indexBy} from '@rondo/common' import {
ITeam, IUserInTeam, ReadonlyRecord, indexBy, without,
} from '@rondo/common'
import {TeamActionType} from './TeamActions' import {TeamActionType} from './TeamActions'
import {GetAction} from '../actions' import {GetAction} from '../actions'
@ -70,7 +72,6 @@ export function Team(state = defaultState, action: TeamActionType): ITeamState {
[action.payload.id]: action.payload, [action.payload.id]: action.payload,
}, },
} }
return state
case 'TEAM_USER_ADD_RESOLVED': case 'TEAM_USER_ADD_RESOLVED':
return { return {
...state, ...state,
@ -107,6 +108,12 @@ export function Team(state = defaultState, action: TeamActionType): ITeamState {
...usersByKey, ...usersByKey,
}, },
} }
case 'TEAM_REMOVE_RESOLVED':
return {
...state,
teamIds: state.teamIds.filter(id => id !== action.payload.id),
teamsById: without(state.teamsById, action.payload.id),
}
case 'TEAM_CREATE_REJECTED': case 'TEAM_CREATE_REJECTED':
case 'TEAM_UPDATE_REJECTED': case 'TEAM_UPDATE_REJECTED':
case 'TEAM_USER_ADD_REJECTED': case 'TEAM_USER_ADD_REJECTED':

View File

@ -1,10 +1,10 @@
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 {FaUser, FaCheck, FaTimes} from 'react-icons/fa'
import { import {
Button, Control, Heading, Input, Panel, PanelHeading, PanelBlock Button, Control, Heading, Help, Input, Panel, PanelHeading, PanelBlock
} from 'bloomer' } from 'bloomer'
const EMPTY_ARRAY: ReadonlyArray<string> = [] const EMPTY_ARRAY: ReadonlyArray<string> = []
@ -34,6 +34,7 @@ export interface IAddUserProps {
} }
export interface IAddUserState { export interface IAddUserState {
error: string
email: string email: string
user?: IUser user?: IUser
} }
@ -55,6 +56,7 @@ export class TeamUser extends React.PureComponent<ITeamUserProps> {
<Button <Button
aria-label='Remove' aria-label='Remove'
isColor='danger' isColor='danger'
isInverted
className='team-user-remove' className='team-user-remove'
onClick={this.handleRemoveUser} onClick={this.handleRemoveUser}
> >
@ -70,6 +72,7 @@ export class AddUser extends React.PureComponent<IAddUserProps, IAddUserState> {
constructor(props: IAddUserProps) { constructor(props: IAddUserProps) {
super(props) super(props)
this.state = { this.state = {
error: '',
email: '', email: '',
user: undefined, user: undefined,
} }
@ -85,6 +88,7 @@ export class AddUser extends React.PureComponent<IAddUserProps, IAddUserState> {
const user = await this.props.onSearchUser(email).payload const user = await this.props.onSearchUser(email).payload
if (!user) { if (!user) {
// TODO handle this better via 404 status code // TODO handle this better via 404 status code
this.setState({error: 'No user found'})
return return
} }
await this.props.onAddUser({ await this.props.onAddUser({
@ -93,16 +97,17 @@ export class AddUser extends React.PureComponent<IAddUserProps, IAddUserState> {
roleId: 1, roleId: 1,
}) })
this.setState({email: '', user: undefined}) this.setState({error: '', email: '', user: undefined})
// TODO handle failures
} }
render() { render() {
const {error} = this.state
return ( return (
<form onSubmit={this.handleAddUser}> <form autoComplete='off' onSubmit={this.handleAddUser}>
<Heading>Add User</Heading> <Heading>Add User</Heading>
<Control hasIcons='left'> <Control hasIcons='left'>
<Input <Input
isColor={error ? 'danger' : ''}
onChange={this.handleChangeEmail} onChange={this.handleChangeEmail}
placeholder='Email' placeholder='Email'
type='email' type='email'
@ -111,13 +116,16 @@ export class AddUser extends React.PureComponent<IAddUserProps, IAddUserState> {
<span className='icon is-left'> <span className='icon is-left'>
<FaUser /> <FaUser />
</span> </span>
{error && (
<Help isColor='danger'>{error}</Help>
)}
</Control> </Control>
<div className='mt-1 text-right'> <div className='mt-1 text-right'>
<Button <Button
isColor='primary' isColor='dark'
type='submit' type='submit'
> >
<FaSave className='mr-1' /> <FaCheck className='mr-1' />
Add Add
</Button> </Button>
</div> </div>

View File

@ -4,11 +4,19 @@ import {IUserInTeam} from '@rondo/common'
import {IUserTeamParams} from './IUserTeamParams' import {IUserTeamParams} from './IUserTeamParams'
import {Team} from '../entities/Team' import {Team} from '../entities/Team'
import {UserTeam} from '../entities/UserTeam' import {UserTeam} from '../entities/UserTeam'
import {Validator, trim} from '../validator'
export class TeamService extends BaseService implements ITeamService { export class TeamService extends BaseService implements ITeamService {
// TODO check team limit per user // TODO check team limit per user
async create({name, userId}: {name: string, userId: number}) { async create({name, userId}: {name: string, userId: number}) {
name = trim(name)
new Validator({name, userId})
.ensure('name')
.ensure('userId')
.throw()
const team = await this.getRepository(Team).save({ const team = await this.getRepository(Team).save({
name, name,
userId, userId,