Skip to content

Commit c3f9ea2

Browse files
committed
refactored and fixed redirect old Topics and Post URLs to the new message tab
1 parent 67c9c30 commit c3f9ea2

File tree

3 files changed

+40
-55
lines changed

3 files changed

+40
-55
lines changed

src/projects/detail/containers/DashboardContainer.jsx

Lines changed: 1 addition & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import React from 'react'
88
import _ from 'lodash'
99
import { connect } from 'react-redux'
10-
import { Redirect, withRouter, Link } from 'react-router-dom'
10+
import { withRouter, Link } from 'react-router-dom'
1111
import Alert from 'react-s-alert'
1212
import './DashboardContainer.scss'
1313

@@ -70,14 +70,9 @@ class DashboardContainer extends React.Component {
7070

7171
this.state = {
7272
open: false,
73-
matchesTopicUrl: null,
74-
matchesPostUrl: null,
75-
topicIdForPost: null
7673
}
7774
this.onNotificationRead = this.onNotificationRead.bind(this)
7875
this.toggleDrawer = this.toggleDrawer.bind(this)
79-
80-
this.alertedFailedTopicRedirect = false
8176
}
8277

8378
onNotificationRead(notification) {
@@ -101,18 +96,6 @@ class DashboardContainer extends React.Component {
10196
})
10297
}
10398

