Skip to content

Commit aba65f8

Browse files
committed
Miletone Management Fixes
2 parents 18225a1 + 8805263 commit aba65f8

File tree

11 files changed

+139
-64
lines changed

11 files changed

+139
-64
lines changed

src/api/projects.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,3 +223,8 @@ export function deleteProjectPhase(projectId, phaseId) {
223223
return axios.delete(`${PROJECTS_API_URL}/v5/projects/${projectId}/phases/${phaseId}`)
224224
.then(() => ({ projectId, phaseId }))
225225
}
226+
227+
export function deleteBulkProjectPhase(projectId, phaseIds) {
228+
return axios.delete(`${PROJECTS_API_URL}/v5/projects/${projectId}/phases`, { data: { phaseIds } })
229+
.then(() => ({ phaseIds }))
230+
}

src/config/constants.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,11 @@ export const DELETE_PROJECT_PHASE_PENDING = 'DELETE_PROJECT_PHASE_PENDING'
300300
export const DELETE_PROJECT_PHASE_FAILURE = 'DELETE_PROJECT_PHASE_FAILURE'
301301
export const DELETE_PROJECT_PHASE_SUCCESS = 'DELETE_PROJECT_PHASE_SUCCESS'
302302

303+
export const DELETE_BULK_PROJECT_PHASE = 'DELETE_BULK_PROJECT_PHASE'
304+
export const DELETE_BULK_PROJECT_PHASE_PENDING = 'DELETE_BULK_PROJECT_PHASE_PENDING'
305+
export const DELETE_BULK_PROJECT_PHASE_FAILURE = 'DELETE_BULK_PROJECT_PHASE_FAILURE'
306+
export const DELETE_BULK_PROJECT_PHASE_SUCCESS = 'DELETE_BULK_PROJECT_PHASE_SUCCESS'
307+
303308
export const UPDATE_PRODUCT = 'UPDATE_PRODUCT'
304309
export const UPDATE_PRODUCT_PENDING = 'UPDATE_PRODUCT_PENDING'
305310
export const UPDATE_PRODUCT_SUCCESS = 'UPDATE_PRODUCT_SUCCESS'

