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
4 changes: 4 additions & 0 deletions src/config/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,10 @@ export const DELETE_PHASE_FEED_COMMENT_PENDING = 'DELETE_PHASE_FEED_COMMENT_PEN
export const DELETE_PHASE_FEED_COMMENT_SUCCESS = 'DELETE_PHASE_FEED_COMMENT_SUCCESS'
export const DELETE_PHASE_FEED_COMMENT_FAILURE = 'DELETE_PHASE_FEED_COMMENT_FAILURE'

export const EXPAND_PROJECT_PHASE = 'EXPAND_PROJECT_PHASE'
export const COLLAPSE_PROJECT_PHASE = 'COLLAPSE_PROJECT_PHASE'
export const COLLAPSE_ALL_PROJECT_PHASES = 'COLLAPSE_ALL_PROJECT_PHASES'

// Project Sort
export const PROJECT_SORT = 'PROJECT_SORT'
export const PROJECT_SORT_FAILURE = 'PROJECT_SORT_FAILURE'
Expand Down
49 changes: 46 additions & 3 deletions src/projects/actions/project.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,56 @@ import {
PROJECT_STATUS_IN_REVIEW,
PHASE_STATUS_REVIEWED,
PROJECT_STATUS_REVIEWED,
PROJECT_STATUS_ACTIVE
PROJECT_STATUS_ACTIVE,
EXPAND_PROJECT_PHASE,
COLLAPSE_PROJECT_PHASE,
COLLAPSE_ALL_PROJECT_PHASES,
} from '../../config/constants'
import {
updateProductMilestone,
updateProductTimeline
} from './productsTimelines'

/**
* Expand phase and optionaly expand particular tab
*
* @param {Number} phaseId phase id
* @param {String} tab (optional) tab id
*/
export function expandProjectPhase(phaseId, tab) {
return (dispatch) => {
return dispatch({
type: EXPAND_PROJECT_PHASE,
payload: { phaseId, tab }
})
}
}

/**
* Collapse phase
*
* @param {Number} phaseId phase id
*/
export function collapseProjectPhase(phaseId) {
return (dispatch) => {
return dispatch({
type: COLLAPSE_PROJECT_PHASE,
payload: { phaseId }
})
}
}

/**
* Collapse all phases and reset tabs to default
*/
export function collapseAllProjectPhases() {
return (dispatch) => {
return dispatch({
type: COLLAPSE_ALL_PROJECT_PHASES,
})
}
}

