Skip to content

Notifications #167

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 22 commits into from
Mar 30, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
3092142
Added Notifications Popup
luizrrodrigues Feb 10, 2020
54c0d14
Compiled
luizrrodrigues Feb 10, 2020
648392a
Notifications Popup Fixes
luizrrodrigues Feb 17, 2020
e271381
Notifications Listing Page
luizrrodrigues Feb 27, 2020
a36d2e1
Fix Issue #158 : Space between bell and pink mark icons
luizrrodrigues Mar 2, 2020
549f0a6
Fix Issue #159 : Center notification title in mobile view
luizrrodrigues Mar 2, 2020
ef383b0
Fix Issue #160 : Make "Mark All as Read" disabled
luizrrodrigues Mar 2, 2020
c3000df
Fix Issue #161 : Unseen notifications counter in mobile view
luizrrodrigues Mar 2, 2020
9c0f3da
Backend Integration + Fixes + Broadcast type
luizrrodrigues Mar 9, 2020
96d3b99
#162 : Notifications - Remove the completed challenges section from t…
luizrrodrigues Mar 9, 2020
258ce62
Notification items clickable
luizrrodrigues Mar 10, 2020
91abbcb
Notifications: Fix check if item is a link
luizrrodrigues Mar 10, 2020
0c047d8
Remove submission event.
luizrrodrigues Mar 11, 2020
e88ef49
Prevent follow link when click in "Mark As Read" button
luizrrodrigues Mar 11, 2020
af2c926
Fix unseen mark in primary nav
luizrrodrigues Mar 12, 2020
ab74a3c
Hide Notificaitons Settings until this page ready
luizrrodrigues Mar 13, 2020
33399c2
Allow HTML tag in notification msg
luizrrodrigues Mar 21, 2020
6913976
Updated SCSS to use color from var instead hex
luizrrodrigues Mar 21, 2020
4e0b4fd
Build updated
luizrrodrigues Mar 21, 2020
ef56b4e
Remove 'Settings' link from empty panel and mobile view
luizrrodrigues Mar 26, 2020
d5ccb2e
#4141: Updated button text and hide description
luizrrodrigues Mar 28, 2020
1446074
Merge branch 'develop' into notifications
luizrrodrigues Mar 30, 2020
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
48 changes: 24 additions & 24 deletions dist/dev/index.js

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dist/prod/index.js

Large diffs are not rendered by default.

20 changes: 20 additions & 0 deletions src/assets/images/icon-bell-grey.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions src/assets/images/icon-checkmark.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions src/assets/sass/_global/_variables.scss
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ $green-light: #B5E9DB;
$green-dark: #229174;
$blue: #0596dc;
$blue-btn: #50ADE8;
$blue-link: #0d61bf;

$font-path: "../../assets/fonts";
$img-path: "../../assets/images";
Expand Down
43 changes: 38 additions & 5 deletions src/components/AccountMenu/index.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import _ from 'lodash'
import React from 'react'
import React, { Fragment } from 'react'
import PropTypes from 'prop-types'
import cn from 'classnames'
import { Link } from 'topcoder-react-utils'
import IconAvatar from '../../assets/images/ico-user-default.svg'
import IconCloseDark from '../../assets/images/icon-close-dark.svg'
import IconSwitchBusiness from '../../assets/images/icon-switch-business.svg'
import IconNotificationsRed from '../../assets/images/icon-bell-red.svg'
import IconNotificationsGrey from '../../assets/images/icon-bell-grey.svg'
import IconRightArrow from '../../assets/images/right-arrow.svg'
import styles from './styles.module.scss'
import moment from 'moment'