src/config/permissions.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ export const PERMISSIONS = {
249249
description: 'Remove copilots form the project.',
250250
},
251251
projectRoles: [
252-
..._.difference(PROJECT_ALL, [PROJECT_ROLE_COPILOT, PROJECT_ROLE_CUSTOMER])
252+
..._.difference(PROJECT_ALL, [PROJECT_ROLE_CUSTOMER])
253253
],
254254
topcoderRoles: [
255255
...TOPCODER_ADMINS,

src/projects/actions/project.js

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { getProjectById,
77
updateProject as updateProjectAPI,
88
deleteProject as deleteProjectAPI,
99
deleteProjectPhase as deleteProjectPhaseAPI,
10+
deleteBulkProjectPhase as deleteBulkProjectPhaseAPI,
1011
getProjectPhases,
1112
updateProduct as updateProductAPI,
1213
updatePhase as updatePhaseAPI,
@@ -79,7 +80,8 @@ import {
7980
CUSTOMER_APPROVE_MILESTONE_APPROVE_SUCCESS,
8081
CUSTOMER_APPROVE_MILESTONE_REJECT_FAILURE,
8182
CUSTOMER_APPROVE_MILESTONE_APPROVE_FAILURE,
82-
CUSTOMER_APPROVE_MILESTONE_REJECT_SUCCESS
83+
CUSTOMER_APPROVE_MILESTONE_REJECT_SUCCESS,
84+
DELETE_BULK_PROJECT_PHASE
8385
} from '../../config/constants'
8486
import {
8587
updateProductMilestone,
@@ -334,6 +336,11 @@ export function createProjectPhaseAndProduct(project, productTemplate, status =
334336
description: productTemplate.description,
335337
productTemplateId: productTemplate.id,
336338
}
339+
340+
if(productTemplate.members) {
341+
param.members = productTemplate.members
342+
}
343+
337344
if (startDate) {
338345
param['startDate'] = startDate.format('YYYY-MM-DD')
339346
}
@@ -441,6 +448,15 @@ export function deleteProjectPhase(projectId, phaseId) {
441448
}
442449
}
443450

451+
export function deleteBulkProjectPhase(projectId, phaseIds) {
452+
return (dispatch) => {
453+
return dispatch({
454+
type: DELETE_BULK_PROJECT_PHASE,
455+
payload: deleteBulkProjectPhaseAPI(projectId, phaseIds)
456+
})
457+
}
458+
}
459+
444460
export function updateProject(projectId, updatedProps, updateExisting = false) {
445461
return (dispatch) => {
446462
return dispatch({

src/projects/detail/components/SimplePlan/CreateSimplePlan/CreateSimplePlan.jsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ class CreateSimplePlan extends React.Component {
3939
onChangeMilestones,
4040
onSaveMilestone,
4141
onRemoveMilestone,
42+
onRemoveAllMilestones,
4243
onGetChallenges,
4344
onApproveMilestones,
4445
isProjectLive,
@@ -78,6 +79,7 @@ class CreateSimplePlan extends React.Component {
7879
onChangeMilestones={onChangeMilestones}
7980
onSaveMilestone={onSaveMilestone}
8081
onRemoveMilestone={onRemoveMilestone}
82+
onRemoveAllMilestones={onRemoveAllMilestones}
8183
onApproveMilestones={onApproveMilestones}
8284
projectMembers={project.members}
8385
project={project}
@@ -97,6 +99,7 @@ CreateSimplePlan.propTypes = {
9799
onChangeMilestones: PT.func,
98100
onSaveMilestone: PT.func,
99101
onRemoveMilestone: PT.func,
102+
onRemoveAllMilestones: PT.func,
100103
onGetChallenges: PT.func,
101104
onApproveMilestones: PT.func,
102105
isCustomer: PT.bool,

src/projects/detail/components/SimplePlan/ManageMilestones/ManageMilestones.jsx

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import MilestoneMoveDateButton from '../components/MilestoneMoveDateButton'
1616
import * as milestoneHelper from '../components/helpers/milestone'
1717
import IconUnselect from '../../../../../assets/icons/icon-disselect.svg'
1818
import IconCopilot from '../../../../../assets/icons/icon-copilot.svg'
19-
import { CHALLENGE_ID_MAPPING, PHASE_STATUS_IN_REVIEW } from '../../../../../config/constants'
19+
import { CHALLENGE_ID_MAPPING, PHASE_STATUS_IN_REVIEW, PROJECT_STATUS_CANCELLED, PROJECT_STATUS_COMPLETED } from '../../../../../config/constants'
2020

2121
import './ManageMilestones.scss'
2222
import MilestoneApprovalButton from '../components/MilestoneApprovalButton'
@@ -84,11 +84,14 @@ class ManageMilestones extends React.Component {
8484
}
8585

8686
onDeleteAll() {
87-
const { milestones, onRemoveMilestone } = this.props
88-
const seletedMilestones = _.filter(milestones, m => m.selected)
89-
_.forEach(seletedMilestones, m => {
90-
onRemoveMilestone(m.id)
91-
})
87+
const { milestones, onRemoveAllMilestones } = this.props
88+
const selectedPhases = _.filter(milestones, m => m.selected)
89+
90+
if (selectedPhases.length) {
91+
const { projectId } = selectedPhases[0]
92+
const phaseIds = selectedPhases.map(m => m.id)
93+
onRemoveAllMilestones(projectId, phaseIds)
94+
}
9295
}
9396

9497
onUnselectAll() {
@@ -256,8 +259,11 @@ class ManageMilestones extends React.Component {
256259
onChangeMilestones,
257260
isUpdatable,
258261
isCustomer,
262+
project,
259263
} = this.props
260264

265+
const hideCheckbox = project.status === PROJECT_STATUS_CANCELLED || project.status === PROJECT_STATUS_COMPLETED
266+
261267
// const isNeedApproval = project.status === PROJECT_STATUS_IN_REVIEW
262268
const isNeedApproval = !milestones.filter(ms => ms.selected === true).find(ms => !(ms.status === PHASE_STATUS_IN_REVIEW))
263269
const canShowApproval = isCustomer && isNeedApproval
@@ -325,7 +331,7 @@ class ManageMilestones extends React.Component {
325331
<table styleName="milestones-table">
326332
<colgroup>
327333
<col style={{ width: '20px' }} />
328-
<col style={{ width: '20px' }} />{/* CHECKBOX */}
334+
{hideCheckbox ? null : <col style={{ width: '20px' }} />}{/* CHECKBOX */}
329335
<col style={{ width: '8%' }} />{/* MILESTONE */}
330336
<col />{/* DESCRIPTION */}
331337
<col style={{ width: '12%' }} />{/* START DATE */}
@@ -339,6 +345,7 @@ class ManageMilestones extends React.Component {
339345
milestones={milestones}
340346
onChangeMilestones={onChangeMilestones}
341347
isUpdatable={isUpdatable || isCustomer}
348+
hideCheckbox={hideCheckbox}
342349
/>
343350
</thead>
344351
<tbody>
@@ -365,6 +372,7 @@ class ManageMilestones extends React.Component {
365372
onApprove={this.onApprove}
366373
phaseMembers={milestone.members}
367374
isApproving={milestonesInApproval.indexOf(milestone.id) !== -1}
375+
hideCheckbox={hideCheckbox}
368376
/>,
369377
...this.renderChallengeTable(milestone)
370378
]
@@ -383,6 +391,7 @@ ManageMilestones.propTypes = {
383391
onChangeMilestones: PT.func,
384392
onSaveMilestone: PT.func,
385393
onRemoveMilestone: PT.func,
394+
onRemoveAllMilestones: PT.func,
386395
onGetChallenges: PT.func,
387396
onApproveMilestones: PT.func,
388397
projectMembers: PT.arrayOf(PT.shape()),

src/projects/detail/components/SimplePlan/components/MilestoneHeaderRow/MilestoneHeaderRow.jsx

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import './MilestoneHeaderRow.scss'
99

1010
const TCFormFields = FormsyForm.Fields
1111

12-
function MilestoneHeaderRow ({ milestones, onChangeMilestones, isUpdatable }) {
12+
function MilestoneHeaderRow ({ milestones, onChangeMilestones, isUpdatable, hideCheckbox }) {
1313
const checked = milestones.reduce(
1414
(selected, milestone) => selected = selected && milestone.selected,
1515
milestones.length > 0
@@ -31,16 +31,18 @@ function MilestoneHeaderRow ({ milestones, onChangeMilestones, isUpdatable }) {
3131

3232
return (
3333
<tr styleName="milestone-row">
34-
{isUpdatable ? <th />: null}
35-
<th>
36-
<TCFormFields.Checkbox
37-
name="select-all"
38-
value={checked}
39-
onChange={(_, value) => {
40-
value ? selectAll() : unselectAll()
41-
}}
42-
/>
43-
</th>
34+
<th />
35+
{
36+
hideCheckbox ? null : <th>
37+
<TCFormFields.Checkbox
38+
name="select-all"
39+
value={checked}
40+
onChange={(_, value) => {
41+
value ? selectAll() : unselectAll()
42+
}}
43+
/>
44+
</th>
45+
}
4446
<th>MILESTONE</th>
4547
<th>DESCRIPTION</th>
4648
<th>START DATE</th>
@@ -54,6 +56,7 @@ function MilestoneHeaderRow ({ milestones, onChangeMilestones, isUpdatable }) {
5456

5557
MilestoneHeaderRow.propTypes = {
5658
onChangeMilestones: PT.func,
59+
hideCheckbox: PT.bool,
5760
}
5861

5962
export default MilestoneHeaderRow

src/projects/detail/components/SimplePlan/components/MilestoneRow/MilestoneRow.jsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ function MilestoneRow({
4545
phaseMembers,
4646
disableDeleteAction,
4747
isCustomer,
48-
isApproving
48+
isApproving,
49+
hideCheckbox
4950
}) {
5051
const isNeedApproval = milestone.status === PHASE_STATUS_IN_REVIEW
5152
const showApproval = isCustomer && isNeedApproval
@@ -58,11 +59,12 @@ function MilestoneRow({
5859
let milestoneRef
5960
let startDateRef
6061
let endDateRef
62+
const tdEl = hideCheckbox ? null : <td/>
6163

6264
return edit ? (
6365
<tr styleName="milestone-row" className="edit-milestone-row">
6466
{isUpdatable ? <td /> : null}
65-
{isEditingMilestone ? <td/ >: <td styleName="checkbox">
67+
{(isEditingMilestone || hideCheckbox) ? <td/ >: <td styleName="checkbox">
6668
<TCFormFields.Checkbox
6769
name={`select-${rowId}`}
6870
value={milestone.selected}
@@ -301,7 +303,7 @@ function MilestoneRow({
301303
) : (
302304
<tr styleName="milestone-row">
303305
{isUpdatable ? <td styleName="expand" onClick={() => onExpand(!isExpand, milestone)}>{isExpand ? <IconClose />: <IconExpand />}</td>: <td />}
304-
{isEditingMilestone ? <td/> : <td styleName="checkbox">
306+
{(isEditingMilestone || hideCheckbox) ? tdEl : <td styleName="checkbox">
305307
<TCFormFields.Checkbox
306308
name={`select-${rowId}`}
307309
value={milestone.selected}
@@ -402,6 +404,7 @@ MilestoneRow.propTypes = {
402404
disableDeleteAction: PT.bool,
403405
isCustomer: PT.bool,
404406
members: PT.object,
407+
hideCheckbox: PT.bool,
405408
}
406409

407410
export default MilestoneRow

0 commit comments

Comments
 (0)