Skip to content

Commit fafe11a

Browse files
committed
https://github.com/appirio-tech/connect-app/issues/4474
- Disable Double click for every Button. - Update Toaster message as well As Milestone rejected successfully - Unable to Reject Milestone >> Let’s disable done button until user does not enter any text.
1 parent 875299c commit fafe11a

File tree

10 files changed

+81
-12
lines changed

10 files changed

+81
-12
lines changed

src/config/constants.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,8 +318,14 @@ export const LOAD_PROJECT_PHASES = 'LOAD_PROJECT_PHASES'
318318
export const LOAD_PROJECT_PHASES_PENDING = 'LOAD_PROJECT_PHASES_PENDING'
319319
export const LOAD_PROJECT_PHASES_FAILURE = 'LOAD_PROJECT_PHASES_FAILURE'
320320
export const LOAD_PROJECT_PHASES_SUCCESS = 'LOAD_PROJECT_PHASES_SUCCESS'
321+
export const CUSTOMER_APPROVE_MILESTONE_PENDING = 'CUSTOMER_APPROVE_MILESTONE_PENDING'
322+
export const CUSTOMER_APPROVE_MILESTONE_FINISHED = 'CUSTOMER_APPROVE_MILESTONE_FINISHED'
321323
export const CUSTOMER_APPROVE_MILESTONE_SUCCESS = 'CUSTOMER_APPROVE_MILESTONE_SUCCESS'
322324
export const CUSTOMER_APPROVE_MILESTONE_FAILURE = 'CUSTOMER_APPROVE_MILESTONE_FAILURE'
325+
export const CUSTOMER_APPROVE_MILESTONE_APPROVE_SUCCESS = 'CUSTOMER_APPROVE_MILESTONE_APPROVE_SUCCESS'
326+
export const CUSTOMER_APPROVE_MILESTONE_APPROVE_FAILURE = 'CUSTOMER_APPROVE_MILESTONE_APPROVE_FAILURE'
327+
export const CUSTOMER_APPROVE_MILESTONE_REJECT_SUCCESS = 'CUSTOMER_APPROVE_MILESTONE_REJECT_SUCCESS'
328+
export const CUSTOMER_APPROVE_MILESTONE_REJECT_FAILURE = 'CUSTOMER_APPROVE_MILESTONE_REJECT_FAILURE'
323329

324330
export const LOAD_PRODUCT_TIMELINE_WITH_MILESTONES = 'LOAD_PRODUCT_TIMELINE_WITH_MILESTONES'
325331
export const LOAD_PRODUCT_TIMELINE_WITH_MILESTONES_PENDING = 'LOAD_PRODUCT_TIMELINE_WITH_MILESTONES_PENDING'

