Skip to content

Commit 64aabb7

Browse files
committed
Merge branch 'dev' into cf19
# Conflicts: # src/components/MenuItem/MenuItem.jsx
2 parents 5149a08 + 4559bb1 commit 64aabb7

File tree

10 files changed

+7523
-6406
lines changed

10 files changed

+7523
-6406
lines changed

package-lock.json

Lines changed: 7279 additions & 6311 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 78 additions & 23 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,29 +17,77 @@ const MenuItem = ({
1417
exact,
1518
isActive,
1619
count,
17-
toolTipText
18-
}) => (
19-
<li>
20-
<NavLink
21-
to={to}
22-
className={styles.navItem}
23-
activeClassName={styles.active}
24-
exact={exact}
25-
isActive={isActive}
20+
children,
21+
isAccordionOpen,
22+
onAccordionToggle,
23+
match,
24+
wrapperClass,
25+
toolTipText,
26+
}) => {
27+
const matchedPath = match && match.path
28+
const isChildActive = children && some(children, c => c.to === matchedPath)
29+
30+
return (
31+
<li className={
32+
cn(wrapperClass,
33+
styles.menuItem,
34+
{ [styles.open]: isAccordionOpen, [styles.withChildren]: children })}
2635
>
27-
<span styleName="left">
28-
{!!Icon && <Icon className={cn(styles.icon, styles[iconClassName])} />}
29-
{label}
30-
</span>
31-
<span styleName="right">
32-
{!!count && <NotificationBadge count={count} text={toolTipText} />}
33-
</span>
34-
</NavLink>
35-
</li>
36-
)
36+
{!children && (
37+
<NavLink
38+
to={to}
39+
className={styles.navItem}
40+
activeClassName={styles.active}
41+
exact={exact}
42+
isActive={isActive}
43+
>
44+
<span styleName="left">
45+
{!!Icon && (
46+
<Icon className={cn(styles.icon, styles[iconClassName])} />
47+
)}
48+
{label}
49+
</span>
50+
<span styleName="right">
51+
{!!count && <NotificationBadge count={count} text={toolTipText} />}
52+
</span>
53+
</NavLink>
54+
)}
55+
56+
{children && (
57+
<div>
58+
<div
59+
className={cn(styles.navItem, {
60+
[styles.activeParent]: isChildActive,
61+
[styles.active]: isChildActive
62+
})}
63+
onClick={() => onAccordionToggle(!isAccordionOpen)}
64+
>
65+
<span styleName="left">
66+
{!!Icon && (
67+
<Icon className={cn(styles.icon, styles[iconClassName])} />
68+
)}
69+
{label}
70+
</span>
71+
<span styleName="right">
72+
{!!count && <NotificationBadge count={count} text={toolTipText} />}
73+
</span>
74+
75+
<ArrowUpIcon className={styles.arrowUpIcon} />
76+
</div>
77+
78+
{isAccordionOpen &&
79+
<ul>
80+
{ children.map(c => <MenuItem {...c} key={c.to} wrapperClass={styles.childNavItem} />) }
81+
</ul>
82+
}
83+
</div>
84+
)}
85+
</li>
86+
)
87+
}
3788

3889
MenuItem.defaultProps = {
39-
exact: true,
90+
exact: true
4091
}
4192

4293
MenuItem.propTypes = {
@@ -47,7 +98,11 @@ MenuItem.propTypes = {
4798
exact: PT.bool,
4899
isActive: PT.func,
49100
count: PT.number,
50-
toolTipText: PT.string
101+
children: PT.array,
102+
isAccordionOpen: PT.bool,
103+
onAccordionToggle: PT.func,
104+
wrapperClass: PT.string,
105+
toolTipText: PT.string,
51106
}
52107

53-
export default MenuItem
108+
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
)
@@ -24,7 +24,8 @@ MenuList.propTypes = {
2424
isActive: PT.func,
2525
toolTipText: PT.string
2626
})
27-
)
27+
),
28+
onAccordionToggle: PT.func.isRequired
2829
}
2930

3031
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)

src/projects/detail/components/Accordion/Accordion.jsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import './Accordion.scss'
2020
* Supported types of questions
2121
*/
2222
const TYPE = {
23+
CHECKBOX: 'checkbox',
2324
CHECKBOX_GROUP: 'checkbox-group',
2425
RADIO_GROUP: 'radio-group',
2526
ADD_ONS: 'add-ons',
@@ -150,6 +151,7 @@ class Accordion extends React.Component {
150151
}
151152

152153
switch (type) {
154+
case TYPE.CHECKBOX: return value ? 'Yes' : 'No'
153155
case TYPE.CHECKBOX_GROUP: return value.map(mapValue).join(', ')
154156
case TYPE.RADIO_GROUP: return mapValue(value)
155157
case TYPE.ADD_ONS: return `${value.length} selected`

src/projects/detail/components/SpecQuestions.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,7 @@ class SpecQuestions extends React.Component {
401401
(isCreation || !question.hiddenOnEdit)
402402
).map((q, index) => {
403403
return (
404-
_.includes(['checkbox-group', 'radio-group', 'add-ons', 'textinput', 'textbox', 'numberinput', 'skills', 'slide-radiogroup', 'slider-standard', 'select-dropdown'], q.type) && q.visibilityForRendering === STEP_VISIBILITY.READ_OPTIMIZED ? (
404+
_.includes(['checkbox', 'checkbox-group', 'radio-group', 'add-ons', 'textinput', 'textbox', 'numberinput', 'skills', 'slide-radiogroup', 'slider-standard', 'select-dropdown'], q.type) && q.visibilityForRendering === STEP_VISIBILITY.READ_OPTIMIZED ? (
405405
<Accordion
406406
key={q.fieldName || `accordion-${index}`}
407407
title={q.summaryTitle || q.title}

0 commit comments

Comments
 (0)