Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 9 additions & 5 deletions src/components/ProjectInfo/ProjectInfo.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import ProjectDirectLinks from '../../projects/list/components/Projects/ProjectD
import MobileExpandable from '../MobileExpandable/MobileExpandable'
import ProjectProgress from '../../projects/detail/components/ProjectProgress'
import MediaQuery from 'react-responsive'
import { SCREEN_BREAKPOINT_MD, PHASE_STATUS_ACTIVE, PROJECT_ROLE_OWNER, PROJECT_ROLE_CUSTOMER } from '../../config/constants'
import { SCREEN_BREAKPOINT_MD, PROJECT_STATUS_ACTIVE, PHASE_STATUS_ACTIVE, PHASE_STATUS_REVIEWED, PROJECT_ROLE_OWNER, PROJECT_ROLE_CUSTOMER } from '../../config/constants'
import ReviewProjectButton from '../../projects/detail/components/ReviewProjectButton'

import { formatProjectProgressProps, formatOldProjectProgressProps } from '../../helpers/projectHelper'
Expand Down Expand Up @@ -52,6 +52,9 @@ class ProjectInfo extends Component {
)

const activePhases = phases ? phases.filter((phase) => phase.status === PHASE_STATUS_ACTIVE) : []
const hasReviewedOrActivePhases = !!_.find(phases, (phase) => _.includes([PHASE_STATUS_REVIEWED, PHASE_STATUS_ACTIVE], phase.status))
const projectCanBeActive = (project.status !== PROJECT_STATUS_ACTIVE && hasReviewedOrActivePhases) || project.status === PROJECT_STATUS_ACTIVE


