Skip to content

Commit 93f12b9

Browse files
authored
Merge pull request #4425 from nqviet/feature/new-milestone-concept
Fix issue #4422, #4424
2 parents 2ed9d6e + cb1d758 commit 93f12b9

File tree

7 files changed

+192
-109
lines changed

7 files changed

+192
-109
lines changed

src/projects/detail/components/SimplePlan/CreateSimplePlan/CreateSimpleplan.scss

Lines changed: 0 additions & 41 deletions
This file was deleted.

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

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ class ManageMilestones extends React.Component {
3030
const index = milestones.findIndex(m => m.id === updatedMilestone.id)
3131

3232
const updatedMilestones = [...milestones]
33+
updatedMilestones.forEach(milestone => milestone.editting = false)
3334
updatedMilestones.splice(index, 1, updatedMilestone)
3435
onChangeMilestones(updatedMilestones)
3536
}
@@ -97,18 +98,22 @@ class ManageMilestones extends React.Component {
9798
<Formsy.Form>
9899
<table styleName="milestones-table">
99100
<colgroup>
100-
<col style={{width: '20px'}} />{/* CHECKBOX */}
101-
<col style={{width: '10%'}} />{/* MILESTONE */}
102-
<col style={{minWidth: '140px'}} />{/* DESCRIPTION */}
103-
<col style={{width: '10%', minWidth: '80px'}} />{/* START DATE */}
104-
<col style={{width: '10%', minWidth: '80px'}} />{/* END DATE */}
105-
<col style={{width: '10%'}} />{/* STATUS */}
106-
<col style={{width: '15%'}} />{/* BUDGET */}
107-
{/* <col style={{width: '10%'}} /> */}{/* COPILOTS */}
108-
<col style={{width: '80px'}} />{/* ACTION */}
101+
<col style={{ width: '20px' }} />{/* CHECKBOX */}
102+
<col style={{ width: '8%' }} />{/* MILESTONE */}
103+
<col />{/* DESCRIPTION */}
104+
<col style={{ width: '12%' }} />{/* START DATE */}
105+
<col style={{ width: '11%' }} />{/* END DATE */}
106+
<col style={{ width: '10%' }} />{/* STATUS */}
107+
<col style={{ width: '12%' }} />{/* BUDGET */}
108+
<col style={{ width: '13%' }} />{/* COPILOTS */}
109+
{isUpdatable && (<col style={{ width: '80px' }} />)}{/* ACTION */}
109110
</colgroup>
110111
<thead>
111-
<MilestoneHeaderRow milestones={milestones} onChangeMilestones={onChangeMilestones} />
112+
<MilestoneHeaderRow
113+
milestones={milestones}
114+
onChangeMilestones={onChangeMilestones}
115+
isUpdatable={isUpdatable}
116+
/>
112117
</thead>
113118
<tbody>
114119
{milestones.map((milestone) => (

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

Lines changed: 67 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,73 @@
4747
text-align: left;
4848
vertical-align: middle;
4949

50-
&:not(:first-child) {
51-
padding-left: 5px;
50+
// checkbox
51+
&:nth-child(1) {}
52+
// milestone
53+
&:nth-child(2) { padding-left: 5px; }
54+
// description
55+
&:nth-child(3) { padding-left: 15px; }
56+
// start date
57+
&:nth-child(4) { padding-left: 25px; }
58+
// end date
59+
&:nth-child(5) { padding-left: 15px; }
60+
// status
61+
&:nth-child(6) { padding-left: 20px; }
62+
// budget
63+
&:nth-child(7) {
64+
padding-left: 20px;
65+
:global(.milestone-budget-prefix-icon) { left: 25px; }
66+
}
67+
// copilot
68+
&:nth-child(8) { padding-left: 25px; }
69+
}
70+
71+
:global(.edit-milestone-row) {
72+
th,
73+
td {
74+
// description
75+
&:nth-child(3) { padding-left: 10px; }
76+
// end date
77+
&:nth-child(5) { padding-left: 10px; }
78+
}
79+
}
80+
81+
@media screen and (max-width: 1024px - 1px) {
82+
th,
83+
td {
84+
// description
85+
&:nth-child(3) { padding-left: 5px; }
86+
// start date
87+
&:nth-child(4) { padding-left: 10px; }
88+
// end date
89+
&:nth-child(5) { padding-left: 5px; }
90+
// status
91+
&:nth-child(6) { padding-left: 10px; }
92+
// budget
93+
&:nth-child(7) {
94+
padding-left: 10px;
95+
:global {
96+
.milestone-budget-prefix-icon {
97+
left: 15px;
98+
}
99+
.tc-file-field__inputs {
100+
min-width: 64px;
101+
padding-left: 10px;
102+
}
103+
}
104+
}
105+
// copilot
106+
&:nth-child(8) { padding-left: 15px; }
107+
}
108+
109+
:global(.edit-milestone-row) {
110+
th,
111+
td {
112+
// description
113+
&:nth-child(3) { padding-left: 5px; }
114+
// end date
115+
&:nth-child(5) { padding-left: 5px; }
116+
}
52117
}
53118
}
54119

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

Lines changed: 2 additions & 2 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 }) {
12+
function MilestoneHeaderRow ({ milestones, onChangeMilestones, isUpdatable }) {
1313
const checked = milestones.reduce(
1414
(selected, milestone) => selected = selected && milestone.selected,
1515
milestones.length > 0
@@ -47,7 +47,7 @@ function MilestoneHeaderRow ({ milestones, onChangeMilestones }) {
4747
<th>STATUS</th>
4848
<th>BUDGET</th>
4949
{/* <th>COPILOTS</th> */}
50-
<th>ACTION</th>
50+
{isUpdatable && (<th>ACTION</th>)}
5151
</tr>
5252
)
5353
}

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

Lines changed: 53 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import PT from 'prop-types'
66
import moment from 'moment'
77
import FormsyForm from 'appirio-tech-react-components/components/Formsy'
88
import _ from 'lodash'
9+
import { components } from 'react-select'
910
import { isValidStartEndDates } from '../../../../../../helpers/utils'
1011
import FormsySelect from '../../../../../../components/Select/FormsySelect'
1112
// import MilestoneCopilots from '../MilestoneCopilots'
@@ -16,8 +17,8 @@ import { PHASE_STATUS_OPTIONS } from '../../../../../../config/constants'
1617
import IconCheck from '../../../../../../assets/icons/icon-check-thin.svg'
1718
import IconXMark from '../../../../../../assets/icons/icon-x-mark-thin.svg'
1819
import IconPencil from '../../../../../../assets/icons/icon-ui-pencil.svg'
19-
2020
import IconDots from '../../../../../../assets/icons/icon-dots.svg'
21+
import IconArrowDown from '../../../../../../assets/icons/arrow-6px-carret-down-normal.svg'
2122

2223
import styles from './MilestoneRow.scss'
2324

@@ -47,14 +48,13 @@ function MilestoneRow({
4748
copilots = copilots.concat(missingCopilots)
4849
}
4950

50-
5151
let milestoneRef
5252
let startDateRef
5353
let endDateRef
5454
let budgetRef
5555

5656
return edit ? (
57-
<tr styleName="milestone-row">
57+
<tr styleName="milestone-row" className="edit-milestone-row">
5858
<td styleName="checkbox">
5959
<TCFormFields.Checkbox
6060
name={`select-${rowId}`}
@@ -69,10 +69,13 @@ function MilestoneRow({
6969
validations={{
7070
isRequired: true,
7171
checkDuplicatedTitles(values) {
72+
if (!milestone.editting) {
73+
return true
74+
}
7275
const existingTitles = allMilestones
7376
.filter(i => i.id !== milestone.id)
74-
.map(i => i.name.toLowerCase())
75-
const inputtingTitle = values[`title-${rowId}`].toLowerCase()
77+
.map(i => i.name.toLowerCase().trim())
78+
const inputtingTitle = values[`title-${rowId}`].toLowerCase().trim()
7679
return existingTitles.indexOf(inputtingTitle) === -1
7780
}
7881
}}
@@ -89,10 +92,11 @@ function MilestoneRow({
8992
if (!milestone.origin) {
9093
milestone.origin = {...milestone }
9194
}
92-
onChange({...milestone, name: value })
95+
onChange({...milestone, name: value, editting: true, editted: true })
9396
}}
9497
wrapperClass={styles.textInput}
9598
innerRef={ref => milestoneRef = ref}
99+
isPristine={() => !milestone.editted}
96100
/>
97101
</td>
98102
<td styleName="description">
@@ -181,14 +185,28 @@ function MilestoneRow({
181185
}}
182186
value={phaseStatusOptions.find(option => option.value === milestone.status)}
183187
isSearchable={false}
188+
components={{
189+
DropdownIndicator: (props) => (
190+
<components.DropdownIndicator {...props}>
191+
<IconArrowDown />
192+
</components.DropdownIndicator>
193+
)
194+
}}
184195
/>
185196
</td>
186197
<td styleName="budget">
198+
<span styleName="prefix-icon" className="milestone-budget-prefix-icon">$</span>
187199
<TCFormFields.TextInput
188200
validations={{
189201
isRequired: true,
202+
isPositive(values) {
203+
return !(values[`budget-${rowId}`] < 0)
204+
}
190205
}}
191206
validationError={'Please, enter budget'}
207+
validationErrors={{
208+
isPositive: 'Budget cannot be negative'
209+
}}
192210
required
193211
type="number"
194212
name={`budget-${rowId}`}
@@ -233,6 +251,8 @@ function MilestoneRow({
233251
className="tc-btn tc-btn-link"
234252
styleName="icon-button"
235253
onClick={() => {
254+
milestone.editted = true
255+
milestone.editting = true
236256
if (milestoneRef.props.isValid()
237257
&& startDateRef.props.isValid()
238258
&& endDateRef.props.isValid()
@@ -272,18 +292,30 @@ function MilestoneRow({
272292
}}
273293
/>
274294
</td>
275-
<td styleName="milestone">{milestone.name}</td>
276-
<td styleName="description">{milestone.description}</td>
277-
<td styleName="start-date">{moment(milestone.startDate).format('MM-DD-YYYY')}</td>
278-
<td styleName="end-date">{moment(milestone.endDate).format('MM-DD-YYYY')}</td>
279-
<td styleName="status"><MilestoneStatus status={milestone.status} /></td>
280-
<td styleName="budget"><MilestoneBudget spent={milestone.spentBudget} budget={milestone.budget} /></td>
295+
<td styleName="milestone">
296+
{milestone.name}
297+
</td>
298+
<td styleName="description">
299+
{milestone.description}
300+
</td>
301+
<td styleName="start-date">
302+
{moment(milestone.startDate).format('MM-DD-YYYY')}
303+
</td>
304+
<td styleName="end-date">
305+
{moment(milestone.endDate).format('MM-DD-YYYY')}
306+
</td>
307+
<td styleName="status">
308+
<MilestoneStatus status={milestone.status} />
309+
</td>
310+
<td styleName="budget">
311+
<MilestoneBudget spent={milestone.spentBudget} budget={milestone.budget} />
312+
</td>
281313
{/* <td styleName="copilots">
282314
<MilestoneCopilots copilots={copilots} />
283315
</td> */}
284-
<td styleName="action">
285-
<div styleName="inline-menu">
286-
{isUpdatable && (
316+
{isUpdatable && (
317+
<td styleName="action">
318+
<div styleName="inline-menu">
287319
<button
288320
type="button"
289321
className="tc-btn tc-btn-link"
@@ -294,19 +326,17 @@ function MilestoneRow({
294326
>
295327
<IconPencil />
296328
</button>
297-
)}
298-
{isUpdatable && (
299329
<MilestoneDeleteButton
300330
onDelete={() => {
301331
onRemove(milestone.id)
302332
}}
303333
/>
304-
)}
305-
<button type="button" className="tc-btn tc-btn-link" styleName="icon-button">
306-
<IconDots />
307-
</button>
308-
</div>
309-
</td>
334+
<button type="button" className="tc-btn tc-btn-link" styleName="icon-button">
335+
<IconDots />
336+
</button>
337+
</div>
338+
</td>
339+
)}
310340
</tr>
311341
)
312342
}

0 commit comments

Comments
 (0)