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
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ workflows:
- build-dev
filters: &filters-dev
branches:
only: ['dev', 'feature/copilot-feedback']
only: ['dev', 'feature/new-milestone-concept']

- deployTest01:
context : org-global
Expand Down
3 changes: 3 additions & 0 deletions src/assets/icons/icon-check-thin.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions src/assets/icons/icon-dots.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions src/assets/icons/icon-gnatt-gray.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions src/assets/icons/icon-x-mark-thin.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions src/assets/icons/x-mark-thin.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions src/components/Layout/Layout.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const Layout = (props) => {
</div>
<Footer />
<GatewayDest name="fullscreen-page" className="mobile-page-gateway" />
<GatewayDest name="right-sidebar" className="right-sidebar-container" />
</div>
)
}
Expand Down
31 changes: 31 additions & 0 deletions src/components/Layout/Layout.scss
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,35 @@
background-color: $tc-gray-neutral-light;
}
}

.right-sidebar-container {
position: fixed;
top: 0;
bottom: 0;
right: 0;
width: 310px;
z-index: 9999;
transform: translateX(310px);
transition: transform 225ms ease;

&:not(:empty) {
transform: translateX(0);

&::before {
content: '';
position: absolute;
top: -100vh;
left: -100vw;
width: 200vw;
height: 200vh;
z-index: -1;
}

@media screen and (max-width: $screen-md - 1px) {
width: 100%;
transition: none;
}
}
}
}

