Skip to content

Commit

Permalink
- GitIssue#2742[Team Management 2.0] Inviting already invited user f…
Browse files Browse the repository at this point in the history
…ails without clear error message
  • Loading branch information
RishiRajSahu committed Jan 13, 2019
1 parent 86db357 commit 52a089f
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 41 deletions.
40 changes: 29 additions & 11 deletions src/components/TeamManagement/ProjectManagementDialog.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import Modal from 'react-modal'
import XMarkIcon from '../../assets/icons/icon-x-mark.svg'
import Avatar from 'appirio-tech-react-components/components/Avatar/Avatar'
import { getAvatarResized } from '../../helpers/tcHelpers'
import FormsyForm from 'appirio-tech-react-components/components/Formsy'
const TCFormFields = FormsyForm.Fields

class Dialog extends React.Component {
constructor(props) {
Expand All @@ -14,11 +16,21 @@ class Dialog extends React.Component {
inviteText: '',
validInviteText: false,
clearText: false,
showAlreadyMemberError: false,
invitedMembers: {},
members: {}
}
this.onInviteChange = this.onInviteChange.bind(this)
this.onChange = this.onChange.bind(this)
this.sendInvites = this.sendInvites.bind(this)
}

componentWillMount(){
this.setState({
invitedMembers: this.props.invites,
members: this.props.members
})
}

componentWillReceiveProps(nextProps) {
if (this.state.clearText && nextProps.processingInvites !== this.props.processingInvites &&
!nextProps.processingInvites) {
Expand All @@ -30,16 +42,19 @@ class Dialog extends React.Component {
}
}

onInviteChange(evt) {
const text = evt.target.value
onChange(currentValues) {
const text = currentValues.emails
const invites = text.split(/[,;]/g)
const isValid = invites.every(invite => {
invite = invite.trim()
return invite.length > 1 && (/(.+)@(.+){2,}\.(.+){2,}/.test(invite) || invite.startsWith('@'))
})
let present = _.some(this.state.invitedMembers, invited => invites.indexOf(invited.email) > -1)
present = present || _.some(this.state.members, member => invites.indexOf(member.email) > -1)
this.setState({
validInviteText: isValid && text.trim().length > 0,
inviteText: evt.target.value
validInviteText: !present && isValid && text.trim().length > 0,
inviteText: currentValues.emails,
showAlreadyMemberError: present
})
}

Expand Down Expand Up @@ -148,24 +163,27 @@ class Dialog extends React.Component {
}))}
</div>

<div className="input-container">
<Formsy.Form className="input-container" onValidSubmit={this.sendInvites} onChange={this.onChange} >
<div className="hint">invite more people</div>
<input
<TCFormFields.TextInput
name="emails"
wrapperClass="inviteTextInput"
type="text"
value={this.state.inviteText}
onInput={this.onInviteChange}
placeholder="Enter one or more emails separated by ';' or comma ','"
className="tc-file-field__inputs"
disabled={!isMember || this.state.clearText}
/>
{ this.state.showAlreadyMemberError && <div className="error-message">
Project Member(s) can't be invited again. Please remove them from list.
</div> }
<button
className="tc-btn tc-btn-primary tc-btn-md"
onClick={this.sendInvites}
type="submit"
disabled={!this.state.validInviteText || this.state.clearText}
>
Send Invite
</button>
</div>
</Formsy.Form>
</div>

</Modal>
Expand Down
10 changes: 10 additions & 0 deletions src/components/TeamManagement/TeamManagement.scss
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,16 @@
text-transform: uppercase;
}

.inviteTextInput {
@include roboto-medium;
margin-top: $base-unit*2;
width: 100%;
text-align: center;
font-size: $tc-label-xs;
color: $tc-gray-50;
text-transform: uppercase;
}