export function loadProject(projectId) {
return (dispatch) => {
return dispatch({
Expand Down Expand Up @@ -446,7 +489,7 @@ export function updatePhase(projectId, phaseId, updatedProps, phaseIndex) {

// if one phase moved to REVIEWED status, make project IN_REVIEW too
if (
_.includes([PROJECT_STATUS_DRAFT], project.status) &&
_.includes([PROJECT_STATUS_DRAFT], project.status) &&
phase.status !== PHASE_STATUS_REVIEWED &&
updatedProps.status === PHASE_STATUS_REVIEWED
) {
Expand All @@ -459,7 +502,7 @@ export function updatePhase(projectId, phaseId, updatedProps, phaseIndex) {

// 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) &&
_.includes([PROJECT_STATUS_DRAFT, PROJECT_STATUS_IN_REVIEW, PROJECT_STATUS_REVIEWED], project.status) &&
phase.status !== PHASE_STATUS_ACTIVE &&
updatedProps.status === PHASE_STATUS_ACTIVE
) {
Expand Down
7 changes: 6 additions & 1 deletion src/projects/detail/ProjectDetail.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { connect } from 'react-redux'
import _ from 'lodash'
import { renderComponent, branch, compose, withProps } from 'recompose'
import { loadProjectDashboard } from '../actions/projectDashboard'
import { clearLoadedProject } from '../actions/project'
import {
LOAD_PROJECT_FAILURE, PROJECT_ROLE_CUSTOMER, PROJECT_ROLE_OWNER,
ROLE_ADMINISTRATOR, ROLE_CONNECT_ADMIN, ROLE_CONNECT_COPILOT, ROLE_CONNECT_MANAGER
Expand Down Expand Up @@ -77,6 +78,10 @@ class ProjectDetail extends Component {
this.props.loadProjectDashboard(projectId)
}

componentWillUnmount() {
this.props.clearLoadedProject()
}

componentWillReceiveProps({isProcessing, isLoading, error, project, match}) {
// handle just deleted projects
if (! (error || isLoading || isProcessing) && _.isEmpty(project))
Expand Down Expand Up @@ -138,7 +143,7 @@ const mapStateToProps = ({projectState, projectDashboard, loadUser, productsTime
}
}

const mapDispatchToProps = { loadProjectDashboard }
const mapDispatchToProps = { loadProjectDashboard, clearLoadedProject }

ProjectDetail.propTypes = {
project: PropTypes.object,
Expand Down
72 changes: 36 additions & 36 deletions src/projects/detail/components/PhaseCard/PhaseCard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,7 @@ class PhaseCard extends React.Component {
this.onClose = this.onClose.bind(this)

this.state = {
isExpanded: '',
isEditting: false,
isDetailView: false
}
}

Expand All @@ -56,11 +54,11 @@ class PhaseCard extends React.Component {
}

toggleCardView() {
this.setState({
isDetailView: true,
isExpanded: !this.state.isExpanded

})
if (this.props.isExpanded) {
this.props.collapseProjectPhase(this.props.phaseId)
} else {
this.props.expandProjectPhase(this.props.phaseId)
}
}

toggleEditView(e) {
Expand All @@ -71,10 +69,7 @@ class PhaseCard extends React.Component {
}

onClose(){
this.setState({
isDetailView: false,
isExpanded: false
})
this.props.collapseProjectPhase(this.props.phaseId)
}

render() {
Expand All @@ -86,6 +81,8 @@ class PhaseCard extends React.Component {
isUpdating,
timeline,
hasReadPosts,
phaseId,
isExpanded,
} = this.props
const progressInPercent = attr.progressInPercent || 0

Expand All @@ -99,12 +96,12 @@ class PhaseCard extends React.Component {
const hasUnseen = hasReadPosts

return (
<div styleName={'phase-card ' + (this.state.isExpanded ? ' expanded ' : ' ')}>
<div styleName={'phase-card ' + (isExpanded ? ' expanded ' : ' ')} id={`phase-${phaseId}`}>
{
<MediaQuery minWidth={SCREEN_BREAKPOINT_MD}>
{(matches) => (matches || !this.state.isDetailView ? (
{(matches) => (matches || !isExpanded ? (
<div>
<div styleName={cn('static-view', { 'has-unseen': hasUnseen && !this.state.isExpanded })} onClick={!this.state.isEditting && this.toggleCardView }>
<div styleName={cn('static-view', { 'has-unseen': hasUnseen && !isExpanded })} onClick={!this.state.isEditting && this.toggleCardView }>
<div styleName="col">
<div styleName="project-details">
<div styleName="project-ico">
Expand Down Expand Up @@ -191,26 +188,28 @@ class PhaseCard extends React.Component {
{!this.state.isEditting && (<div styleName="expandable-view">
{this.props.children}
</div>)}
{(<div styleName={'sm-separator ' + ((!isManageUser || !this.state.isEditting) ? 'hide ': '')} >
{!isUpdating && (
<EditStageForm
phase={attr.phase}
phaseIndex={attr.phaseIndex}
cancel={this.toggleEditView}
timeline={timeline}
/>
)}
{canDelete && !isUpdating && (
<DeletePhase
onDeleteClick={() => {
if (confirm(`Are you sure you want to delete phase '${attr.phase.name}'?`)) {
deleteProjectPhase()
}
}}
/>
)}
{isUpdating && <LoadingIndicator />}
</div>)}
{isManageUser && this.state.isEditting && (
<div styleName="sm-separator">
{!isUpdating && (
<EditStageForm
phase={attr.phase}
phaseIndex={attr.phaseIndex}
cancel={this.toggleEditView}
timeline={timeline}
/>
)}
{canDelete && !isUpdating && (
<DeletePhase
onDeleteClick={() => {
if (confirm(`Are you sure you want to delete phase '${attr.phase.name}'?`)) {
deleteProjectPhase()
}
}}
/>
)}
{isUpdating && <LoadingIndicator />}
</div>
)}
</div>
):(
<MobilePage>
Expand Down Expand Up @@ -248,14 +247,15 @@ PhaseCard.propTypes = {
attr: PT.shape({
duration: PT.string.isRequired,
icon: PT.string.isRequired,
isExpanded: PT.bool,
paidStatus: PT.string.isRequired,
posts: PT.string,
startEndDates: PT.string.isRequired,
status: PT.string.isRequired,
title: PT.string.isRequired,
hasReadPosts: PT.bool,
})
}),
phaseId: PT.number.isRequired,
isExpanded: PT.bool,
}


Expand Down
12 changes: 10 additions & 2 deletions src/projects/detail/components/PhaseCard/PhaseCard.scss
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,11 @@
display: flex;
align-items: center;
position: relative;
justify-content: space-between;
justify-content: flex-start;

@media screen and (max-width: $screen-md - 1px) {
justify-content: space-between;
}
}
.edit-btn {
width: 40px;
Expand All @@ -215,7 +219,11 @@
background-size: 15px;
cursor: pointer;
transition: 0.25s;
margin: auto auto auto 0;
flex: 0 0 40px;

@media screen and (max-width: $screen-md - 1px) {
margin-right: -30px;
}
}
.toggle-arrow {
position: absolute;
Expand Down
30 changes: 17 additions & 13 deletions src/projects/detail/components/ProjectStage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import React from 'react'
import PT from 'prop-types'
import _ from 'lodash'
import uncontrollable from 'uncontrollable'

import { formatNumberWithCommas } from '../../../helpers/format'
import { getPhaseActualData } from '../../../helpers/projectHelper'
Expand Down Expand Up @@ -93,6 +92,7 @@ class ProjectStage extends React.Component{
this.removeProductAttachment = this.removeProductAttachment.bind(this)
this.updateProductAttachment = this.updateProductAttachment.bind(this)
this.addProductAttachment = this.addProductAttachment.bind(this)
this.onTabClick = this.onTabClick.bind(this)
}

removeProductAttachment(attachmentId) {
Expand All @@ -116,9 +116,14 @@ class ProjectStage extends React.Component{
addProductAttachment(project.id, phase.id, product.id, attachment)
}

onTabClick(tab) {
const { expandProjectPhase, phase } = this.props

expandProjectPhase(phase.id, tab)
}

render() {
const {
activeTab,
phase,
phaseIndex,
project,
Expand All @@ -130,8 +135,10 @@ class ProjectStage extends React.Component{
updateProduct,
fireProductDirty,
fireProductDirtyUndo,
onTabClick,
deleteProjectPhase,
phaseState,
collapseProjectPhase,
expandProjectPhase,

// comes from phaseFeedHOC
currentUser,
Expand All @@ -156,7 +163,7 @@ class ProjectStage extends React.Component{

const hasTimeline = !!timeline
const defaultActiveTab = hasTimeline ? 'timeline' : 'posts'
const currentActiveTab = activeTab ? activeTab : defaultActiveTab
const currentActiveTab = _.get(phaseState, 'tab', defaultActiveTab)
const postNotifications = filterNotificationsByPosts(notifications, _.get(feed, 'posts', []))
const unreadPostNotifications = filterReadNotifications(postNotifications)
const hasReadPosts = unreadPostNotifications.length > 0
Expand All @@ -169,11 +176,15 @@ class ProjectStage extends React.Component{
deleteProjectPhase={() => deleteProjectPhase(project.id, phase.id)}
timeline={timeline}
hasReadPosts={hasReadPosts}
phaseId={phase.id}
isExpanded={_.get(phaseState, 'isExpanded')}
collapseProjectPhase={collapseProjectPhase}
expandProjectPhase={expandProjectPhase}
>
<div>
<ProjectStageTabs
activeTab={currentActiveTab}
onTabClick={onTabClick}
onTabClick={this.onTabClick}
isSuperUser={isSuperUser}
isManageUser={isManageUser}
hasTimeline={hasTimeline}
Expand Down Expand Up @@ -225,13 +236,10 @@ class ProjectStage extends React.Component{
}

ProjectStage.defaultProps = {
activeTab: '',
currentMemberRole: null,
}

ProjectStage.propTypes = {
activeTab: PT.string,
onTabClick: PT.func.isRequired,
project: PT.object.isRequired,
currentMemberRole: PT.string,
isProcessing: PT.bool.isRequired,
Expand All @@ -245,8 +253,4 @@ ProjectStage.propTypes = {
deleteProjectPhase: PT.func.isRequired,
}

const ProjectStageUncontrollable = uncontrollable(ProjectStage, {
activeTab: 'onTabClick',
})

export default phaseFeedHOC(ProjectStageUncontrollable)
export default phaseFeedHOC(ProjectStage)
6 changes: 6 additions & 0 deletions src/projects/detail/components/ProjectStages.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ function formatPhaseCardListFooterProps(phases, productsTimelines) {
const ProjectStages = ({
project,
phases,
phasesStates,
productTemplates,
productsTimelines,
currentMemberRole,
Expand All @@ -74,6 +75,8 @@ const ProjectStages = ({
removeProductAttachment,
isManageUser,
deleteProjectPhase,
expandProjectPhase,
collapseProjectPhase,
}) => (
<Section>

Expand All @@ -82,6 +85,7 @@ const ProjectStages = ({
phases.map((phase, index) => (
<ProjectStage
key={phase.id}
phaseState={phasesStates[phase.id]}
productTemplates={productTemplates}
currentMemberRole={currentMemberRole}
isProcessing={isProcessing}
Expand All @@ -97,6 +101,8 @@ const ProjectStages = ({
updateProductAttachment={updateProductAttachment}
removeProductAttachment={removeProductAttachment}
deleteProjectPhase={deleteProjectPhase}
expandProjectPhase={expandProjectPhase}
collapseProjectPhase={collapseProjectPhase}
/>
))
}
Expand Down
Loading