104-
/*
105-
For redirecting old urls to new urls for topics and posts
106-
Old TOPIC: '/projects/{{projectId}}/#feed-{{topicId}}',
107-
Old POST: '/projects/{{projectId}}/#comment-{{postId}}',
108-
*/
109-
const matchesTopicUrl = location.hash.match(/#feed-(\d+)/)
110-
const matchesPostUrl = location.hash.match(/#comment-(\d+)/)
111-
this.setState({
112-
matchesPostUrl,
113-
matchesTopicUrl
114-
})
115-
11699
// if the user is a customer and its not a direct link to a particular phase
117100
// then by default expand all phases which are active
118101
if (_.isEmpty(location.hash) && this.props.isCustomerUser) {
@@ -130,40 +113,12 @@ class DashboardContainer extends React.Component {
130113
collapseAllProjectPhases()
131114
}
132115

133-
componentWillReceiveProps(nextProps) {
134-
const { isFeedsLoading } = nextProps
135-
const { matchesPostUrl } = this.state
136-
137-
// we need topicId for redirecting old post url (/projects/{{projectId}}/#comment-{{postId}})
138-
if (!isFeedsLoading && matchesPostUrl && !this.alertedFailedTopicRedirect) {
139-
const topicIdForPost = this.getTopicIdForPost(matchesPostUrl[1])
140-
this.setState({ topicIdForPost })
141-
this.alertFailedTopicRedirection(matchesPostUrl, topicIdForPost, isFeedsLoading)
142-
}
143-
}
144-
145116
toggleDrawer() {
146117
this.setState((prevState) => ({
147118
open: !prevState.open
148119
}))
149120
}
150121

151-
// Get topic id corresponding to the post that we're trying to redirect to
152-
getTopicIdForPost(postId) {
153-
const {feeds} = this.props
154-
const topic = feeds && feeds
155-
.find(feed => feed.posts.find(p => p.id === Number(postId)))
156-
return topic && topic.id
157-
}
158-
159-
// Alert user in case the post is not available / not accessible to him.
160-
alertFailedTopicRedirection(matchesPostUrl, topicIdForPost, isFeedsLoading) {
161-
if (matchesPostUrl && !topicIdForPost && !isFeedsLoading) {
162-
this.alertedFailedTopicRedirect = true
163-
Alert.error('Couldn\'t find the post')
164-
}
165-
}
166-
167122
render() {
168123
const {
169124
project,
@@ -191,9 +146,6 @@ class DashboardContainer extends React.Component {
191146
location,
192147
estimationQuestion,
193148
} = this.props
194-
const { matchesPostUrl, matchesTopicUrl, topicIdForPost } = this.state
195-
196-
197149
const projectTemplate = project && project.templateId && projectTemplates ? (getProjectTemplateById(projectTemplates, project.templateId)) : null
198150

199151
let template
@@ -254,9 +206,6 @@ class DashboardContainer extends React.Component {
254206
]}
255207
/>
256208

257-
{matchesTopicUrl && <Redirect to={`/projects/${project.id}/messages/${matchesTopicUrl[1]}`} />}
258-
{matchesPostUrl && topicIdForPost && <Redirect to={`/projects/${project.id}/messages/${topicIdForPost}#comment-${matchesPostUrl[1]}`} />}
259-
260209
<TwoColsLayout.Sidebar>
261210
<MediaQuery minWidth={SCREEN_BREAKPOINT_MD}>
262211
{(matches) => {

src/projects/detail/containers/MessagesTabContainer.jsx

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import React from 'react'
22
import { connect } from 'react-redux'
3-
import { Prompt } from 'react-router-dom'
3+
import { Prompt, withRouter } from 'react-router-dom'
4+
import Alert from 'react-s-alert'
45
import MediaQuery from 'react-responsive'
56
import {
67
groupBy,
@@ -189,6 +190,22 @@ class MessagesTabContainer extends React.Component {
189190
}
190191

191192
componentWillReceiveProps(nextProps) {
193+
// if we have URL like `/projects/{projectId}/messages#comment-{postId}` without mentioning topicId
194+
// then we should try to find topic of such post and redirect to the full URL with topicId
195+
const matchesPostUrl = this.props.match.path === '/projects/:projectId/messages' &&
196+
this.props.location.hash.match(/#comment-(\d+)/)
197+
// as soon as all topics are loaded we will redirect to the correct URL, if there such topic
198+
if (this.props.isFeedsLoading && !nextProps.isFeedsLoading && matchesPostUrl) {
199+
const postId = parseInt(matchesPostUrl[1], 10)
200+
const topic = nextProps.feeds.find(feed => _.find(feed.posts, { id: postId }))
201+
202+
if (topic) {
203+
this.props.history.replace(`/projects/${this.props.match.params.projectId}/messages/${topic.id}#comment-${postId}`)
204+
} else {
205+
Alert.error('Couldn\'t find the post referred in URL')
206+
}
207+
}
208+
192209
// reset title and content in the state after successful post creation
193210
// so that we treat the post editor not changed, thus when we leave the page we don't get confirmation alert
194211
if (this.props.isCreatingFeed && !nextProps.isCreatingFeed && !nextProps.error) {
@@ -421,4 +438,4 @@ const mapDispatchToProps = {
421438
export default connect(
422439
mapStateToProps,
423440
mapDispatchToProps
424-
)(MessagesTabContainer)
441+
)(withRouter(MessagesTabContainer))

src/projects/routes.jsx

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,26 @@ const FileDownloadWithAuth = requiresAuthentication(FileDownload)
2121

2222
const ProjectDetailWithAuth = requiresAuthentication(() =>
2323
(<Switch>
24-
<Route exact path="/projects/:projectId" render={() => <ProjectDetail component={Dashboard} />} />
24+
<Route
25+
exact
26+
path="/projects/:projectId"
27+
render={({ match, location }) => {
28+
const matchesTopicUrl = location.hash.match(/#feed-(\d+)/)
29+
const matchesPostUrl = location.hash.match(/#comment-(\d+)/)
30+
31+
// redirect old Topic URLs to the topics on the messages tab
32+
if (matchesTopicUrl) {
33+
return <Redirect to={`/projects/${match.params.projectId}/messages/${matchesTopicUrl[1]}`} />
34+
35+
// redirect old Posts URLs to the messages tab
36+
// as we don't know the topic ID form the URL, message tab should take care about it
37+
} else if (matchesPostUrl) {
38+
return <Redirect to={`/projects/${match.params.projectId}/messages${location.hash}`} />
39+
}
40+
41+
return <ProjectDetail component={Dashboard} />
42+
}}
43+
/>
2544
<Route path="/projects/:projectId/status/:statusId" render={() => <ProjectDetail component={Dashboard} />} />
2645
<Route path="/projects/:projectId/messages/:topicId" render={() => <ProjectDetail component={MessagesTabContainer} />} />
2746
<Route path="/projects/:projectId/messages" render={() => <ProjectDetail component={MessagesTabContainer} />} />

0 commit comments

Comments
 (0)