Skip to content

Commit 8e833ae

Browse files
authored
Merge pull request #3338 from appirio-tech/feature/registration_and_profile_page_improvements
Feature/registration and profile page improvements
2 parents 9b6e9d2 + 9f4253f commit 8e833ae

File tree

8 files changed

+7517
-6402
lines changed

8 files changed

+7517
-6402
lines changed

package-lock.json

Lines changed: 7278 additions & 6310 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 76 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1-
import { NavLink } from 'react-router-dom'
1+
import { NavLink, withRouter } from 'react-router-dom'
22
import React from 'react'
3+
import { some } from 'lodash'
34
import PT from 'prop-types'
45
import cn from 'classnames'
56
import NotificationBadge from '../NotificationBadge/NotificationBadge'
7+
import ArrowUpIcon from '../../assets/icons/arrows-16px-1_minimal-up.svg'
8+
69

710
import styles from './MenuItem.scss'
811

@@ -14,28 +17,76 @@ const MenuItem = ({
1417
exact,
1518
isActive,
1619
count,
17-
}) => (
18-
<li>
19-
<NavLink
20-
to={to}
21-
className={styles.navItem}
22-
activeClassName={styles.active}
23-
exact={exact}
24-
isActive={isActive}
20+
children,
21+
isAccordionOpen,
22+
onAccordionToggle,
23+
match,
24+
wrapperClass
25+
}) => {
26+
const matchedPath = match && match.path
27+
const isChildActive = children && some(children, c => c.to === matchedPath)
28+
29+
return (
30+
<li className={
31+
cn(wrapperClass,
32+
styles.menuItem,
33+
{ [styles.open]: isAccordionOpen, [styles.withChildren]: children })}
2534
>
26-
<span styleName="left">
27-
{!!Icon && <Icon className={cn(styles.icon, styles[iconClassName])} />}
28-
{label}
29-
</span>
30-
<span styleName="right">
31-
{!!count && <NotificationBadge count={count} />}
32-
</span>
33-
</NavLink>
34-
</li>
35-
)
35+
{!children && (
36+
<NavLink
37+
to={to}
38+
className={styles.navItem}
39+
activeClassName={styles.active}
40+
exact={exact}
41+
isActive={isActive}
42+
>
43+
<span styleName="left">
44+
{!!Icon && (
45+
<Icon className={cn(styles.icon, styles[iconClassName])} />
46+
)}
47+
{label}
48+
</span>
49+
<span styleName="right">
50+
{!!count && <NotificationBadge count={count} />}
51+
</span>
52+
</NavLink>
53+
)}
54+
55+
{children && (
56+
<div>
57+
<div
58+
className={cn(styles.navItem, {
59+
[styles.activeParent]: isChildActive,
60+
[styles.active]: isChildActive
61+
})}
62+
onClick={() => onAccordionToggle(!isAccordionOpen)}
63+
>
64+
<span styleName="left">
65+
{!!Icon && (
66+
<Icon className={cn(styles.icon, styles[iconClassName])} />
67+
)}
68+
{label}
69+
</span>
70+
<span styleName="right">
71+
{!!count && <NotificationBadge count={count} />}
72+
</span>
73+
74+
<ArrowUpIcon className={styles.arrowUpIcon} />
75+
</div>
76+
77+
{isAccordionOpen &&
78+
<ul>
79+
{ children.map(c => <MenuItem {...c} key={c.to} wrapperClass={styles.childNavItem} />) }
80+
</ul>
81+
}
82+
</div>
83+
)}
84+
</li>
85+
)
86+
}
3687

3788
MenuItem.defaultProps = {
38-
exact: true,
89+
exact: true
3990
}
4091

4192
MenuItem.propTypes = {
@@ -46,6 +97,10 @@ MenuItem.propTypes = {
4697
exact: PT.bool,
4798
isActive: PT.func,
4899
count: PT.number,
100+
children: PT.array,
101+
isAccordionOpen: PT.bool,
102+
onAccordionToggle: PT.func,
103+
wrapperClass: PT.string
49104
}
50105

51-
export default MenuItem
106+
export default withRouter(MenuItem)

src/components/MenuItem/MenuItem.scss

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,29 @@
11
@import "../../styles/includes";
22

3+
.menuItem.withChildren {
4+
.arrowUpIcon {
5+
transform: rotate(180deg);
6+
opacity: 0.6;
7+
height: 10px;
8+
}
9+
10+
&.open .arrowUpIcon {
11+
transform: rotate(0deg);
12+
}
13+
14+
&.open > div > .navItem {
15+
box-shadow: 0 4px 4px -4px #777;
16+
position: relative;
17+
z-index: 1;
18+
}
19+
20+
&.open+li {
21+
box-shadow: 0 -4px 4px -4px #777;
22+
position: relative;
23+
z-index: 1;
24+
}
25+
}
26+
327
.navItem {
428
@include roboto;
529

@@ -10,6 +34,7 @@
1034
margin-right: -1px;
1135
position: relative;
1236
font-size: 14px;
37+
cursor: pointer;
1338

1439
&,
1540
&:avtive,
@@ -19,6 +44,13 @@
1944
}
2045
}
2146

