Skip to content

Commit 15404b5

Browse files
authored
Merge pull request #1983 from appirio-tech/feature/connectMobile
Feature/connect mobile
2 parents 1930c96 + 28385e1 commit 15404b5

File tree

9 files changed

+160
-172
lines changed

9 files changed

+160
-172
lines changed

src/components/NotificationsDropdown/NotificationsDropdownContainer.jsx

Lines changed: 114 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@ import { Link } from 'react-router-dom'
88
import { connect } from 'react-redux'
99
import _ from 'lodash'
1010
import { getNotifications, visitNotifications, toggleNotificationSeen, markAllNotificationsRead,
11-
toggleNotificationRead, toggleBundledNotificationRead, viewOlderNotifications, toggleNotificationsDropdownMobile } from '../../routes/notifications/actions'
12-
import { splitNotificationsBySources, filterReadNotifications, limitQuantityInSources, filterOldNotifications } from '../../routes/notifications/helpers/notifications'
11+
toggleNotificationRead, toggleBundledNotificationRead, viewOlderNotifications,
12+
toggleNotificationsDropdownMobile, hideOlderNotifications } from '../../routes/notifications/actions'
13+
import { splitNotificationsBySources, filterReadNotifications, limitQuantityInSources } from '../../routes/notifications/helpers/notifications'
1314
import NotificationsSection from '../NotificationsSection/NotificationsSection'
1415
import NotificationsEmpty from '../NotificationsEmpty/NotificationsEmpty'
1516
import NotificationsDropdownHeader from '../NotificationsDropdownHeader/NotificationsDropdownHeader'
@@ -18,21 +19,11 @@ import NotificationsMobilePage from './NotificationsMobilePage'
1819
import NotificationsReadAll from './NotificationsReadAll'
1920
import ScrollLock from 'react-scroll-lock-component'
2021
import MediaQuery from 'react-responsive'
21-
import { NOTIFICATIONS_DROPDOWN_PER_SOURCE, NOTIFICATIONS_DROPDOWN_MAX_TOTAL, REFRESH_NOTIFICATIONS_INTERVAL, SCREEN_BREAKPOINT_MD } from '../../config/constants'
22+
import { NOTIFICATIONS_DROPDOWN_PER_SOURCE, NOTIFICATIONS_NEW_PER_SOURCE, REFRESH_NOTIFICATIONS_INTERVAL, SCREEN_BREAKPOINT_MD } from '../../config/constants'
2223
import './NotificationsDropdown.scss'
2324

