diff --git a/src/api/projectMembers.js b/src/api/projectMembers.js index 6e6bdbfa3..90501f311 100644 --- a/src/api/projectMembers.js +++ b/src/api/projectMembers.js @@ -49,7 +49,7 @@ export function addProjectMember(projectId, newMember) { export function updateProjectMember(projectId, memberId, updatedProps) { - const fields = 'id,userId,role,isPrimary,deletedAt,createdAt,updatedAt,deletedBy,createdBy,updatedBy,handle,photoURL,workingHourStart,workingHourEnd,timeZone' + const fields = 'id,userId,role,isPrimary,deletedAt,createdAt,updatedAt,deletedBy,createdBy,updatedBy,handle,photoURL,workingHourStart,workingHourEnd,timeZone,email' const url = `${PROJECTS_API_URL}/v5/projects/${projectId}/members/${memberId}/?fields=` + encodeURIComponent(fields) return axios.patch(url, updatedProps) @@ -68,7 +68,7 @@ export function removeProjectMember(projectId, memberId) { } export function getProjectMembers(projectId) { - const fields = 'id,userId,role,isPrimary,deletedAt,createdAt,updatedAt,deletedBy,createdBy,updatedBy,handle,photoURL,workingHourStart,workingHourEnd,timeZone' + const fields = 'id,userId,role,isPrimary,deletedAt,createdAt,updatedAt,deletedBy,createdBy,updatedBy,handle,photoURL,workingHourStart,workingHourEnd,timeZone,email' const url = `${PROJECTS_API_URL}/v5/projects/${projectId}/members/?fields=` + encodeURIComponent(fields) return axios.get(url) @@ -78,7 +78,7 @@ export function getProjectMembers(projectId) { } export function getProjectMember(projectId, memberId) { - const fields = 'id,userId,role,isPrimary,deletedAt,createdAt,updatedAt,deletedBy,createdBy,updatedBy,handle,photoURL,workingHourStart,workingHourEnd,timeZone' + const fields = 'id,userId,role,isPrimary,deletedAt,createdAt,updatedAt,deletedBy,createdBy,updatedBy,handle,photoURL,workingHourStart,workingHourEnd,timeZone,email' const url = `${PROJECTS_API_URL}/v5/projects/${projectId}/members/${memberId}?fields=` + encodeURIComponent(fields) return axios.get(url) diff --git a/src/components/TeamManagement/Dialog.js b/src/components/TeamManagement/Dialog.js index 9f59364d0..809da1c1f 100644 --- a/src/components/TeamManagement/Dialog.js +++ b/src/components/TeamManagement/Dialog.js @@ -63,9 +63,8 @@ class Dialog extends React.Component { isOpen className="management-dialog" overlayClassName="management-dialog-overlay" - onRequestClose={onCancel} - shouldCloseOnOverlayClick={!isLoading} - shouldCloseOnEsc={!isLoading} + shouldCloseOnOverlayClick={false} + shouldCloseOnEsc={false} contentLabel="" >
diff --git a/src/components/User/UserTooltip.jsx b/src/components/User/UserTooltip.jsx index 7030feb20..28696d139 100644 --- a/src/components/User/UserTooltip.jsx +++ b/src/components/User/UserTooltip.jsx @@ -1,6 +1,7 @@ import _ from 'lodash' import React from 'react' import PropTypes from 'prop-types' +import cn from 'classnames' import Tooltip from 'appirio-tech-react-components/components/Tooltip/Tooltip' import Avatar from 'appirio-tech-react-components/components/Avatar/Avatar' import { DOMAIN } from '../../config/constants' @@ -53,7 +54,7 @@ const UserTooltip = ({ usr, id, previewAvatar, size, invitedLabel, showEmailOnly )}
-
+
{!showEmailOnly &&
{userFullName}
} diff --git a/src/components/User/UserTooltip.scss b/src/components/User/UserTooltip.scss index 2d067e669..770d84f6f 100644 --- a/src/components/User/UserTooltip.scss +++ b/src/components/User/UserTooltip.scss @@ -127,12 +127,14 @@ display: flex; flex-wrap: wrap; align-content: flex-start; - position: relative; - width: 80%; + overflow: hidden; } .user-name-container { - flex: 1 0 90%; + flex: 1 1 100%; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; span { font-size: 15px; @@ -143,8 +145,10 @@ } .user-handle-container { - padding-right: 10px; height: 20px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; &.with-email { border-right: 1px solid $tc-gray-50; @@ -163,7 +167,6 @@ overflow: hidden; text-overflow: ellipsis; white-space: nowrap; - max-width: 80%; a { font-size: 12px; @@ -186,6 +189,11 @@ } } } + + .tt-col-user-data.with-invite-label .user-name-container, + .tt-col-user-data.with-invite-label .user-email-container.text-dark { + margin-right: 75px; + } } .sf-data-bottom-container { diff --git a/src/config/permissions.js b/src/config/permissions.js index 5ecd6cb72..cf5c0ff54 100644 --- a/src/config/permissions.js +++ b/src/config/permissions.js @@ -114,6 +114,7 @@ const TOPCODER_ALL = [ ROLE_ADMINISTRATOR, ROLE_CONNECT_ADMIN, ROLE_CONNECT_MANAGER, + ROLE_CONNECT_COPILOT_MANAGER, ROLE_CONNECT_ACCOUNT_MANAGER, ROLE_BUSINESS_DEVELOPMENT_REPRESENTATIVE, ROLE_PRESALES, diff --git a/src/projects/detail/components/TalentPickerQuestion/TalentPickerQuestion.jsx b/src/projects/detail/components/TalentPickerQuestion/TalentPickerQuestion.jsx index 610ecdb49..b6a25e5ee 100644 --- a/src/projects/detail/components/TalentPickerQuestion/TalentPickerQuestion.jsx +++ b/src/projects/detail/components/TalentPickerQuestion/TalentPickerQuestion.jsx @@ -48,6 +48,16 @@ class TalentPickerQuestion extends Component { return v.people !== '0' && v.duration !== '0' && v.skills.length > 0 }) // validation body }, + noPartialFillsExist: (formValues, value) => { + return _.every(value, v => { + const isOneValueFilled = v.people > 0 || v.duration > 0 || (v.skills && v.skills.length) + const isAllValuesFilled = v.people > 0 && v.duration > 0 && v.skills && v.skills.length + + // If one value is filled, all values should be filled to make this row valid. Partial fill is not valid + const isRowValid = !isOneValueFilled || isAllValuesFilled + return isRowValid + }) + } } setValidations(validations) } diff --git a/src/projects/detail/components/TalentPickerRow/TalentPickerRow.jsx b/src/projects/detail/components/TalentPickerRow/TalentPickerRow.jsx index de8ac2dfe..d6ab115be 100644 --- a/src/projects/detail/components/TalentPickerRow/TalentPickerRow.jsx +++ b/src/projects/detail/components/TalentPickerRow/TalentPickerRow.jsx @@ -1,5 +1,6 @@ import React from 'react' import PT from 'prop-types' +import cn from 'classnames' import IconX from '../../../../assets/icons/ui-16px-1_bold-remove.svg' import IconAdd from '../../../../assets/icons/ui-16px-1_bold-add.svg' @@ -21,6 +22,9 @@ class TalentPickerRow extends React.PureComponent { this.handleDurationChange = this.handleDurationChange.bind(this) this.handleSkillChange = this.handleSkillChange.bind(this) + this.resetPeople = this.resetPeople.bind(this) + this.resetDuration = this.resetDuration.bind(this) + this.onAddRow = this.onAddRow.bind(this) this.onDeleteRow = this.onDeleteRow.bind(this) } @@ -37,6 +41,20 @@ class TalentPickerRow extends React.PureComponent { this.props.onChange(this.props.rowIndex, 'skills', value) } + resetDuration() { + const { rowIndex, onChange, value } = this.props + if (!value.duration) { + onChange(rowIndex, 'duration', '0') + } + } + + resetPeople() { + const { rowIndex, onChange, value } = this.props + if (!value.people) { + onChange(rowIndex, 'people', '0') + } + } + onAddRow() { const { rowIndex, value, onAddRow: addRowHandler } = this.props addRowHandler(rowIndex + 1, value.role) @@ -49,6 +67,7 @@ class TalentPickerRow extends React.PureComponent { render() { const { value, canBeDeleted, roleSetting, rowIndex } = this.props + const isRowIncomplete = value.people > 0 || value.duration > 0 || (value.skills && value.skills.length) /* Different columns are defined here and used in componsing mobile/desktop views below */ const roleColumn = ( @@ -83,9 +102,10 @@ class TalentPickerRow extends React.PureComponent {
) @@ -98,9 +118,10 @@ class TalentPickerRow extends React.PureComponent {
) @@ -126,7 +147,7 @@ class TalentPickerRow extends React.PureComponent { setValue={this.handleSkillChange} getValue={() => value.skills} onChange={_.noop} - selectWrapperClass={styles.noMargin} + selectWrapperClass={cn(styles.noMargin, {[styles.skillHasError]: isRowIncomplete && !(value.skills && value.skills.length)})} /> ) diff --git a/src/projects/detail/components/TalentPickerRow/TalentPickerRow.scss b/src/projects/detail/components/TalentPickerRow/TalentPickerRow.scss index a9d868114..dc8d08899 100644 --- a/src/projects/detail/components/TalentPickerRow/TalentPickerRow.scss +++ b/src/projects/detail/components/TalentPickerRow/TalentPickerRow.scss @@ -110,3 +110,12 @@ overflow: hidden; text-overflow: ellipsis; } + + +.skillHasError { + :global { + .react-select__control { + border-color: $tc-red-70; + } + } +}