Expand Down Expand Up @@ -43,7 +46,7 @@ class AccountMenu extends React.Component {

render () {
const {
onClose, open, menu, switchText, onSwitch, profile, domRef
onClose, open, menu, switchText, onSwitch, profile, domRef, numNotifications, onClickNotifications
} = this.props

return (
Expand Down Expand Up @@ -90,6 +93,34 @@ class AccountMenu extends React.Component {
</div>
)
}
{
!_.isEmpty(profile) && (
<Fragment>
<div
role='button'
className={styles['notifications-mobile']}
onClick={onClickNotifications}
>
<div className={styles['noti-left']}>
{numNotifications > 0
? <IconNotificationsRed className={styles['bell-icon']} />
: <IconNotificationsGrey className={styles['bell-icon']} />
}
<div>
<span className={styles['notifications-title']}>Notifications</span>
{numNotifications > 0 &&
<span className={styles['red-number']}>{'(' + numNotifications + ')'}</span>
}
</div>
</div>
<span role='button' className={styles['icon-open-noti']}>
<IconRightArrow />
</span>
</div>
<span className={styles['noti-separator']} />
</Fragment>
)
}

<div className={styles.menu}>

Expand All @@ -100,13 +131,13 @@ class AccountMenu extends React.Component {
))}

</div>
</div>
</div >
)
}
}

AccountMenu.defaultProps = {
numNotifications: 35
numNotifications: 0
}

AccountMenu.propTypes = {
Expand All @@ -116,7 +147,9 @@ AccountMenu.propTypes = {
switchText: PropTypes.shape(),
onSwitch: PropTypes.func,
profile: PropTypes.shape(),
domRef: PropTypes.shape()
domRef: PropTypes.shape(),
numNotifications: PropTypes.number,
onClickNotifications: PropTypes.func.isRequired
}

export default AccountMenu
55 changes: 49 additions & 6 deletions src/components/AccountMenu/styles.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -79,14 +79,15 @@
}
}

.notifications-mobile {
@include mobile-only;
}

.menu {
@include not-mobile {
padding: 15px 0 25px 0;
}

.notification-mobile {
@include mobile-only;
}

a {
height: 50px;
Expand Down Expand Up @@ -186,6 +187,50 @@
}
}

.notifications-mobile {
height: 75px;
display: flex;
align-items: center;
justify-content: space-between;

.noti-left {

display: flex;
align-items: center;
margin-bottom: 2px;

.bell-icon {
margin: 0 10px 0 22px;
}

.red-number {
color: $red;
margin: 0 10px;
}
}

.icon-open-noti {
width: 50px;
height: 50px;
display: flex;
justify-content: center;
align-items: center;
}

a {
color: $white;
font-size: 14px;
line-height: 30px;
}
}
.noti-separator {
background: $gray-05;
width: calc(100% - 46px);
height: 1px;
align-self: center;
padding: 0 $base-unit * 4;
}

.menu {
display: flex;
flex-direction: column;
Expand All @@ -200,8 +245,7 @@
padding: 0 $base-unit * 4;
}

a,
.notification-mobile {
a {
color: $gray-90;
height: 40px;
display: flex;
Expand Down Expand Up @@ -237,7 +281,6 @@
}
}
}

}
}
}
45 changes: 35 additions & 10 deletions src/components/LoginNav/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,23 @@ import NotificationButton from '../NotificationButton'
import NotificationsPopup from '../NotificationsPopup'
import UserInfo from '../UserInfo'
import AccountMenu from '../AccountMenu'
import _ from 'lodash'