// prepare review button
const showReviewBtn = project.status === 'draft' &&
Expand All @@ -60,10 +63,10 @@ class ProjectInfo extends Component {
const reviewButtonSection = (
<div className="project-info-review">
<p>
Your project "{_.unescape(project.name)}" has been drafted.
If you have your requirements documented, just verify it against our checklist and then upload it on the <Link to={`/projects/${project.id}/scope`}>Scope</Link> section.
Once you've finalized your scope, select the "Submit for Review" button.
Topcoder will then review your drafted project and will assign a manager to get your delivery in-progress!
Your project "{_.unescape(project.name)}" has been drafted.
If you have your requirements documented, just verify it against our checklist and then upload it on the <Link to={`/projects/${project.id}/scope`}>Scope</Link> section.
Once you've finalized your scope, select the "Submit for Review" button.
Topcoder will then review your drafted project and will assign a manager to get your delivery in-progress!
Get stuck or need help? Email us at <a href="mailto:support@topcoder.com">support@topcoder.com</a>.
</p>
<ReviewProjectButton project={project} onClick={onSubmitForReview} disabled={isProjectProcessing} />
Expand Down Expand Up @@ -108,6 +111,7 @@ class ProjectInfo extends Component {
{(matches) => (
<ProjectCardBody
project={project}
projectCanBeActive={projectCanBeActive}
currentMemberRole={currentMemberRole}
duration={duration}
descLinesCount={
Expand Down
16 changes: 16 additions & 0 deletions src/components/ProjectStatus/ProjectStatus.scss
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,22 @@
&.active {
background: $tc-gray-10;
}

&.disabled {
cursor: default;

svg {
filter: grayscale(1);
}

span {
color: $tc-gray-30;
}

&:hover {
background: transparent;
}
}

svg {
margin-top: 7px;
Expand Down
76 changes: 57 additions & 19 deletions src/components/ProjectStatus/editableProjectStatus.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,18 @@ import ProjectStatusChangeConfirmation from './ProjectStatusChangeConfirmation'
import cn from 'classnames'
import _ from 'lodash'
import enhanceDropdown from 'appirio-tech-react-components/components/Dropdown/enhanceDropdown'
import Tooltip from 'appirio-tech-react-components/components/Tooltip/Tooltip'
import {
PROJECT_STATUS,
PROJECT_STATUS_ACTIVE,
PROJECT_STATUS_COMPLETED,
PROJECT_STATUS_CANCELLED
PROJECT_STATUS_CANCELLED,
TOOLTIP_DEFAULT_DELAY
} from '../../config/constants'
import CarretDownNormal9px from '../../assets/icons/arrow-9px-carret-down-normal.svg'


const hocStatusDropdown = (CompositeComponent, statusList) => {
const hocStatusDropdown = (CompositeComponent, statusList, projectCanBeActive) => {
class StatusDropdown extends Component {
shouldDropdownUp() {
if (this.refs.dropdown) {
Expand All @@ -32,6 +35,12 @@ const hocStatusDropdown = (CompositeComponent, statusList) => {
return null
}

const activestatusList = statusList.map((status) => ({
...status,
disabled: !projectCanBeActive && status.value === PROJECT_STATUS_ACTIVE,
toolTipMessage: (!projectCanBeActive && status.value === PROJECT_STATUS_ACTIVE) ? 'To activate project there should be at least one phase in "Planned" status. Please, check "Project Plan" tab.' : null,
}))

this.shouldDropdownUp()
return (
<div className="project-status-dropdown" ref="dropdown">
Expand All @@ -46,26 +55,51 @@ const hocStatusDropdown = (CompositeComponent, statusList) => {
unifiedHeader={unifiedHeader}
/>
{ canEdit && <i className="caret" >
<CarretDownNormal9px className="icon-carret-down-normal"/>
<CarretDownNormal9px className="icon-carret-down-normal" />
</i> }
</div>
{ isOpen && canEdit &&
<div className={cn('status-dropdown', { 'dropdown-up': this.shouldDropdownUp() })}>
<div className="status-header">Project Status</div>
<ul>
{
statusList.sort((a, b) => a.dropDownOrder > b.dropDownOrder).map((item) =>
(<li key={item.value}>
<a
href="javascript:"
className={cn('status-option', 'status-' + item.value, { active: item.value === status })}
onClick={(e) => {
onItemSelect(item.value, e)
}}
>
<CompositeComponent status={item} showText />
</a>
</li>)
activestatusList.sort((a, b) => a.dropDownOrder > b.dropDownOrder).map((item) =>
item.toolTipMessage ? (
<Tooltip key={item.value} theme="light" tooltipDelay={TOOLTIP_DEFAULT_DELAY}>
<div className="tooltip-target">
<li>
<a
href="javascript:"
className={cn('status-option', 'status-' + item.value, { active: item.value === status, disabled: item.disabled })}
onClick={(e) => {
if (!item.disabled)
onItemSelect(item.value, e)
}}
>
<CompositeComponent status={item} showText />
</a>
</li>
</div>
<div className="tooltip-body">
{item.toolTipMessage}
</div>
</Tooltip>
) : (
<div key={item.value} className="tooltip-target">
<li>
<a
href="javascript:"
className={cn('status-option', 'status-' + item.value, { active: item.value === status, disabled: item.disabled })}
onClick={(e) => {
if (!item.disabled)
onItemSelect(item.value, e)
}}
>
<CompositeComponent status={item} showText />
</a>
</li>
</div>
)
)
}
</ul>
Expand Down Expand Up @@ -126,10 +160,10 @@ const editableProjectStatus = (CompositeComponent) => class extends Component {

render() {
const { showStatusChangeDialog, newStatus, statusChangeReason } = this.state
const { canEdit } = this.props
const { canEdit, projectCanBeActive } = this.props
const StatusDropdown = canEdit
? enhanceDropdown(hocStatusDropdown(CompositeComponent, PROJECT_STATUS))
: hocStatusDropdown(CompositeComponent, PROJECT_STATUS)
? enhanceDropdown(hocStatusDropdown(CompositeComponent, PROJECT_STATUS, projectCanBeActive))
: hocStatusDropdown(CompositeComponent, PROJECT_STATUS, projectCanBeActive)
return (
<div className={cn('EditableProjectStatus', {'modal-active': showStatusChangeDialog})}>
<div className="modal-overlay" onClick={ this.hideStatusChangeDialog }/>
Expand All @@ -152,7 +186,11 @@ editableProjectStatus.propTypes = {
/**
* Boolean flag to control editability of the project status. It does not render the dropdown if it is not editable.
*/
canEdit: PropTypes.bool
canEdit: PropTypes.bool,
/**
* Boolean flag to control if project status can be switched to active.
*/
projectCanBeActive: PropTypes.bool
}

export default editableProjectStatus
5 changes: 4 additions & 1 deletion src/projects/components/projectsCard/ProjectCardBody.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import _ from 'lodash'

const EnhancedProjectStatus = editableProjectStatus(ProjectStatus)

function ProjectCardBody({ project, duration, currentMemberRole, descLinesCount = 8,
function ProjectCardBody({ project, projectCanBeActive, duration, currentMemberRole, descLinesCount = 8,
onChangeStatus, isSuperUser, showLink, showLinkURL, canEditStatus = true }) {
if (!project) return null

Expand Down Expand Up @@ -39,6 +39,7 @@ function ProjectCardBody({ project, duration, currentMemberRole, descLinesCount
{(project.status !== PROJECT_STATUS_ACTIVE || progress === 0) &&
<EnhancedProjectStatus
status={project.status}
projectCanBeActive={projectCanBeActive}
showText
withoutLabel
currentMemberRole={currentMemberRole}
Expand All @@ -59,13 +60,15 @@ function ProjectCardBody({ project, duration, currentMemberRole, descLinesCount
}

ProjectCardBody.defaultTypes = {
projectCanBeActive: true,
showLink: false,
showLinkURL: '',
canEditStatus: true
}

ProjectCardBody.propTypes = {
project: PT.object.isRequired,
projectCanBeActive: PT.bool,
currentMemberRole: PT.string,
duration: PT.object.isRequired,
showLink: PT.bool,
Expand Down