Skip to content

Commit d169c48

Browse files
committed
implemented auto-opening of comment threads on mobile when there is a comment hash in URL and smooth scrolling to such comments
replaced screen breakpoints in react components with constants
1 parent 631012e commit d169c48

File tree

14 files changed

+73
-34
lines changed

14 files changed

+73
-34
lines changed

src/components/ActionCard/CommentMobile.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const CommentMobile = ({ messageId, author, date, children }) => {
1616
const messageLink = window.location.pathname.substr(0, window.location.pathname.indexOf('#')) + `#comment-${messageId}`
1717

1818
return (
19-
<div styleName="comment">
19+
<div styleName="comment" id={`comment-${messageId}`}>
2020
<div styleName="header">
2121
<UserWithName {..._.pick(author, 'firstName', 'lastName', 'photoURL')} size="40" />
2222
<Link styleName="date" to={messageLink}>{moment(date).fromNow()}</Link>

src/components/Feed/FeedComments.jsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import Comment from '../ActionCard/Comment'
77
import cn from 'classnames'
88
import MediaQuery from 'react-responsive'
99
import CommentMobile from '../ActionCard/CommentMobile'
10-
// import { THREAD_MESSAGES_PAGE_SIZE } from '../../config/constants'
10+
import { SCREEN_BREAKPOINT_MD } from '../../config/constants'
1111

1212
const getCommentCount = (totalComments) => {
1313
if (!totalComments) {
@@ -71,7 +71,7 @@ class FeedComments extends React.Component {
7171
</div>
7272
</div>
7373
</Panel.Body>
74-
<MediaQuery minWidth={768}>
74+
<MediaQuery minWidth={SCREEN_BREAKPOINT_MD}>
7575
{(matches) => (matches ? (
7676
<div>
7777
{comments.map((item, idx) => (

src/components/Feed/FeedMobile.jsx

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,33 @@ class FeedMobile extends React.Component {
2626
}
2727
}
2828

29+
componentWillReceiveProps(nextProps) {
30+
// if comments just has been loaded, check if have to open the thread
31+
if (this.props.comments.length === 0 && nextProps.comments.length > 0) {
32+
this.openCommentFromHash(nextProps.comments)
33+
}
34+
}
35+
36+
componentWillMount() {
37+
this.openCommentFromHash(this.props.comments)
38+
}
39+
40+
/**
41+
* If there is hash in the URL referencing some comment,
42+
* open the comments thread by default
43+
*
44+
* @param {Array} comments list of comments
45+
*/
46+
openCommentFromHash(comments) {
47+
const { isCommentsShown } = this.state
48+
const commentInHash = window.location.hash.match(/#comment-(\d+)/)
49+
const isCommentInTheFeed = !!(commentInHash && _.find(comments, (comment) => (comment.id.toString() === commentInHash[1])))
50+
51+
if (!isCommentsShown && isCommentInTheFeed) {
52+
this.toggleComments()
53+
}
54+
}
55+
2956
toggleComments() {
3057
this.setState({ isCommentsShown: !this.state.isCommentsShown })
3158
}

src/components/Footer/Footer.jsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import MenuBar from 'appirio-tech-react-components/components/MenuBar/MenuBar'
33
import moment from 'moment'
44
import MediaQuery from 'react-responsive'
55
import FooterV2 from '../FooterV2/FooterV2'
6-
import { NEW_PROJECT_PATH } from '../../config/constants'
6+
import { NEW_PROJECT_PATH, SCREEN_BREAKPOINT_MD } from '../../config/constants'
77

88
require('./Footer.scss')
99

@@ -25,14 +25,14 @@ const Footer = () => {
2525
const shouldHideOnMobile = window.location.pathname !== '/'
2626

2727
return (
28-
<MediaQuery minWidth={768}>
28+
<MediaQuery minWidth={SCREEN_BREAKPOINT_MD}>
2929
{(matches) => {
3030
if (matches) {
3131
return (shouldHideOnDesktop ? null :
3232
<div className="Footer">
3333
<p className="copyright-notice">© Topcoder { currentYear }</p>
3434
<div className="footer-menu">
35-
<MenuBar items={otherNavigationItems} orientation="horizontal" mobileBreakPoint={767} />
35+
<MenuBar items={otherNavigationItems} orientation="horizontal" mobileBreakPoint={SCREEN_BREAKPOINT_MD - 1} />
3636
</div>
3737
</div>
3838
)

src/components/NotificationsDropdown/NotificationsDropdownContainer.jsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import NotificationsMobilePage from './NotificationsMobilePage'
1818
import NotificationsReadAll from './NotificationsReadAll'
1919
import ScrollLock from 'react-scroll-lock-component'
2020
import MediaQuery from 'react-responsive'
21-
import { NOTIFICATIONS_DROPDOWN_PER_SOURCE, NOTIFICATIONS_DROPDOWN_MAX_TOTAL, REFRESH_NOTIFICATIONS_INTERVAL } from '../../config/constants'
21+
import { NOTIFICATIONS_DROPDOWN_PER_SOURCE, NOTIFICATIONS_DROPDOWN_MAX_TOTAL, REFRESH_NOTIFICATIONS_INTERVAL, SCREEN_BREAKPOINT_MD } from '../../config/constants'
2222
import './NotificationsDropdown.scss'
2323

2424
class NotificationsDropdownContainer extends React.Component {
@@ -141,7 +141,7 @@ class NotificationsDropdownContainer extends React.Component {
141141
}
142142

143143
return (
144-
<MediaQuery minWidth={768}>
144+
<MediaQuery minWidth={SCREEN_BREAKPOINT_MD}>
145145
{(matches) => (matches ? (
146146
<NotificationsDropdown hasUnread={hasUnread} hasNew={hasNew} onToggle={visitNotifications}>
147147
<NotificationsDropdownHeader onMarkAllClick={() => !pending && markAllNotificationsRead()} hasUnread={hasUnread}/>

src/components/ProjectInfo/ProjectInfo.jsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import ProjectCardBody from '../../projects/list/components/Projects/ProjectCard
77
import ProjectDirectLinks from '../../projects/list/components/Projects/ProjectDirectLinks'
88
import MobileExpandable from '../MobileExpandable/MobileExpandable'
99
import MediaQuery from 'react-responsive'
10+
import { SCREEN_BREAKPOINT_MD } from '../../config/constants'
1011

1112
import './ProjectInfo.scss'
1213

@@ -54,7 +55,7 @@ class ProjectInfo extends Component {
5455
/>
5556
}
5657
</Panel>
57-
<MediaQuery minWidth={768}>
58+
<MediaQuery minWidth={SCREEN_BREAKPOINT_MD}>
5859
{(matches) => (
5960
<ProjectCardBody
6061
project={project}

src/components/ScrollToAnchors.jsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* If there is any hash we check if component has element with such id and scroll to it.
88
*/
99
import React from 'react'
10-
import { SCROLL_TO_MARGIN } from '../config/constants'
10+
import { SCROLL_TO_MARGIN, SCROLL_TO_DURATION } from '../config/constants'
1111
import { scroller } from 'react-scroll'
1212

1313
/**
@@ -17,12 +17,16 @@ import { scroller } from 'react-scroll'
1717
*/
1818
export function scrollToHash(hash) {
1919
const id = hash.replace('#', '')
20+
const windowWidth = window.innerWidth
21+
|| document.documentElement.clientWidth
22+
|| document.body.clientWidth
2023

2124
scroller.scrollTo(id, {
2225
spy: true,
2326
smooth: true,
24-
offset: -SCROLL_TO_MARGIN,
25-
duration: 500
27+
offset: windowWidth < 768 ? 0 : -SCROLL_TO_MARGIN,
28+
duration: SCROLL_TO_DURATION,
29+
activeClass: 'active'
2630
})
2731
}
2832

src/config/constants.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -384,11 +384,18 @@ export const NOTIFICATIONS_LIMIT = 1000
384384
// old notification time in minutes, a notification is old if its date is later than this time
385385
export const OLD_NOTIFICATION_TIME = 60 * 48 // 2 day2
386386

387-
export const SCROLL_TO_MARGIN = 70 // px - 60px of toolbar height + 10px to make sume margin
387+
export const SCROLL_TO_MARGIN = 70 // px - 60px of toolbar height + 10px to make some margin
388388
export const SCROLL_TO_DURATION = 500 // ms
389389

390390
// Settings
391391
export const MAX_USERNAME_LENGTH = 15
392392
export const EMAIL_AVAILABILITY_CHECK_DEBOUNCE = 300 /* in ms */
393393
export const PASSWORD_MIN_LENGTH = 8
394394
export const PASSWORD_REG_EXP = /^(?=.*[a-z])(?=.*[^a-z]).+$/i
395+
396+
// Screen breakpoints
397+
export const SCREEN_BREAKPOINT_LG = 1360
398+
export const SCREEN_BREAKPOINT_RG = 992
399+
export const SCREEN_BREAKPOINT_MD = 768
400+
export const SCREEN_BREAKPOINT_SM = 640
401+
export const SCREEN_BREAKPOINT_XS = 320

src/projects/detail/Dashboard.jsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import FeedContainer from './containers/FeedContainer'
66
import MobileNavigationTabs from './components/MobileNavigationTabs'
77
import Sticky from 'react-stickynode'
88
import spinnerWhileLoading from '../../components/LoadingSpinner'
9+
import { SCREEN_BREAKPOINT_MD } from '../../config/constants'
910

1011
require('./Dashboard.scss')
1112

@@ -25,7 +26,7 @@ const DashboardView = ({project, currentMemberRole, route, params, isSuperUser }
2526
<div className="dashboard-container">
2627
<MobileNavigationTabs projectId={project.id} />
2728
<div className="left-area">
28-
<MediaQuery minWidth={768}>
29+
<MediaQuery minWidth={SCREEN_BREAKPOINT_MD}>
2930
{(matches) => {
3031
if (matches) {
3132
return <Sticky top={80}>{leftArea}</Sticky>

src/projects/detail/components/ProjectSpecSidebar.jsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import Sticky from 'react-stickynode'
88
import MediaQuery from 'react-responsive'
99
import SidebarNav from './SidebarNav'
1010
import VisualDesignProjectEstimateSection from './VisualDesignProjectEstimateSection'
11-
import { PROJECT_ROLE_OWNER, PROJECT_ROLE_CUSTOMER } from '../../../config/constants'
11+
import { PROJECT_ROLE_OWNER, PROJECT_ROLE_CUSTOMER, SCREEN_BREAKPOINT_MD } from '../../../config/constants'
1212
import { updateProject } from '../../actions/project'
1313
import { findProduct } from '../../../config/projectWizard'
1414
import './ProjectSpecSidebar.scss'
@@ -165,7 +165,7 @@ class ProjectSpecSidebar extends Component {
165165
you a good estimate.
166166
</p>
167167
</div>
168-
<MediaQuery minWidth={768}>
168+
<MediaQuery minWidth={SCREEN_BREAKPOINT_MD}>
169169
{(matches) => {
170170
if (matches) {
171171
return (

0 commit comments

Comments
 (0)