Skip to content

Commit bc9ff21

Browse files
author
Parth Shah
committed
fixes #376, fixes #457
1 parent 587c7e0 commit bc9ff21

File tree

17 files changed

+296
-142
lines changed

17 files changed

+296
-142
lines changed

src/api/messages.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ export function getTopicPosts(topicId, postIds) {
2828
.then( resp => {
2929
return {
3030
totalCount: _.get(resp.data, 'result.metadata.totalCount', 0),
31-
posts: _.get(resp.data, 'result.content', [])
31+
posts: _.get(resp.data, 'result.content', []),
32+
topicId
3233
}
3334
})
3435
}

src/components/Feed/FeedComments.jsx

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import Panel from '../Panel/Panel'
44
import AddComment from '../ActionCard/AddComment'
55
import Comment from '../ActionCard/Comment'
66
import cn from 'classnames'
7-
import { THREAD_MESSAGES_PAGE_SIZE } from '../../config/constants'
7+
// import { THREAD_MESSAGES_PAGE_SIZE } from '../../config/constants'
88

99
const getCommentCount = (totalComments) => {
1010
if (!totalComments) {
@@ -24,7 +24,7 @@ class FeedComments extends React.Component {
2424

2525
render() {
2626
const {
27-
comments, currentUser, totalComments, /*onLoadMoreComments,*/ isLoadingComments, hasMoreComments, onAdd,
27+
comments, currentUser, totalComments, onLoadMoreComments, isLoadingComments, hasMoreComments, onAdd,
2828
onChange, content, avatarUrl, isAddingComment
2929
} = this.props
3030
let authorName = currentUser.firstName
@@ -35,17 +35,17 @@ class FeedComments extends React.Component {
3535
this.setState({showAll: true})
3636
// TODO - handle the case when a topic has more than 20 comments
3737
// since those will have to retrieved from the server
38-
// if (!isLoadingComments) {
39-
// onLoadMoreComments()
40-
// }
38+
if (!isLoadingComments) {
39+
onLoadMoreComments()
40+
}
4141
}
4242

43-
let _comments = comments
44-
let _hasMoreComments = hasMoreComments
45-
if (!this.state.showAll && _comments.length > THREAD_MESSAGES_PAGE_SIZE) {
46-
_comments = _comments.slice(-THREAD_MESSAGES_PAGE_SIZE)
47-
_hasMoreComments = true
48-
}
43+
// let _comments = comments
44+
// let _hasMoreComments = hasMoreComments
45+
// if (!this.state.showAll && _comments.length > THREAD_MESSAGES_PAGE_SIZE) {
46+
// _comments = _comments.slice(-THREAD_MESSAGES_PAGE_SIZE)
47+
// _hasMoreComments = true
48+
// }
4949

5050
return (
5151
<div>
@@ -57,15 +57,15 @@ class FeedComments extends React.Component {
5757
{getCommentCount(totalComments)}
5858
</div>
5959
<hr className={cn({'no-margin': !comments.length})} />
60-
{_hasMoreComments && <div className={cn('comment-collapse', {'loading-comments': isLoadingComments})}>
60+
{hasMoreComments && <div className={cn('comment-collapse', {'loading-comments': isLoadingComments})}>
6161
<a href="javascript:" onClick={ handleLoadMoreClick } className="comment-collapse-button">
6262
{isLoadingComments ? 'Loading...' : 'View older comments'}
6363
</a>
6464
</div>}
6565
</div>
6666
</div>
6767
</Panel.Body>
68-
{_comments.map((item, idx) =>
68+
{comments.map((item, idx) =>
6969
<Comment
7070
key={idx}
7171
avatarUrl={item.author.photoURL}

src/components/Feed/NewPost.jsx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,14 @@ class NewPost extends React.Component {
5858
document.removeEventListener('click', this.onClickOutside)
5959
}
6060

61+
componentWillReceiveProps(nextProps) {
62+
if (!(nextProps.isCreating || nextProps.hasError && !nextProps.isCreating)) {
63+
this.setState({editorState: EditorState.createEmpty()})
64+
this.refs.title.value = ''
65+
}
66+
this.onNewPostChange()
67+
}
68+
6169
onClickOutside(evt) {
6270
let currNode = evt.target
6371
let isEditor = false
@@ -150,8 +158,8 @@ class NewPost extends React.Component {
150158
const content = stateToMarkdown(editorState.getCurrentContent())
151159
if (title && content) {
152160
this.props.onPost({title, content})
153-
this.setState({editorState: EditorState.createEmpty()})
154-
this.refs.title.value = ''
161+
// this.setState({editorState: EditorState.createEmpty()})
162+
// this.refs.title.value = ''
155163
}
156164
}
157165

src/components/MessageDetails/MessageDetails.jsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ class MessageDetails extends React.Component {
3636
isLoadingComments,
3737
currentUser,
3838
isAddingComment,
39+
error,
3940
allowAddingComment} = this.props
4041
let authorName = currentUser.firstName
4142
if (authorName && currentUser.lastName) {
@@ -71,6 +72,7 @@ class MessageDetails extends React.Component {
7172
<AddComment
7273
className="messaging-comment-section"
7374
isAdding={isAddingComment}
75+
hasError={error}
7476
avatarUrl={currentUser.photoURL}
7577
authorName={ authorName }
7678
onAdd={onAddNewMessage}

src/components/ProjectProgress/ProjectProgress.jsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ const ProjectProgress = ({title, type, percent, children }) => (
2222
ProjectProgress.defaultProps = {
2323
type: 'completed'
2424
}
25+
2526
ProjectProgress.propTypes = {
2627
title: PropTypes.string.isRequired,
2728
type: PropTypes.oneOf(['working', 'error', 'completed']),

src/components/TopBar/TopBarContainer.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ import TopBar from './TopBar'
88
import CreateView from '../../projects/create/components/CreateView'
99
import { TCEmitter } from '../../helpers'
1010
import {
11+
DOMAIN,
1112
ROLE_CONNECT_COPILOT,
1213
ROLE_CONNECT_MANAGER,
1314
ROLE_ADMINISTRATOR,
1415
EVENT_ROUTE_CHANGE,
15-
ACCOUNTS_APP_LOGIN_URL,
1616
ACCOUNTS_APP_REGISTER_URL
1717
} from '../../config/constants'
1818

@@ -97,7 +97,8 @@ class TopBarContainer extends React.Component {
9797
const {isCreatingProject, currentPath, isFilterVisible } = this.state
9898
const isProjectDetails = /projects\/\d+/.test(currentPath)
9999
const isHomePage = this.context.router.isActive('/', true)
100-
const loginUrl = ACCOUNTS_APP_LOGIN_URL
100+
// NOTE: hardcoding to connectv2, once connect v1
101+
const loginUrl = `ACCOUNTS_APP_LOGIN_URL?retUrl=https://connectv2.${DOMAIN}/`
101102
const registerUrl = !isHomePage ? ACCOUNTS_APP_REGISTER_URL : null
102103
return (
103104
<div>

src/projects/detail/containers/Specification.jsx renamed to src/config/projectQuestions/topcoder.v1.js

Lines changed: 1 addition & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,6 @@
1-
'use strict'
2-
3-
import React, { Component, PropTypes } from 'react'
4-
import { connect } from 'react-redux'
51
import _ from 'lodash'
6-
import Sticky from 'react-stickynode'
7-
8-
import ProjectSpecSidebar from '../components/ProjectSpecSidebar'
9-
import FooterV2 from '../../../components/FooterV2/FooterV2'
10-
import EditProjectForm from '../components/EditProjectForm'
11-
import { updateProject } from '../../actions/project'
12-
import spinnerWhileLoading from '../../../components/LoadingSpinner'
132
import { Icons } from 'appirio-tech-react-components'
143

15-
16-
require('./Specification.scss')
17-
184
const isFileRequired = (project, subSections) => {
195
const subSection = _.find(subSections, (s) => s.type === 'questions')
206
const fields = _.filter(subSection.questions, q => q.type.indexOf('see-attached') > -1)
@@ -199,69 +185,4 @@ const sections = [
199185
}
200186
]
201187

202-
// This handles showing a spinner while the state is being loaded async
203-
const enhance = spinnerWhileLoading(props => !props.processing)
204-
const EnhancedEditProjectForm = enhance(EditProjectForm)
205-
206-
class ProjectSpecification extends Component {
207-
constructor(props) {
208-
super(props)
209-
this.saveProject = this.saveProject.bind(this)
210-
}
211-
212-
saveProject(model) {
213-
// compare old & new
214-
this.props.updateProject(this.props.project.id, model)
215-
}
216-
217-
render() {
218-
const { project, currentMemberRole } = this.props
219-
220-
return (
221-
<section className="two-col-content content">
222-
<div className="container">
223-
<div className="left-area">
224-
<Sticky top={80}>
225-
<ProjectSpecSidebar project={project} sections={sections} currentMemberRole={currentMemberRole} />
226-
<FooterV2 />
227-
</Sticky>
228-
</div>
229-
230-
<div className="right-area">
231-
<EnhancedEditProjectForm
232-
project={project}
233-
sections={sections}
234-
isEdittable={!!currentMemberRole}
235-
submitHandler={this.saveProject}
236-
/>
237-
</div>
238-
239-
</div>
240-
</section>
241-
)
242-
}
243-
}
244-
245-
ProjectSpecification.propTypes = {
246-
project: PropTypes.object.isRequired,
247-
currentMemberRole: PropTypes.string,
248-
processing: PropTypes.bool,
249-
error: PropTypes.oneOfType([
250-
PropTypes.bool,
251-
PropTypes.object
252-
])
253-
}
254-
255-
const mapStateToProps = ({projectState, loadUser}) => {
256-
return {
257-
processing: projectState.processing,
258-
error: projectState.error,
259-
currentUserId: parseInt(loadUser.user.id)
260-
}
261-
}
262-
263-
const mapDispatchToProps = { updateProject }
264-
265-
ProjectSpecification.sections = sections
266-
267-
export default connect(mapStateToProps, mapDispatchToProps)(ProjectSpecification)
188+
export default sections

src/projects/actions/projectTopics.js

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,40 @@ export function laodProjectMessages(projectId) {
4141

4242
// ignore action param
4343
/*eslint-disable no-unused-vars */
44+
45+
const getTopicsWithComments = (projectId, tag) => {
46+
return getTopics({ reference : 'project', referenceId: projectId, tag })
47+
.then(({topics, totalCount}) => {
48+
const additionalPosts = []
49+
// if a topic has more than 20 posts then to display the latest posts,
50+
// we'll have to first retrieve them from the server
51+
_.forEach(topics, (t) => {
52+
if (t.postIds.length > 20) {
53+
const postIds = t.postIds.slice(20).slice(-6)
54+
additionalPosts.push(getTopicPosts(t.id, postIds))
55+
}
56+
t.posts = _.sortBy(t.posts, ['id'])
57+
})
58+
if (additionalPosts.length === 0) {
59+
// we dont need to retrieve any additional posts
60+
return { topics, totalCount }
61+
}
62+
return Promise.all(additionalPosts)
63+
.then(posts => {
64+
_.forEach(posts, (p) => {
65+
const topic = _.find(topics, p.topicId)
66+
topic.posts = _.sortBy(topic.posts.concat(p.posts), ['id'])
67+
})
68+
return { topics, totalCount }
69+
})
70+
71+
})
72+
}
4473
const getProjectTopicsWithMember = (dispatch, projectId, tag) => {
4574
return new Promise((resolve, reject) => {
4675
return dispatch({
4776
type: LOAD_PROJECT_FEEDS,
48-
payload: getTopics({ reference : 'project', referenceId: projectId, tag }),
77+
payload: getTopicsWithComments(projectId, tag),
4978
meta: { tag, projectId }
5079
})
5180
.then(({ value, action }) => {

src/projects/detail/components/EditProjectForm.jsx

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ class EditProjectForm extends Component {
2222

2323
componentWillMount() {
2424
this.setState({
25+
isProjectDirty: false,
2526
isFeaturesDirty: false,
2627
project: Object.assign({}, this.props.project),
2728
canSubmit: false,
@@ -30,10 +31,14 @@ class EditProjectForm extends Component {
3031
}
3132

3233
componentWillReceiveProps(nextProps) {
34+
let updatedProject = Object.assign({}, nextProps.project)
35+
if (this.state.isFeaturesDirty && !this.state.isSaving) {
36+
updatedProject = update(updatedProject, {details: { appDefinition: { features: { $set: this.state.project.details.appDefinition.features } } } })
37+
}
3338
this.setState({
34-
project: Object.assign({}, nextProps.project),
35-
canSubmit: false,
36-
isFeaturesDirty: false
39+
project: updatedProject,
40+
canSubmit: this.state.isFeaturesDirty,
41+
isSaving: false
3742
})
3843
}
3944

@@ -79,6 +84,7 @@ class EditProjectForm extends Component {
7984
if (this.state.isFeaturesDirty) {
8085
model.details.appDefinition.features = this.state.project.details.appDefinition.features
8186
}
87+
this.setState({isSaving: true })
8288
this.props.submitHandler(model)
8389
}
8490

@@ -134,6 +140,7 @@ class EditProjectForm extends Component {
134140

135141
EditProjectForm.propTypes = {
136142
project: PropTypes.object.isRequired,
143+
saving: PropTypes.bool.isRequired,
137144
sections: PropTypes.arrayOf(PropTypes.object).isRequired,
138145
isEdittable: PropTypes.bool.isRequired,
139146
submitHandler: PropTypes.func.isRequired

src/projects/detail/components/ProjectSpecSidebar.jsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import _ from 'lodash'
22
import React, { PropTypes, Component } from 'react'
33
import { connect } from 'react-redux'
4+
import update from 'react-addons-update'
45
import SidebarNav from './SidebarNav'
56
import { PROJECT_ROLE_OWNER, PROJECT_ROLE_CUSTOMER } from '../../../config/constants'
67
import { updateProject } from '../../actions/project'
@@ -86,6 +87,7 @@ class ProjectSpecSidebar extends Component {
8687
_.indexOf([PROJECT_ROLE_OWNER, PROJECT_ROLE_CUSTOMER], currentMemberRole) > -1
8788
return (
8889
<div className="projectSpecSidebar">
90+
<button onClick={() => this.props.updateProject(project.id, update(project, { details: { appDefinition: { goal: { value: { $apply: (x) => { return parseInt(x) + 1}}}}}}))} className="btn btn-primary">Test Save</button>
8991
<h4 className="titles gray-font">Specifications</h4>
9092
<div className="list-group">
9193
<SidebarNav items={navItems} />

0 commit comments

Comments
 (0)