7 changes: 3 additions & 4 deletions src/components/ProjectProgress/ProjectProgress.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const Themes = {

const ProjectProgress = ({type, percent, children, viewType=ViewTypes.HBAR }) => (
<div className="project-progress">
{ viewType === ViewTypes.HBAR &&
{ viewType === ViewTypes.HBAR &&
<div className="progress-bar">
<div className={cn('progress', type)} style={{width: percent + '%'}} />
</div>
Expand All @@ -35,14 +35,13 @@ ProjectProgress.ViewTypes = ViewTypes
ProjectProgress.Themes = Themes

ProjectProgress.defaultProps = {
type: Themes.BLUE
type: Themes.BLUE
}

ProjectProgress.propTypes = {
title: PropTypes.string.isRequired,
type: PropTypes.oneOf(_.values(Themes)),
percent: PropTypes.number.isRequired,
children: PropTypes.any.isRequired
children: PropTypes.any
}

export default ProjectProgress
2 changes: 1 addition & 1 deletion src/components/TwoColsLayout/TwoColsLayout.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ TwoColsLayout.Sidebar = ({ children, wrapperClass }) => (

TwoColsLayout.Content = ({ children }) => (
<div styleName="content">
<div styleName="content-inner">
<div styleName="content-inner" className="twoColsLayout-contentInner">
{children}
</div>
</div>
Expand Down
9 changes: 9 additions & 0 deletions src/components/User/UserTooltip.scss
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,15 @@
}
}

&.size-50 {
.tooltip-target {
.Avatar {
height: 50px;
width: 50px;
}
}
}

.stack-avatar-0 {
z-index: 3;
}
Expand Down
12 changes: 11 additions & 1 deletion src/config/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -632,6 +632,16 @@ export const PHASE_STATUS = [
// {color: 'red', name: 'Paused', fullName: 'Phase is paused', value: PHASE_STATUS_PAUSED, order: 7, dropDownOrder: 7 }
]

export const PHASE_STATUS_OPTIONS = [
{ label: 'Draft', value: PHASE_STATUS_DRAFT },
{ label: 'In Review', value: PHASE_STATUS_IN_REVIEW },
{ label: 'Reviewed', value: PHASE_STATUS_REVIEWED },
{ label: 'Active', value: PHASE_STATUS_ACTIVE },
{ label: 'Completed', value: PHASE_STATUS_COMPLETED },
{ label: 'Cancelled', value: PHASE_STATUS_CANCELLED },
{ label: 'Phased', value: PHASE_STATUS_PAUSED },
]

// this defines default criteria to filter projects for projects list
export const PROJECT_LIST_DEFAULT_CRITERIA = {
sort: 'lastActivityAt desc'
Expand Down Expand Up @@ -1228,4 +1238,4 @@ export const DEFAULT_NDA_UUID = process.env.DEFAULT_NDA_UUID
/**
* The minimal duration of a TaaS Job in weeks
*/
export const TAAS_MIN_JOB_DURATION = 4
export const TAAS_MIN_JOB_DURATION = 4
111 changes: 58 additions & 53 deletions src/projects/actions/project.js
Original file line number Diff line number Diff line change
Expand Up @@ -286,12 +286,14 @@ function createProductsTimelineAndMilestone(project) {
*
* @return {Promise} project
*/
export function createProjectPhaseAndProduct(project, productTemplate, status = PHASE_STATUS_DRAFT, startDate, endDate, createTimeline = true) {
export function createProjectPhaseAndProduct(project, productTemplate, status = PHASE_STATUS_DRAFT, startDate, endDate, createTimeline = true, budget, details) {
const param = {
status,
name: productTemplate.name,
description: productTemplate.description,
productTemplateId: productTemplate.id
productTemplateId: productTemplate.id,
budget,
details,
}
if (startDate) {
param['startDate'] = startDate.format('YYYY-MM-DD')
Expand Down Expand Up @@ -356,12 +358,12 @@ function createPhaseAndMilestonesRequest(project, productTemplate, status = PHAS
* @param {*} startDate
* @param {*} endDate
*/
export function createPhaseWithoutTimeline(project, productTemplate, status, startDate, endDate) {
export function createPhaseWithoutTimeline(project, productTemplate, status, startDate, endDate, budget, details) {
return (dispatch) => {
console.log(CREATE_PROJECT_PHASE)
return dispatch({
type: CREATE_PROJECT_PHASE,
payload: createProjectPhaseAndProduct(project, productTemplate, status, startDate, endDate, false)
payload: createProjectPhaseAndProduct(project, productTemplate, status, startDate, endDate, false, budget, details)
})
}
}
Expand Down Expand Up @@ -505,75 +507,78 @@ export function updatePhase(projectId, phaseId, updatedProps, phaseIndex) {
updatedProps.endDate = moment(updatedProps.endDate).format('YYYY-MM-DD')
}

let result
return dispatch({
type: UPDATE_PHASE,
payload: updatePhaseAPI(projectId, phaseId, updatedProps, phaseIndex).then()
}).then(() => {
})
.then(res => result = res)
.then(() => {
// finds active milestone, if exists in timeline
const activeMilestone = timeline ? _.find(timeline.milestones, m => m.status === PHASE_STATUS_ACTIVE) : null
// this will be done after updating timeline (if timeline update is required)
// or immediately if timeline update is not required
// update product milestone strictly after updating timeline
// otherwise it could happened like this:
// - send request to update timeline
// - send request to update milestone
// - get updated milestone
// - get updated timeline (without updated milestone)
// so otherwise we can end up with the timeline without updated milestone
const optionallyUpdateFirstMilestone = () => {
const activeMilestone = timeline ? _.find(timeline.milestones, m => m.status === PHASE_STATUS_ACTIVE) : null
// this will be done after updating timeline (if timeline update is required)
// or immediately if timeline update is not required
// update product milestone strictly after updating timeline
// otherwise it could happened like this:
// - send request to update timeline
// - send request to update milestone
// - get updated milestone
// - get updated timeline (without updated milestone)
// so otherwise we can end up with the timeline without updated milestone
const optionallyUpdateFirstMilestone = () => {
// update first product milestone only if
// - there is a milestone, obviously
// - phase's status is changed
// - phase's status is changed to active
// - there is not active milestone alreay (this can happen when phase is made active more than once
// e.g. Active => Paused => Active)
if (projectVersion !== 'v4' && timeline && !activeMilestone && phaseActivated ) {
if (projectVersion !== 'v4' && timeline && !activeMilestone && phaseActivated ) {
dispatch(
updateProductMilestone(
productId,
timeline.id,
timeline.milestones[0].id,
{status:MILESTONE_STATUS.ACTIVE}
)
)
}
}

if (timeline && (startDateChanged || phaseActivated)) {
dispatch(
updateProductMilestone(
updateProductTimeline(
productId,
timeline.id,
timeline.milestones[0].id,
{status:MILESTONE_STATUS.ACTIVE}
{
name: timeline.name,
startDate: updatedProps.startDate,
reference: timeline.reference,
referenceId: timeline.referenceId,
}
)
)
).then(optionallyUpdateFirstMilestone)
} else {
optionallyUpdateFirstMilestone()
}
}

if (timeline && (startDateChanged || phaseActivated)) {
dispatch(
updateProductTimeline(
productId,
timeline.id,
{
name: timeline.name,
startDate: updatedProps.startDate,
reference: timeline.reference,
referenceId: timeline.referenceId,
}
)
).then(optionallyUpdateFirstMilestone)
} else {
optionallyUpdateFirstMilestone()
}

// update project caused by phase updates
}).then(() => {
const project = state.projectState.project
// update project caused by phase updates
}).then(() => {
const project = state.projectState.project

// if one phase moved to ACTIVE status, make project ACTIVE too
if (
_.includes([PROJECT_STATUS_DRAFT, PROJECT_STATUS_IN_REVIEW, PROJECT_STATUS_REVIEWED], project.status) &&
// if one phase moved to ACTIVE status, make project ACTIVE too
if (
_.includes([PROJECT_STATUS_DRAFT, PROJECT_STATUS_IN_REVIEW, PROJECT_STATUS_REVIEWED], project.status) &&
phase.status !== PHASE_STATUS_ACTIVE &&
updatedProps.status === PHASE_STATUS_ACTIVE &&
hasPermission(PERMISSIONS.EDIT_PROJECT_STATUS)
) {
dispatch(
updateProject(projectId, {
status: PROJECT_STATUS_ACTIVE
}, true)
)
}
})
) {
dispatch(
updateProject(projectId, {
status: PROJECT_STATUS_ACTIVE
}, true)
)
}
}).then(() => result)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ class CreatePhaseForm extends React.Component {
const {
milestones
} = this.state

const ms = _.map(milestones, (m, index) => {
return (
<div styleName="milestone-item" key={m.pseudoId}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,15 @@ import { hasPermission } from '../../../../helpers/permissions'

import './ProjectPlanEmpty.scss'

const ProjectPlanEmpty = () => {
const ProjectPlanEmpty = ({ version }) => {
return hasPermission(PERMISSIONS.MANAGE_PROJECT_PLAN) ? (
<div styleName="container">
<h2>Build Your Project Plan</h2>
<p>Build your project plan in Connect to reflect delivery progress to the customer. Begin by clicking the "Add Phase" button, select the template that best matches your need, and modify the phase title and milestone dates prior to publishing to the customer.</p>
{version === 'v4' ? (
<p>Build your project plan in Connect to reflect delivery progress to the customer. Begin by clicking the "Add Milestone" button, and modify the milestone attributes prior to publishing to the customer.</p>
) : (
<p>Build your project plan in Connect to reflect delivery progress to the customer. Begin by clicking the "Add Phase" button, select the template that best matches your need, and modify the phase title and milestone dates prior to publishing to the customer.</p>
)}
<p><b>Important Note:</b> To move the project into <i>'Active'</i> status, you must set at least one phase in Connect's Project Plan to be in 'Planned' status, which signifies to customers that delivery planning and execution has begun.</p>
<p>If you feel like you have more things to send over, or want to reach out to us, please drop us a line at support@topcoder.com. Thanks!</p>
</div>
Expand Down
Loading