const LoginNav = ({
loggedIn,
notificationButtonState,
notifications,
accountMenu,
switchText,
onSwitch,
onMenuOpen,
showNotification,
profile,
authURLs
authURLs,
auth,
markNotificationAsRead,
markAllNotificationAsRead,
markAllNotificationAsSeen,
dismissChallengeNotifications
}) => {
const [openNotifications, setOpenNotifications] = useState()
const [openAccountMenu, setOpenAccountMenu] = useState()
Expand Down Expand Up @@ -66,19 +71,26 @@ const LoginNav = ({
setOpenAccountMenu(x => !x)
}

// process seenNotifications
const seenNotifications = _.filter((notifications || []), t => !t.isSeen && !t.isRead)
.map(opt => opt.id)
.join('-')

// process unReadNotifications
const unReadNotifications = _.filter((notifications || []), t => !t.isRead).length > 0

const renderLoginPanel = () => {
if (showNotification) {
return ([
<NotificationButton
className={styles.notificationButton}
state={notificationButtonState}
notifications={notifications || []}
notificationsPopupOpen={openNotifications}
onClick={handleClickNotifications}
key='notification-button'
/>,
<UserInfo
profile={profile}
newNotifications={notificationButtonState === 'new'}
newNotifications={!!seenNotifications}
onClick={handleClickUserInfo}
open={openAccountMenu}
key='user-info'
Expand All @@ -90,7 +102,7 @@ const LoginNav = ({
return (
<UserInfo
profile={profile}
newNotifications={notificationButtonState === 'new'}
newNotifications={!!seenNotifications}
onClick={handleClickUserInfo}
open={openAccountMenu}
key='user-info'
Expand All @@ -117,14 +129,23 @@ const LoginNav = ({
<NotificationsPopup
open={openNotifications}
notifications={notifications}
onClose={() => setOpenNotifications(false)}
onClose={() => {
seenNotifications &&
markAllNotificationAsSeen(seenNotifications, auth.tokenV3)
setOpenNotifications(false)
}}
auth={auth}
unReadNotifications={unReadNotifications}
markNotificationAsRead={markNotificationAsRead}
markAllNotificationAsRead={markAllNotificationAsRead}
dismissChallengeNotifications={dismissChallengeNotifications}
/>
<AccountMenu
profile={profile}
open={openAccountMenu}
menu={accountMenu}
switchText={switchText}
numNotifications={(notifications || []).length}
numNotifications={_.filter((notifications || []), n => !n.isSeen && !n.isRead).length}
onClickNotifications={handleClickNotifications}
onSwitch={onSwitch}
onClose={() => {
Expand All @@ -139,15 +160,19 @@ const LoginNav = ({

LoginNav.propTypes = {
loggedIn: PropTypes.bool,
notificationButtonState: PropTypes.string,
notifications: PropTypes.array,
accountMenu: PropTypes.array,
onSwitch: PropTypes.func,
onMenuOpen: PropTypes.func,
showNotification: PropTypes.bool,
profile: PropTypes.shape(),
auth: PropTypes.shape(),
switchText: PropTypes.shape(),
authURLs: PropTypes.shape()
authURLs: PropTypes.shape(),
markNotificationAsRead: PropTypes.func.isRequired,
markAllNotificationAsRead: PropTypes.func.isRequired,
markAllNotificationAsSeen: PropTypes.func.isRequired,
dismissChallengeNotifications: PropTypes.func.isRequired
}

export default LoginNav
26 changes: 20 additions & 6 deletions src/components/NotificationButton/index.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,37 @@
import React from 'react'
import PropTypes from 'prop-types'
import cn from 'classnames'
import IconBellEmpty from '../../assets/images/icon-bell-grey.svg'
import IconBell from '../../assets/images/icon-bell.svg'
import styles from './styles.module.scss'
import _ from 'lodash'

const NotificationButton = ({ className, state, onClick, notificationsPopupOpen }) => (
const getNotificationButtonState = (notifications) => {
if (notifications && _.countBy(notifications || [], n => !n.isSeen && !n.isRead).true > 0) {
return 'new'
}
if (notifications.length === 0) {
return 'none'
} else {
return 'seen'
}
}

const NotificationButton = ({ onClick, notificationsPopupOpen, notifications }) => (
<div
className={cn(styles.notificationButton, styles[state], notificationsPopupOpen && styles.isNotificationsPopupOpen, className)}
className={cn([styles.notificationButton,
notificationsPopupOpen && styles.isNotificationsPopupOpen,
styles[getNotificationButtonState(notifications)]])}
onClick={onClick}
>
<IconBell />
{(!_.isEmpty(notifications || []) ? <IconBell /> : <IconBellEmpty />)}
</div>
)

NotificationButton.propTypes = {
className: PropTypes.string,
state: PropTypes.oneOf(['none', 'new', 'seen']),
onClick: PropTypes.func,
notificationsPopupOpen: PropTypes.bool
notificationsPopupOpen: PropTypes.bool,
notifications: PropTypes.array
}

export default NotificationButton
Loading