2425
class NotificationsDropdownContainer extends React.Component {
2526

26-
constructor(props) {
27-
super(props)
28-
29-
this.state = {
30-
isViewAll: false
31-
}
32-
33-
this.viewAll = this.viewAll.bind(this)
34-
}
35-
3627
componentDidMount() {
3728
this.props.getNotifications()
3829
this.autoRefreshNotifications = setInterval(() => this.props.getNotifications(), REFRESH_NOTIFICATIONS_INTERVAL)
@@ -42,6 +33,7 @@ class NotificationsDropdownContainer extends React.Component {
4233
clearInterval(this.autoRefreshNotifications)
4334
// hide notifications dropdown for mobile, when this component is unmounted
4435
this.props.toggleNotificationsDropdownMobile(false)
36+
this.props.hideOlderNotifications()
4537
}
4638

4739
componentWillReceiveProps(nextProps) {
@@ -52,13 +44,10 @@ class NotificationsDropdownContainer extends React.Component {
5244
// hide notifications dropdown for mobile,
5345
// when this component persist but URL changed
5446
this.props.toggleNotificationsDropdownMobile(false)
47+
this.props.hideOlderNotifications()
5548
}
5649
}
5750

58-
viewAll() {
59-
this.setState({isViewAll: true})
60-
}
61-
6251
render() {
6352
if (!this.props.initialized) {
6453
return <NotificationsDropdown hasUnread={false} />
@@ -67,10 +56,9 @@ class NotificationsDropdownContainer extends React.Component {
6756
const {lastVisited, sources, notifications, markAllNotificationsRead, toggleNotificationRead, toggleNotificationSeen,
6857
pending, toggleBundledNotificationRead, visitNotifications, oldSourceIds, viewOlderNotifications, isDropdownMobileOpen,
6958
toggleNotificationsDropdownMobile } = this.props
70-
const {isViewAll} = this.state
7159
const getPathname = link => link.split(/[?#]/)[0].replace(/\/?$/, '')
7260

73-
// mark notifications with url mathc current page's url as seen
61+
// mark notifications with url match current page's url as seen
7462
if (!pending) {
7563
const seenNotificationIds = notifications
7664
.filter(({ isRead, seen, goto = '' }) => !isRead && !seen && getPathname(goto) === getPathname(window.location.pathname))
@@ -80,26 +68,9 @@ class NotificationsDropdownContainer extends React.Component {
8068
}
8169

8270
const notReadNotifications = filterReadNotifications(notifications)
83-
const notOldNotifications = filterOldNotifications(notReadNotifications, oldSourceIds)
84-
const allNotificationsBySources = splitNotificationsBySources(sources, notOldNotifications)
85-
let notificationsBySources
86-
87-
if (!isViewAll) {
88-
notificationsBySources = limitQuantityInSources(
89-
allNotificationsBySources,
90-
NOTIFICATIONS_DROPDOWN_PER_SOURCE,
91-
NOTIFICATIONS_DROPDOWN_MAX_TOTAL
92-
)
93-
} else {
94-
notificationsBySources = allNotificationsBySources
95-
}
96-
97-
const hiddenByLimitCount = _.sumBy(allNotificationsBySources, 'notifications.length') - _.sumBy(notificationsBySources, 'notifications.length')
71+
const allNotificationsBySources = splitNotificationsBySources(sources, notReadNotifications)
9872

99-
const globalSource = notificationsBySources.length > 0 && notificationsBySources[0].id === 'global' ? notificationsBySources[0] : null
100-
const projectSources = notificationsBySources.length > 1 && globalSource ? notificationsBySources.slice(1) : notificationsBySources
10173
const hasUnread = notReadNotifications.length > 0
102-
const olderNotificationsCount = notReadNotifications.length - notOldNotifications.length
10374
// we have to give Dropdown component some time
10475
// before removing notification item node from the list
10576
// otherwise dropdown thinks we clicked outside and closes dropdown
@@ -142,92 +113,111 @@ class NotificationsDropdownContainer extends React.Component {
142113

143114
return (
144115
<MediaQuery minWidth={SCREEN_BREAKPOINT_MD}>
145-
{(matches) => (matches ? (
146-
<NotificationsDropdown hasUnread={hasUnread} hasNew={hasNew} onToggle={visitNotifications}>
147-
<NotificationsDropdownHeader onMarkAllClick={() => !pending && markAllNotificationsRead()} hasUnread={hasUnread}/>
148-
{!hasUnread ? (
149-
<div className="notifications-dropdown-body">
150-
{notificationsEmpty}
151-
</div>
152-
) : ([
153-
<ScrollLock key="body">
154-
<div className="notifications-dropdown-body">
155-
{globalSource && globalSource.notifications.length &&
156-
<NotificationsSection
157-
{...globalSource}
158-
isGlobal
159-
isSimple
160-
onReadToggleClick={toggleNotificationReadWithDelay}
161-
onLinkClick={markNotificationSeen}
162-
/>
163-
}
164-
{projectSources.filter(source => source.notifications.length > 0).map(source => (
165-
<NotificationsSection
166-
{...source}
167-
key={source.id}
168-
isSimple
169-
onReadToggleClick={toggleNotificationReadWithDelay}
170-
onLinkClick={markNotificationSeen}
171-
/>
172-
))}
173-
</div>
174-
</ScrollLock>,
175-
<NotificationsReadAll key="footer" to="/notifications">
176-
{
177-
olderNotificationsCount > 0 ?
178-
`View ${olderNotificationsCount} older notification${olderNotificationsCount > 1 ? 's' : ''}` :
179-
'View all notifications'
180-
}
181-
</NotificationsReadAll>
182-
])}
183-
</NotificationsDropdown>
184-
) : (
185-
<NotificationsMobilePage
186-
hasUnread={hasUnread}
187-
hasNew={hasNew}
188-
onToggle={() => {
189-
toggleNotificationsDropdownMobile()
190-
visitNotifications()
191-
}}
192-
isOpen={isDropdownMobileOpen}
193-
>
194-
{!hasUnread ? (
195-
notificationsEmpty
196-
) : (
197-
<div>
198-
{globalSource && (globalSource.notifications.length || isViewAll && globalSource.total) &&
199-
<NotificationsSection
200-
{...globalSource}
201-
isGlobal
202-
isSimple
203-
isLoading={globalSource.isLoading}
204-
onReadToggleClick={toggleNotificationReadWithDelay}
205-
onViewOlderClick={isViewAll ? () => viewOlderNotifications(globalSource.id) : null}
206-
onLinkClick={(notificationId) => {
207-
toggleNotificationsDropdownMobile()
208-
markNotificationSeen(notificationId)
209-
}}
210-
/>}
211-
{projectSources.filter(source => source.notifications.length || isViewAll && source.total).map(source => (
212-
<NotificationsSection
213-
{...source}
214-
key={source.id}
215-
isSimple
216-
isLoading={source.isLoading}
217-
onReadToggleClick={toggleNotificationReadWithDelay}
218-
onViewOlderClick={isViewAll ? () => viewOlderNotifications(source.id) : null}
219-
onLinkClick={(notificationId) => {
220-
toggleNotificationsDropdownMobile()
221-
markNotificationSeen(notificationId)
222-
}}
223-
/>
224-
))}
225-
{!isViewAll && (olderNotificationsCount > 0 || hiddenByLimitCount > 0) &&
226-
<NotificationsReadAll onClick={this.viewAll}>Read all notifications</NotificationsReadAll>}
227-
</div>
228-
)}
229-
</NotificationsMobilePage>
230-
))}
116+
{(matches) => {
117+
if (matches) {
118+
const notificationsBySources = limitQuantityInSources(
119+
allNotificationsBySources,
120+
NOTIFICATIONS_DROPDOWN_PER_SOURCE,
121+
oldSourceIds
122+
)
123+
const hiddenByLimitCount = _.sumBy(notificationsBySources, 'total') - _.sumBy(notificationsBySources, 'notifications.length')
124+
const globalSource = notificationsBySources.length > 0 && notificationsBySources[0].id === 'global' ? notificationsBySources[0] : null
125+
const projectSources = notificationsBySources.length > 1 && globalSource ? notificationsBySources.slice(1) : notificationsBySources
126+
127+
return (
128+
<NotificationsDropdown hasUnread={hasUnread} hasNew={hasNew} onToggle={visitNotifications}>
129+
<NotificationsDropdownHeader onMarkAllClick={() => !pending && markAllNotificationsRead()} hasUnread={hasUnread}/>
130+
{!hasUnread ? (
131+
<div className="notifications-dropdown-body">
132+
{notificationsEmpty}
133+
</div>
134+
) : ([
135+
<ScrollLock key="body">
136+
<div className="notifications-dropdown-body">
137+
{globalSource && globalSource.notifications.length &&
138+
<NotificationsSection
139+
{...globalSource}
140+
isGlobal
141+
isSimple
142+
onReadToggleClick={toggleNotificationReadWithDelay}
143+
onLinkClick={markNotificationSeen}
144+
/>
145+
}
146+
{projectSources.filter(source => source.notifications.length > 0).map(source => (
147+
<NotificationsSection
148+
{...source}
149+
key={source.id}
150+
isSimple
151+
onReadToggleClick={toggleNotificationReadWithDelay}
152+
onLinkClick={markNotificationSeen}
153+
/>
154+
))}
155+
</div>
156+
</ScrollLock>,
157+
<NotificationsReadAll key="footer" to="/notifications">
158+
{
159+
hiddenByLimitCount > 0 ?
160+
`View ${hiddenByLimitCount} older notification${hiddenByLimitCount > 1 ? 's' : ''}` :
161+
'View all notifications'
162+
}
163+
</NotificationsReadAll>
164+
])}
165+
</NotificationsDropdown>
166+
)
167+
} else {
168+
const notificationsBySources = limitQuantityInSources(
169+
allNotificationsBySources,
170+
NOTIFICATIONS_NEW_PER_SOURCE,
171+
oldSourceIds
172+
)
173+
const globalSource = notificationsBySources.length > 0 && notificationsBySources[0].id === 'global' ? notificationsBySources[0] : null
174+
const projectSources = notificationsBySources.length > 1 && globalSource ? notificationsBySources.slice(1) : notificationsBySources
175+
176+
return (
177+
<NotificationsMobilePage
178+
hasUnread={hasUnread}
179+
hasNew={hasNew}
180+
onToggle={() => {
181+
toggleNotificationsDropdownMobile()
182+
visitNotifications()
183+
}}
184+
isOpen={isDropdownMobileOpen}
185+
>
186+
{!hasUnread ? (
187+
notificationsEmpty
188+
) : (
189+
<div>
190+
{globalSource && globalSource.notifications.length > 0 &&
191+
<NotificationsSection
192+
{...globalSource}
193+
isGlobal
194+
isSimple
195+
onReadToggleClick={toggleNotificationReadWithDelay}
196+
onViewOlderClick={() => viewOlderNotifications(globalSource.id)}
197+
onLinkClick={(notificationId) => {
198+
toggleNotificationsDropdownMobile()
199+
markNotificationSeen(notificationId)
200+
}}
201+
/>}
202+
{projectSources.filter(source => source.notifications.length).map(source => (
203+
<NotificationsSection
204+
{...source}
205+
key={source.id}
206+
isSimple
207+
onReadToggleClick={toggleNotificationReadWithDelay}
208+
onViewOlderClick={() => viewOlderNotifications(source.id)}
209+
onLinkClick={(notificationId) => {
210+
toggleNotificationsDropdownMobile()
211+
markNotificationSeen(notificationId)
212+
}}
213+
/>
214+
))}
215+
</div>
216+
)}
217+
</NotificationsMobilePage>
218+
)
219+
}
220+
}}
231221
</MediaQuery>
232222
)
233223
}
@@ -243,6 +233,7 @@ const mapDispatchToProps = {
243233
toggleNotificationRead,
244234
toggleBundledNotificationRead,
245235
viewOlderNotifications,
236+
hideOlderNotifications,
246237
toggleNotificationsDropdownMobile
247238
}
248239

src/components/ScrollToAnchors.jsx

Lines changed: 2 additions & 2 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, SCROLL_TO_DURATION } from '../config/constants'
10+
import { SCROLL_TO_MARGIN, SCROLL_TO_DURATION, SCREEN_BREAKPOINT_MD } from '../config/constants'
1111
import { scroller } from 'react-scroll'
1212

1313
/**
@@ -24,7 +24,7 @@ export function scrollToHash(hash) {
2424
scroller.scrollTo(id, {
2525
spy: true,
2626
smooth: true,
27-
offset: windowWidth < 768 ? 0 : -SCROLL_TO_MARGIN,
27+
offset: windowWidth < SCREEN_BREAKPOINT_MD ? 0 : -SCROLL_TO_MARGIN,
2828
duration: SCROLL_TO_DURATION,
2929
activeClass: 'active'
3030
})

src/components/TopBar/SectionToolBar.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,5 +121,9 @@
121121
}
122122
}
123123
}
124+
125+
> .section .logo .icon-connect-logo-mono {
126+
margin-top: 0;
127+
}
124128
}
125129
}

src/config/constants.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export const MARK_ALL_NOTIFICATIONS_READ = 'MARK_ALL_NOTIFICATIONS_READ'
1414
export const TOGGLE_NOTIFICATION_READ = 'TOGGLE_NOTIFICATION_READ'
1515
export const TOGGLE_NOTIFICATION_SEEN = 'TOGGLE_NOTIFICATION_SEEN'
1616
export const VIEW_OLDER_NOTIFICATIONS_SUCCESS = 'VIEW_OLDER_NOTIFICATIONS_SUCCESS'
17+
export const HIDE_OLDER_NOTIFICATIONS_SUCCESS = 'HIDE_OLDER_NOTIFICATIONS_SUCCESS'
1718
export const NOTIFICATIONS_PENDING = 'NOTIFICATIONS_PENDING'
1819
export const TOGGLE_NOTIFICATIONS_DROPDOWN_MOBILE = 'TOGGLE_NOTIFICATIONS_DROPDOWN_MOBILE'
1920

@@ -379,11 +380,9 @@ export const SORT_OPTIONS = [
379380
export const REFRESH_NOTIFICATIONS_INTERVAL = 1000 * 60 * 1 // 1 minute interval
380381
export const REFRESH_UNREAD_UPDATE_INTERVAL = 1000 * 10 * 1 // 10 second interval
381382
export const NOTIFICATIONS_DROPDOWN_PER_SOURCE = 5
382-
export const NOTIFICATIONS_DROPDOWN_MAX_TOTAL = Infinity
383+
export const NOTIFICATIONS_NEW_PER_SOURCE = 10
383384

384385
export const NOTIFICATIONS_LIMIT = 1000
385-
// old notification time in minutes, a notification is old if its date is later than this time
386-
export const OLD_NOTIFICATION_TIME = 60 * 48 // 2 day2
387386

388387
export const SCROLL_TO_MARGIN = 70 // px - 60px of toolbar height + 10px to make some margin
389388
export const SCROLL_TO_DURATION = 500 // ms

src/projects/list/components/Projects/ProjectsGridView.scss

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -323,11 +323,11 @@ $screen-one-column: 720px;
323323
white-space: nowrap;
324324
overflow: hidden;
325325
text-overflow: ellipsis;
326+
}
326327

327-
&:hover {
328-
background-color: $tc-dark-blue-30;
329-
color: $tc-black;
330-
}
328+
.tooltip-target.active .project-customer {
329+
background-color: $tc-dark-blue-30;
330+
color: $tc-black;
331331
}
332332

333333
.project-segment {

src/routes/notifications/actions/index.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
MARK_ALL_NOTIFICATIONS_READ,
1010
TOGGLE_NOTIFICATION_READ,
1111
VIEW_OLDER_NOTIFICATIONS_SUCCESS,
12+
HIDE_OLDER_NOTIFICATIONS_SUCCESS,
1213
NOTIFICATIONS_PENDING,
1314
TOGGLE_NOTIFICATIONS_DROPDOWN_MOBILE
1415
} from '../../../config/constants'
@@ -112,6 +113,10 @@ export const viewOlderNotifications = (sourceId) => (dispatch) => dispatch({
112113
payload: sourceId
113114
})
114115

116+
export const hideOlderNotifications = () => (dispatch) => dispatch({
117+
type: HIDE_OLDER_NOTIFICATIONS_SUCCESS
118+
})
119+
115120
export const toggleNotificationsDropdownMobile = (isOpen) => (dispatch) => dispatch({
116121
type: TOGGLE_NOTIFICATIONS_DROPDOWN_MOBILE,
117122
payload: isOpen

0 commit comments

Comments
 (0)