packages/client: Style TeamManager, fix error on delete
This commit is contained in:
parent
3f96a128a0
commit
c83fa2d6d4
@ -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'>
|
||||||
|
|||||||
@ -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>
|
||||||
|
|||||||
@ -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'>
|
||||||
|
|||||||
@ -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':
|
||||||
|
|||||||
@ -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>
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user