47+
.childNavItem {
48+
a {
49+
padding-left: 40px;
50+
font-size: 12px;
51+
}
52+
}
53+
2254
.left,
2355
.right {
2456
display: flex;
@@ -48,7 +80,11 @@
4880
fill: #0AB88A;
4981
}
5082

51-
.active {
83+
.arrowUpIcon {
84+
float: right;
85+
}
86+
87+
.active:not(.activeParent) {
5288
@include roboto-bold;
5389
background-color: $tc-gray-neutral-dark;
5490
color: $tc-gray-90;

src/components/MenuList/MenuList.jsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ import MenuItem from '../MenuItem/MenuItem'
55

66
import styles from './MenuList.scss'
77

8-
const MenuList = ({ navLinks }) => (
8+
const MenuList = ({ navLinks, onAccordionToggle }) => (
99
<nav className={styles.container}>
1010
<ul>
1111
{!!navLinks &&
12-
navLinks.map((link, i) => <MenuItem key={i} {...link} />)}
12+
navLinks.map((link, i) => <MenuItem key={i} {...link} onAccordionToggle={(open) => onAccordionToggle(i, open)} />)}
1313
</ul>
1414
</nav>
1515
)
@@ -23,7 +23,8 @@ MenuList.propTypes = {
2323
exact: PT.bool,
2424
isActive: PT.func
2525
})
26-
)
26+
),
27+
onAccordionToggle: PT.func.isRequired
2728
}
2829

2930
export default MenuList
Lines changed: 80 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
import React from 'react'
22
import PropTypes from 'prop-types'
3+
import update from 'react-addons-update'
4+
import { findIndex, some } from 'lodash'
5+
import { withRouter } from 'react-router-dom'
6+
37
import UserSummary from '../UserSummary/UserSummary'
48
import MenuList from '../MenuList/MenuList'
59
import NotificationsIcon from '../../assets/icons/ui-bell.svg'
@@ -21,37 +25,93 @@ const navLinks = [{
2125
to: '/settings/profile',
2226
Icon: MyProfileIcon,
2327
iconClassName: 'fill',
24-
}, {
25-
label: 'NOTIFICATION SETTINGS',
26-
to: '/settings/notifications',
27-
Icon: NotificationSettingsIcon,
28-
iconClassName: 'fill',
29-
}, {
30-
label: 'ACCOUNT & SECURITY',
31-
to: '/settings/account',
32-
Icon: AccountSecurityIcon,
33-
iconClassName: 'fill',
28+
children: [
29+
{
30+
label: 'PROFILE INFORMATION',
31+
to: '/settings/profile',
32+
Icon: MyProfileIcon,
33+
iconClassName: 'fill',
34+
},
35+
{
36+
label: 'NOTIFICATION SETTINGS',
37+
to: '/settings/notifications',
38+
Icon: NotificationSettingsIcon,
39+
iconClassName: 'fill',
40+
}, {
41+
label: 'ACCOUNT & SECURITY',
42+
to: '/settings/account',
43+
Icon: AccountSecurityIcon,
44+
iconClassName: 'fill',
45+
}
46+
]
3447
}, {
3548
label: 'NOTIFICATIONS',
3649
to: '/notifications',
3750
Icon: NotificationsIcon,
3851
iconClassName: 'fill',
3952
}]
4053

41-
const UserSidebar = ({user}) => {
42-
return (
43-
<div styleName="container">
44-
<div className="sideAreaWrapper">
45-
<UserSummary user={user}/>
46-
<hr styleName="separator"/>
47-
<MenuList navLinks={navLinks}/>
54+
class UserSidebar extends React.Component {
55+
constructor(props) {
56+
super(props)
57+
this.state = {
58+
navLinks
59+
}
60+
}
61+
62+
componentDidMount() {
63+
this.initAccordion()
64+
}
65+
66+
initAccordion() {
67+
const {match} = this.props
68+
const {navLinks} = this.state
69+
70+
const matchedPath = match && match.path
71+
const activeNavIndex = findIndex(navLinks, nav => nav.children && some(nav.children, c => c.to === matchedPath))
72+
73+
if (activeNavIndex >= 0) {
74+
this.setAccordionOpen(activeNavIndex, true)
75+
}
76+
}
77+
78+
setAccordionOpen(i, open) {
79+
const { navLinks } = this.state
80+
const updatedNavLinks = update(navLinks, {
81+
[i]: {
82+
$set: {
83+
...navLinks[i],
84+
isAccordionOpen: open
85+
}
86+
}
87+
})
88+
89+
this.setState({
90+
navLinks: updatedNavLinks
91+
})
92+
}
93+
94+
render() {
95+
const {user} = this.props
96+
const {navLinks} = this.state
97+
98+
return (
99+
<div styleName="container">
100+
<div className="sideAreaWrapper">
101+
<UserSummary user={user}/>
102+
<hr styleName="separator"/>
103+
<div styleName="section-title">
104+
SYSTEM
105+
</div>
106+
<MenuList navLinks={navLinks} onAccordionToggle={(i, open) => this.setAccordionOpen(i, open)} />
107+
</div>
48108
</div>
49-
</div>
50-
)
109+
)
110+
}
51111
}
52112

53113
UserSidebar.propTypes = {
54114
user: PropTypes.object.isRequired
55115
}
56116

57-
export default UserSidebar
117+
export default withRouter(UserSidebar)

0 commit comments

Comments
 (0)