input {
width: stretch;
margin: $base-unit*4 $base-unit*2;
Expand Down
70 changes: 40 additions & 30 deletions src/components/TeamManagement/TopcoderManagementDialog.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import XMarkIcon from '../../assets/icons/icon-x-mark.svg'
import Avatar from 'appirio-tech-react-components/components/Avatar/Avatar'
import { getAvatarResized } from '../../helpers/tcHelpers'
import Dropdown from 'appirio-tech-react-components/components/Dropdown/Dropdown'


import FormsyForm from 'appirio-tech-react-components/components/Formsy'
const TCFormFields = FormsyForm.Fields


class Dialog extends React.Component {
Expand All @@ -21,12 +21,14 @@ class Dialog extends React.Component {
validUserText: false,
managerType: {},
clearText: false,
members: {},
showAlreadyMemberError: false
}

this.onUserRoleChange = this.onUserRoleChange.bind(this)
this.onInviteChange = this.onInviteChange.bind(this)
this.handleRoles = this.handleRoles.bind(this)
this.addUsers = this.addUsers.bind(this)
this.onChange = this.onChange.bind(this)
}

componentWillMount(){
Expand All @@ -40,16 +42,19 @@ class Dialog extends React.Component {
title: 'Copilot',
value: 'copilot',
}]
this.setState({
members: this.props.members
})
}


componentWillReceiveProps(nextProps) {
if (this.state.clearText && nextProps.processingInvites !== this.props.processingInvites &&
!nextProps.processingInvites) {
this.setState({
userText: '',
validUserText: false,
clearText: false,
members: this.props.members
})
}
}
Expand All @@ -61,22 +66,6 @@ class Dialog extends React.Component {
this.setState({managerType})
}

onInviteChange(evt) {
const text = evt.target.value
const users = text.split(/[,;]/g)
const isInvalid = users.some(user => {
user = user.trim()
if (user === '') {
return false
}
return !(user.startsWith('@') && user.length > 1)
})
this.setState({
validUserText: !isInvalid && text.trim().length > 0,
userText: evt.target.value
})
}

handleRoles(value) {
this.setState({
userRole: value
Expand All @@ -96,6 +85,27 @@ class Dialog extends React.Component {
this.setState({clearText: true})
}

onChange(currentValues) {
const text = currentValues.handlesText
let handles = text.split(/[,;]/g)
const isInvalid = handles.some(user => {
user = user.trim()
if (user === '') {
return false
}
return !(user.startsWith('@') && user.length > 1)
})
const validText = !isInvalid && text.trim().length > 0
handles = handles.filter((handle) => (handle.trim().startsWith('@') && handle.length > 1))
handles = handles.map(handle => handle.trim().replace(/^@/, ''))
const present = _.some(this.state.members, m => handles.indexOf(m.handle) > -1)
this.setState({
validUserText: !present && validText,
showAlreadyMemberError: present,
userText: text
})
}

render() {
const {members, currentUser, isMember, removeMember, onCancel, removeInvite, invites = []} = this.props
const showRemove = currentUser.isAdmin || (isMember && currentUser.isManager)
Expand Down Expand Up @@ -221,17 +231,19 @@ class Dialog extends React.Component {
}))}
</div>

{showRemove && <div className="input-container">
{showRemove && <Formsy.Form className="input-container" onValidSubmit={this.addUsers} onChange={this.onChange} >
<div className="hint">invite more people</div>
<input
<TCFormFields.TextInput
name="handlesText"
wrapperClass="inviteTextInput"
type="text"
value={this.state.userText}
onInput={this.onInviteChange}
placeholder="Enter one or more user @handles separated by ';' or comma ','"
className="tc-file-field__inputs"
disabled={!isMember || this.state.clearText}
/>

{ this.state.showAlreadyMemberError && <div className="error-message">
Project Member(s) can't be invited again. Please remove them from list.
</div> }
<Dropdown className="role-drop-down default">
<div className="dropdown-menu-header">
{(() => {
Expand All @@ -254,17 +266,15 @@ class Dialog extends React.Component {
</ul>
</div>
</Dropdown>


<button
className="tc-btn tc-btn-primary tc-btn-md"
onClick={this.addUsers}
type="submit"
disabled={!this.state.validUserText || this.state.clearText}
>
Send Invite
</button>
</div>}

</Formsy.Form>
}
{!showRemove && <div className="dialog-placeholder" />}
</div>
</Modal>
Expand Down

0 comments on commit 52a089f

Please sign in to comment.