src/projects/actions/project.js

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,13 @@ import {
7373
ES_REINDEX_DELAY,
7474
CREATE_PROJECT_PHASE,
7575
CUSTOMER_APPROVE_MILESTONE_SUCCESS,
76-
CUSTOMER_APPROVE_MILESTONE_FAILURE
76+
CUSTOMER_APPROVE_MILESTONE_FAILURE,
77+
CUSTOMER_APPROVE_MILESTONE_PENDING,
78+
CUSTOMER_APPROVE_MILESTONE_FINISHED,
79+
CUSTOMER_APPROVE_MILESTONE_APPROVE_SUCCESS,
80+
CUSTOMER_APPROVE_MILESTONE_REJECT_FAILURE,
81+
CUSTOMER_APPROVE_MILESTONE_APPROVE_FAILURE,
82+
CUSTOMER_APPROVE_MILESTONE_REJECT_SUCCESS
7783
} from '../../config/constants'
7884
import {
7985
updateProductMilestone,
@@ -516,9 +522,17 @@ export function executePhaseApproval(projectId, phaseId, updatedProps, phaseInde
516522
console.log('execute update phases')
517523
const state = getState()
518524
phaseIndex = phaseIndex ? phaseIndex : _.findIndex(state.projectState.phases, { id: phaseId })
519-
525+
dispatch({type: CUSTOMER_APPROVE_MILESTONE_PENDING,
526+
payload: {phaseId}
527+
})
520528
return createPhaseApprovalAPI(projectId, phaseId, updatedProps, phaseIndex).then(() => {
529+
dispatch({type: CUSTOMER_APPROVE_MILESTONE_FINISHED,
530+
payload: {phaseId}
531+
})
521532
}).catch(() => {
533+
dispatch({type: CUSTOMER_APPROVE_MILESTONE_FINISHED,
534+
payload: {phaseId}
535+
})
522536
return Promise.reject(new Error('Fail to approve milestone'))
523537
})
524538
}
@@ -531,12 +545,18 @@ export function executePhaseApproval(projectId, phaseId, updatedProps, phaseInde
531545
*
532546
* @return {Promise} phase
533547
*/
534-
export function approveMilestone(success = true) {
548+
export function approveMilestone(success = true, approvalType) {
535549
return (dispatch) => {
550+
let type = CUSTOMER_APPROVE_MILESTONE_FAILURE
536551
if (success) {
537-
dispatch({ type: CUSTOMER_APPROVE_MILESTONE_SUCCESS })
552+
if (approvalType === 'approve') type = CUSTOMER_APPROVE_MILESTONE_APPROVE_SUCCESS
553+
else if (approvalType === 'reject') type = CUSTOMER_APPROVE_MILESTONE_REJECT_SUCCESS
554+
else type = CUSTOMER_APPROVE_MILESTONE_SUCCESS;
555+
dispatch({ type })
538556
} else {
539-
dispatch({ type: CUSTOMER_APPROVE_MILESTONE_FAILURE })
557+
if (approvalType === 'approve') type = CUSTOMER_APPROVE_MILESTONE_APPROVE_FAILURE
558+
else if (approvalType === 'reject') type = CUSTOMER_APPROVE_MILESTONE_REJECT_FAILURE
559+
dispatch({ type })
540560
}
541561
}
542562
}

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ class CreateSimplePlan extends React.Component {
3535
project,
3636
// phases,
3737
milestones,
38+
milestonesInApproval,
3839
onChangeMilestones,
3940
onSaveMilestone,
4041
onRemoveMilestone,
@@ -72,6 +73,7 @@ class CreateSimplePlan extends React.Component {
7273
</div>
7374
<ManageMilestones
7475
milestones={milestones}
76+
milestonesInApproval={milestonesInApproval}
7577
onGetChallenges={onGetChallenges}
7678
onChangeMilestones={onChangeMilestones}
7779
onSaveMilestone={onSaveMilestone}

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,7 @@ class ManageMilestones extends React.Component {
251251
render() {
252252
const {
253253
milestones,
254+
milestonesInApproval,
254255
projectMembers,
255256
onChangeMilestones,
256257
isUpdatable,
@@ -285,12 +286,14 @@ class ManageMilestones extends React.Component {
285286
<MilestoneApprovalButton key={1} type="approve"
286287
global
287288
title={'APPROVE'}
289+
disabled={milestonesInApproval.length > 0}
288290
onClick={() => {this.onApprove({type: 'approve'})}}
289291
/>
290292
</div>,
291293
<MilestoneApprovalButton key={2} type="reject"
292294
global
293295
title={'REJECT'}
296+
disabled={milestonesInApproval.length > 0}
294297
onClick={(v) => this.onApprove({type: 'reject', comment: v})}
295298
/>
296299
] :
@@ -361,6 +364,7 @@ class ManageMilestones extends React.Component {
361364
isCustomer={isCustomer}
362365
onApprove={this.onApprove}
363366
phaseMembers={milestone.members}
367+
isApproving={milestonesInApproval.indexOf(milestone.id) !== -1}
364368
/>,
365369
...this.renderChallengeTable(milestone)
366370
]

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ class ConfirmRejectMilestone extends React.Component {
3333
type="button"
3434
className="tc-btn tc-btn-sm"
3535
onClick={() => onClose(true, this.state.value)}
36+
disabled={this.state.value.trim().length === 0}
3637
>
3738
DONE
3839
</button>

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ class MilestoneApprovalButton extends React.Component {
2020
}
2121

2222
render() {
23-
const {type, onClick, global, title, hidePoper} = this.props
23+
const {type, onClick, global, title, hidePoper, disabled} = this.props
2424
const color = type === 'approve' ? 'green' : 'red'
2525

2626
return (
@@ -31,6 +31,7 @@ class MilestoneApprovalButton extends React.Component {
3131
styleName={`icon-button ${
3232
global ? 'icon-button-global' : ''
3333
} ${color} ${title ? 'with-title' : ''}`}
34+
disabled={disabled}
3435
onClick={() => {
3536
if(type === 'reject') {
3637
this.setState({open: true})

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ function MilestoneRow({
4444
isUpdatable,
4545
phaseMembers,
4646
disableDeleteAction,
47-
isCustomer
47+
isCustomer,
48+
isApproving
4849
}) {
4950
const isNeedApproval = milestone.status === PHASE_STATUS_IN_REVIEW
5051
const showApproval = isCustomer && isNeedApproval
@@ -360,6 +361,7 @@ function MilestoneRow({
360361
showApproval &&
361362
<MilestoneApprovalButton
362363
type={'approve'}
364+
disabled={isApproving}
363365
onClick={() => {
364366
onApprove({type: 'approve', item: milestone})
365367
}}
@@ -369,6 +371,7 @@ function MilestoneRow({
369371
showApproval &&
370372
<MilestoneApprovalButton
371373
type="reject"
374+
disabled={isApproving}
372375
onClick={(v) => {
373376
onApprove({type: 'reject', comment: v, item: milestone})
374377
}}

src/projects/detail/containers/DashboardContainer.jsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,11 +172,11 @@ class DashboardContainer extends React.Component {
172172
})
173173
})
174174

175-
approveMilestone()
175+
approveMilestone(true, type)
176176
})
177177
.catch((e) => {
178178
console.log('onApproveMilestones f', e)
179-
approveMilestone(false)
179+
approveMilestone(false, type)
180180
})
181181
.finally(() => {
182182
this.onChangeMilestones(updatedPhases)
@@ -391,6 +391,7 @@ class DashboardContainer extends React.Component {
391391
)
392392

393393
const milestones = this.state.createGameplanPhases || visiblePhases || []
394+
const milestonesInApproval = this.props.milestonesInApproval || []
394395

395396
return (
396397
<TwoColsLayout>
@@ -517,6 +518,7 @@ class DashboardContainer extends React.Component {
517518
project={project}
518519
phases={phases}
519520
milestones={milestones}
521+
milestonesInApproval={milestonesInApproval}
520522
onChangeMilestones={this.onChangeMilestones}
521523
onSaveMilestone={this.onSaveMilestone}
522524
onGetChallenges={this.onGetChallenges}
@@ -556,6 +558,7 @@ const mapStateToProps = ({ notifications, projectState, projectTopics, templates
556558
isFeedsLoading: projectTopics.isLoading,
557559
phasesStates: projectState.phasesStates,
558560
phasesTopics: topics,
561+
milestonesInApproval: projectState.milestonesInApproval,
559562
}
560563
}
561564

src/projects/reducers/project.js

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import {
2626
ACCEPT_OR_REFUSE_INVITE_SUCCESS, ACCEPT_OR_REFUSE_INVITE_FAILURE, ACCEPT_OR_REFUSE_INVITE_PENDING,
2727
UPLOAD_PROJECT_ATTACHMENT_FILES, DISCARD_PROJECT_ATTACHMENT, CHANGE_ATTACHMENT_PERMISSION,
2828
CREATE_SCOPE_CHANGE_REQUEST_SUCCESS, APPROVE_SCOPE_CHANGE_SUCCESS, REJECT_SCOPE_CHANGE_SUCCESS, CANCEL_SCOPE_CHANGE_SUCCESS, ACTIVATE_SCOPE_CHANGE_SUCCESS,
29-
LOAD_PROJECT_MEMBERS_SUCCESS, LOAD_PROJECT_MEMBER_INVITES_SUCCESS, LOAD_PROJECT_MEMBER_SUCCESS, CREATE_PROJECT_PHASE_PENDING, CREATE_PROJECT_PHASE_SUCCESS,
29+
LOAD_PROJECT_MEMBERS_SUCCESS, LOAD_PROJECT_MEMBER_INVITES_SUCCESS, LOAD_PROJECT_MEMBER_SUCCESS, CREATE_PROJECT_PHASE_PENDING, CREATE_PROJECT_PHASE_SUCCESS, CUSTOMER_APPROVE_MILESTONE_PENDING, CUSTOMER_APPROVE_MILESTONE_FINISHED,
3030
} from '../../config/constants'
3131
import _ from 'lodash'
3232
import update from 'react-addons-update'
@@ -60,7 +60,8 @@ const initialState = {
6060
isLoadingPhases: false,
6161
showUserInvited: undefined, // keep default as `undefined` so we can track when it changes values to false/true on load
6262
userInvitationId: null,
63-
phasesStates: {} // controls opened phases and tabs of the phases
63+
phasesStates: {}, // controls opened phases and tabs of the phases
64+
milestonesInApproval: []
6465
}
6566

6667
// NOTE: We should always update projectNonDirty state whenever we update the project state
@@ -963,6 +964,14 @@ export const projectState = function (state=initialState, action) {
963964
updatingMemberIds: _.remove(state.updatingMemberIds, [action.payload.id]),
964965
error: parseErrorObj(action)
965966
})
967+
case CUSTOMER_APPROVE_MILESTONE_PENDING:
968+
return Object.assign({}, state, {
969+
milestonesInApproval: state.milestonesInApproval.concat([action.payload.phaseId])
970+
})
971+
case CUSTOMER_APPROVE_MILESTONE_FINISHED:
972+
return Object.assign({}, state, {
973+
milestonesInApproval: state.milestonesInApproval.filter(x => x !== action.payload.phaseId)
974+
})
966975

967976
default:
968977
return state

src/reducers/alerts.js

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,11 @@ import {
7373
ACTIVATE_SCOPE_CHANGE_FAILURE,
7474
CREATE_PROJECT_PHASE_SUCCESS,
7575
CUSTOMER_APPROVE_MILESTONE_SUCCESS,
76-
CUSTOMER_APPROVE_MILESTONE_FAILURE
76+
CUSTOMER_APPROVE_MILESTONE_FAILURE,
77+
CUSTOMER_APPROVE_MILESTONE_APPROVE_SUCCESS,
78+
CUSTOMER_APPROVE_MILESTONE_REJECT_SUCCESS,
79+
CUSTOMER_APPROVE_MILESTONE_APPROVE_FAILURE,
80+
CUSTOMER_APPROVE_MILESTONE_REJECT_FAILURE
7781
} from '../config/constants'
7882
/* eslint-enable no-unused-vars */
7983

@@ -266,8 +270,24 @@ export default function(state = {}, action) {
266270
return state
267271
}
268272
case CUSTOMER_APPROVE_MILESTONE_SUCCESS:
273+
Alert.success('Approved or Rejected Milestones successfully.')
274+
return state
275+
276+
case CUSTOMER_APPROVE_MILESTONE_APPROVE_SUCCESS:
269277
Alert.success('Approved Milestones successfully.')
270278
return state
279+
280+
case CUSTOMER_APPROVE_MILESTONE_REJECT_SUCCESS:
281+
Alert.success('Rejected Milestones successfully.')
282+
return state
283+
284+
case CUSTOMER_APPROVE_MILESTONE_APPROVE_FAILURE:
285+
Alert.success('Unable to Approve Milestone.')
286+
return state
287+
288+
case CUSTOMER_APPROVE_MILESTONE_REJECT_FAILURE:
289+
Alert.success('Unable to Reject Milestone.')
290+
return state
271291

272292
case CUSTOMER_APPROVE_MILESTONE_FAILURE:
273293
Alert.error('Unable to Approve Milestone.')

0 commit comments

Comments
 (0)