Skip to content

Commit f7e2bfa

Browse files
author
vikasrohit
authored
Merge pull request #2809 from appirio-tech/feature/project-activation-improvement
Feature/project activation improvement
2 parents d1f761b + 861a7a7 commit f7e2bfa

File tree

4 files changed

+86
-25
lines changed

4 files changed

+86
-25
lines changed

src/components/ProjectInfo/ProjectInfo.jsx

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import ProjectDirectLinks from '../../projects/list/components/Projects/ProjectD
1010
import MobileExpandable from '../MobileExpandable/MobileExpandable'
1111
import ProjectProgress from '../../projects/detail/components/ProjectProgress'
1212
import MediaQuery from 'react-responsive'
13-
import { SCREEN_BREAKPOINT_MD, PHASE_STATUS_ACTIVE, PROJECT_ROLE_OWNER, PROJECT_ROLE_CUSTOMER } from '../../config/constants'
13+
import { SCREEN_BREAKPOINT_MD, PROJECT_STATUS_ACTIVE, PHASE_STATUS_ACTIVE, PHASE_STATUS_REVIEWED, PROJECT_ROLE_OWNER, PROJECT_ROLE_CUSTOMER } from '../../config/constants'
1414
import ReviewProjectButton from '../../projects/detail/components/ReviewProjectButton'
1515

1616
import { formatProjectProgressProps, formatOldProjectProgressProps } from '../../helpers/projectHelper'
@@ -52,6 +52,9 @@ class ProjectInfo extends Component {
5252
)
5353

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

5659
// prepare review button
5760
const showReviewBtn = project.status === 'draft' &&
@@ -60,10 +63,10 @@ class ProjectInfo extends Component {
6063
const reviewButtonSection = (
6164
<div className="project-info-review">
6265
<p>
63-
Your project "{_.unescape(project.name)}" has been drafted.
64-
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.
65-
Once you've finalized your scope, select the "Submit for Review" button.
66-
Topcoder will then review your drafted project and will assign a manager to get your delivery in-progress!
66+
Your project "{_.unescape(project.name)}" has been drafted.
67+
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.
68+
Once you've finalized your scope, select the "Submit for Review" button.
69+
Topcoder will then review your drafted project and will assign a manager to get your delivery in-progress!
6770
Get stuck or need help? Email us at <a href="mailto:support@topcoder.com">support@topcoder.com</a>.
6871
</p>
6972
<ReviewProjectButton project={project} onClick={onSubmitForReview} disabled={isProjectProcessing} />
@@ -108,6 +111,7 @@ class ProjectInfo extends Component {
108111
{(matches) => (
109112
<ProjectCardBody
110113
project={project}
114+
projectCanBeActive={projectCanBeActive}
111115
currentMemberRole={currentMemberRole}
112116
duration={duration}
113117
descLinesCount={

src/components/ProjectStatus/ProjectStatus.scss

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,22 @@
160160
&.active {
161161
background: $tc-gray-10;
162162
}
163+
164+
&.disabled {
165+
cursor: default;
166+
167+
svg {
168+
filter: grayscale(1);
169+
}
170+
171+
span {
172+
color: $tc-gray-30;
173+
}
174+
175+
&:hover {
176+
background: transparent;
177+
}
178+
}
163179

164180
svg {
165181
margin-top: 7px;

src/components/ProjectStatus/editableProjectStatus.js

Lines changed: 57 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,18 @@ import ProjectStatusChangeConfirmation from './ProjectStatusChangeConfirmation'
44
import cn from 'classnames'
55
import _ from 'lodash'
66
import enhanceDropdown from 'appirio-tech-react-components/components/Dropdown/enhanceDropdown'
7+
import Tooltip from 'appirio-tech-react-components/components/Tooltip/Tooltip'
78
import {
89
PROJECT_STATUS,
10+
PROJECT_STATUS_ACTIVE,
911
PROJECT_STATUS_COMPLETED,
10-
PROJECT_STATUS_CANCELLED
12+
PROJECT_STATUS_CANCELLED,
13+
TOOLTIP_DEFAULT_DELAY
1114
} from '../../config/constants'
1215
import CarretDownNormal9px from '../../assets/icons/arrow-9px-carret-down-normal.svg'
1316

1417

15-
const hocStatusDropdown = (CompositeComponent, statusList) => {
18+
const hocStatusDropdown = (CompositeComponent, statusList, projectCanBeActive) => {
1619
class StatusDropdown extends Component {
1720
shouldDropdownUp() {
1821
if (this.refs.dropdown) {
@@ -32,6 +35,12 @@ const hocStatusDropdown = (CompositeComponent, statusList) => {
3235
return null
3336
}
3437

38+
const activestatusList = statusList.map((status) => ({
39+
...status,
40+
disabled: !projectCanBeActive && status.value === PROJECT_STATUS_ACTIVE,
41+
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,
42+
}))
43+
3544
this.shouldDropdownUp()
3645
return (
3746
<div className="project-status-dropdown" ref="dropdown">
@@ -46,26 +55,51 @@ const hocStatusDropdown = (CompositeComponent, statusList) => {
4655
unifiedHeader={unifiedHeader}
4756
/>
4857
{ canEdit && <i className="caret" >
49-
<CarretDownNormal9px className="icon-carret-down-normal"/>
58+
<CarretDownNormal9px className="icon-carret-down-normal" />
5059
</i> }
5160
</div>
5261
{ isOpen && canEdit &&
5362
<div className={cn('status-dropdown', { 'dropdown-up': this.shouldDropdownUp() })}>
5463
<div className="status-header">Project Status</div>
5564
<ul>
5665
{
57-
statusList.sort((a, b) => a.dropDownOrder > b.dropDownOrder).map((item) =>
58-
(<li key={item.value}>
59-
<a
60-
href="javascript:"
61-
className={cn('status-option', 'status-' + item.value, { active: item.value === status })}
62-
onClick={(e) => {
63-
onItemSelect(item.value, e)
64-
}}
65-
>
66-
<CompositeComponent status={item} showText />
67-
</a>
68-
</li>)
66+
activestatusList.sort((a, b) => a.dropDownOrder > b.dropDownOrder).map((item) =>
67+
item.toolTipMessage ? (
68+
<Tooltip key={item.value} theme="light" tooltipDelay={TOOLTIP_DEFAULT_DELAY}>
69+
<div className="tooltip-target">
70+
<li>
71+
<a
72+
href="javascript:"
73+
className={cn('status-option', 'status-' + item.value, { active: item.value === status, disabled: item.disabled })}
74+
onClick={(e) => {
75+
if (!item.disabled)
76+
onItemSelect(item.value, e)
77+
}}
78+
>
79+
<CompositeComponent status={item} showText />
80+
</a>
81+
</li>
82+
</div>
83+
<div className="tooltip-body">
84+
{item.toolTipMessage}
85+
</div>
86+
</Tooltip>
87+
) : (
88+
<div key={item.value} className="tooltip-target">
89+
<li>
90+
<a
91+
href="javascript:"
92+
className={cn('status-option', 'status-' + item.value, { active: item.value === status, disabled: item.disabled })}
93+
onClick={(e) => {
94+
if (!item.disabled)
95+
onItemSelect(item.value, e)
96+
}}
97+
>
98+
<CompositeComponent status={item} showText />
99+
</a>
100+
</li>
101+
</div>
102+
)
69103
)
70104
}
71105
</ul>
@@ -126,10 +160,10 @@ const editableProjectStatus = (CompositeComponent) => class extends Component {
126160

127161
render() {
128162
const { showStatusChangeDialog, newStatus, statusChangeReason } = this.state
129-
const { canEdit } = this.props
163+
const { canEdit, projectCanBeActive } = this.props
130164
const StatusDropdown = canEdit
131-
? enhanceDropdown(hocStatusDropdown(CompositeComponent, PROJECT_STATUS))
132-
: hocStatusDropdown(CompositeComponent, PROJECT_STATUS)
165+
? enhanceDropdown(hocStatusDropdown(CompositeComponent, PROJECT_STATUS, projectCanBeActive))
166+
: hocStatusDropdown(CompositeComponent, PROJECT_STATUS, projectCanBeActive)
133167
return (
134168
<div className={cn('EditableProjectStatus', {'modal-active': showStatusChangeDialog})}>
135169
<div className="modal-overlay" onClick={ this.hideStatusChangeDialog }/>
@@ -152,7 +186,11 @@ editableProjectStatus.propTypes = {
152186
/**
153187
* Boolean flag to control editability of the project status. It does not render the dropdown if it is not editable.
154188
*/
155-
canEdit: PropTypes.bool
189+
canEdit: PropTypes.bool,
190+
/**
191+
* Boolean flag to control if project status can be switched to active.
192+
*/
193+
projectCanBeActive: PropTypes.bool
156194
}
157195

158196
export default editableProjectStatus

src/projects/components/projectsCard/ProjectCardBody.jsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import _ from 'lodash'
1111

1212
const EnhancedProjectStatus = editableProjectStatus(ProjectStatus)
1313

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

@@ -39,6 +39,7 @@ function ProjectCardBody({ project, duration, currentMemberRole, descLinesCount
3939
{(project.status !== PROJECT_STATUS_ACTIVE || progress === 0) &&
4040
<EnhancedProjectStatus
4141
status={project.status}
42+
projectCanBeActive={projectCanBeActive}
4243
showText
4344
withoutLabel
4445
currentMemberRole={currentMemberRole}
@@ -59,13 +60,15 @@ function ProjectCardBody({ project, duration, currentMemberRole, descLinesCount
5960
}
6061

6162
ProjectCardBody.defaultTypes = {
63+
projectCanBeActive: true,
6264
showLink: false,
6365
showLinkURL: '',
6466
canEditStatus: true
6567
}
6668

6769
ProjectCardBody.propTypes = {
6870
project: PT.object.isRequired,
71+
projectCanBeActive: PT.bool,
6972
currentMemberRole: PT.string,
7073
duration: PT.object.isRequired,
7174
showLink: PT.bool,

0 commit comments

Comments
 (0)