Skip to content

Commit 4642422

Browse files
authored
Merge pull request #4071 from appirio-tech/dev
Connect Release 2.11.0
2 parents e1ccbae + 597fa5a commit 4642422

30 files changed

+896
-493
lines changed

.circleci/config.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -128,15 +128,15 @@ workflows:
128128
- build-dev
129129
filters:
130130
branches:
131-
only: ['dev', 'dev-msinteg']
131+
only: ['dev']
132132

133133
- deployTest01:
134134
context : org-global
135135
requires:
136136
- build-dev
137137
filters:
138138
branches:
139-
only: ['feature/bulk-milestone-updates']
139+
only: ['feature/faqs']
140140

141141
- deployProd:
142142
context : org-global

config/constants/dev.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -49,5 +49,9 @@ module.exports = {
4949
TC_SYSTEM_USERID: process.env.DEV_TC_SYSTEM_USERID,
5050
MAINTENANCE_MODE: process.env.DEV_MAINTENANCE_MODE,
5151

52-
TC_CDN_URL: process.env.TC_CDN_URL
52+
TC_CDN_URL: process.env.TC_CDN_URL,
53+
54+
DASHBOARD_FAQ_CONTENT_ID : process.env.DASHBOARD_FAQ_CONTENT_ID,
55+
CONTENTFUL_DELIVERY_KEY : process.env.CONTENTFUL_DELIVERY_KEY,
56+
CONTENTFUL_SPACE_ID : process.env.CONTENTFUL_SPACE_ID
5357
}

config/constants/master.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -49,5 +49,9 @@ module.exports = {
4949
TC_SYSTEM_USERID: process.env.PROD_TC_SYSTEM_USERID,
5050
MAINTENANCE_MODE: process.env.PROD_MAINTENANCE_MODE,
5151

52-
TC_CDN_URL: process.env.TC_CDN_URL
52+
TC_CDN_URL: process.env.TC_CDN_URL,
53+
54+
DASHBOARD_FAQ_CONTENT_ID : process.env.DASHBOARD_FAQ_CONTENT_ID,
55+
CONTENTFUL_DELIVERY_KEY : process.env.CONTENTFUL_DELIVERY_KEY,
56+
CONTENTFUL_SPACE_ID : process.env.CONTENTFUL_SPACE_ID
5357
}

package-lock.json

+372-394
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+2
Original file line numberDiff line numberDiff line change
@@ -83,11 +83,13 @@
8383
"webpack-merge": "^4.1.1"
8484
},
8585
"dependencies": {
86+
"@contentful/rich-text-react-renderer": "^13.4.0",
8687
"appirio-tech-react-components": "git+https://github.com/appirio-tech/react-components.git#feature/connectv2",
8788
"axios": "^0.19.2",
8889
"brace": "^0.11.1",
8990
"classnames": "^2.2.3",
9091
"coffeescript": "^1.12.7",
92+
"contentful": "^7.14.4",
9193
"draft-js": "0.10.5",
9294
"draft-js-drag-n-drop-plugin": "^2.0.0-rc2",
9395
"draft-js-image-plugin": "^2.0.0-rc2",

src/api/contentful.js

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { createClient } from 'contentful'
2+
import { CONTENTFUL_DELIVERY_KEY, CONTENTFUL_SPACE_ID } from '../config/constants'
3+
4+
export function getClient() {
5+
return createClient({
6+
space: CONTENTFUL_SPACE_ID,
7+
accessToken: CONTENTFUL_DELIVERY_KEY,
8+
})
9+
}
10+
11+
export function getEntry(id) {
12+
const client = getClient()
13+
return client.getEntry(id, { include: 10 })
14+
}

src/assets/icons/faq.svg

+18
Loading

src/components/FAQ/FAQContainer.jsx

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import React, { Component } from 'react'
2+
import FAQItem from './FAQItem'
3+
import { getEntry } from '../../api/contentful'
4+
import spinnerWhileLoading from '../../components/LoadingSpinner'
5+
import './FAQContainer.scss'
6+
7+
8+
const FAQList = ({ entry }) => (
9+
<div styleName="faq-list-container">
10+
{
11+
entry.fields.items.map((item, idx) => {
12+
return (
13+
<FAQItem key={idx} item={item} />
14+
)}
15+
)
16+
}
17+
</div>
18+
)
19+
20+
const EnhancedFAQContainer = spinnerWhileLoading(props => {
21+
return !props.isLoading
22+
})(FAQList)
23+
24+
class FAQContainer extends Component {
25+
constructor(props) {
26+
super(props)
27+
this.state = {
28+
faqs: null,
29+
isLoading: true
30+
}
31+
}
32+
33+
componentWillMount() {
34+
getEntry(this.props.contentKey).then((entry) => {
35+
this.setState({ faqs: entry, isLoading: false })
36+
})
37+
}
38+
39+
render() {
40+
const { pageTitle } = this.props
41+
const { faqs, isLoading } = this.state
42+
43+
return (
44+
<div styleName="main">
45+
<h1 styleName="title">{pageTitle}</h1>
46+
<div styleName="content">
47+
<EnhancedFAQContainer entry={faqs} isLoading={isLoading} />
48+
</div>
49+
</div>
50+
)
51+
}
52+
}
53+
54+
export default FAQContainer

src/components/FAQ/FAQContainer.scss

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
@import '~tc-ui/src/styles/tc-includes';
2+
@import "../../styles/includes";
3+
4+
5+
.faq-list-container {
6+
7+
}
8+
9+
.accordion {
10+
& + & {
11+
margin-top: 2 * $base-unit;
12+
}
13+
}
14+
15+
.main {
16+
background-color: $tc-white;
17+
border-radius: 6px;
18+
max-width: 960px;
19+
padding: 35px 35px 20px 35px;
20+
flex-grow: 1;
21+
margin: auto;
22+
margin-top: 20px;
23+
margin-bottom: 260px; // gives space to show country selection list
24+
25+
@media screen and (max-width: $screen-md - 1px) {
26+
padding: 0;
27+
margin: 0;
28+
max-width: none;
29+
margin-bottom: 260px; // gives space to show country selection list in mobile view
30+
}
31+
}
32+
33+
.title {
34+
font-weight: 400;
35+
@include roboto-condensed;
36+
color: $tc-black;
37+
font-size: 20px;
38+
line-height: 30px;
39+
text-align: left;
40+
text-transform: uppercase;
41+
42+
@media screen and (max-width: $screen-md - 1px) {
43+
display: none;
44+
}
45+
}
46+
47+
.content {
48+
margin-top: 25px;
49+
@media screen and (max-width: $screen-md - 1px) {
50+
margin-top: 0;
51+
}
52+
}

src/components/FAQ/FAQItem.jsx

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import React, { Component } from 'react'
2+
import cn from 'classnames'
3+
import { documentToReactComponents } from '@contentful/rich-text-react-renderer'
4+
import IconX from ' ../../assets/icons/ui-x-mark.svg'
5+
import IconCarretDown from '../../assets/icons/arrow-6px-carret-down-normal.svg'
6+
import { CONTENTFUL_NODE_TYPES } from '../../config/constants'
7+
import './FAQItem.scss'
8+
9+
10+
class FAQItem extends Component {
11+
constructor(props) {
12+
super(props)
13+
this.state = { isOpen : false }
14+
15+
this.toggle = this.toggle.bind(this)
16+
}
17+
18+
toggle(evt) {
19+
evt.preventDefault()
20+
21+
this.setState({
22+
isOpen: !this.state.isOpen
23+
})
24+
}
25+
26+
render() {
27+
const {item} = this.props
28+
const {isOpen} = this.state
29+
30+
const FormattedHyperLink = ({ value, url }) => <a href={url} target="_blank" className="hyperlink-style">{value}</a>
31+
const options = {
32+
renderNode: {/* eslint-disable no-unused-vars*/
33+
[CONTENTFUL_NODE_TYPES.HYPERLINK]: (node, children) => <FormattedHyperLink value={node.content[0].value} url={node.data.uri}/>
34+
}
35+
}
36+
return (
37+
<div styleName={cn('accordion', { 'is-open': isOpen })}>
38+
<div styleName="header" onClick={this.toggle}>
39+
<div styleName="title">{item.fields.question}</div>
40+
<div styleName="toggle">
41+
{isOpen ? <IconX styleName="toggle-icon" /> : <IconCarretDown styleName="toggle-icon" />}
42+
</div>
43+
</div>
44+
<div styleName="content">{documentToReactComponents(item.fields.answer, options)}</div>
45+
</div>
46+
)
47+
}
48+
}
49+
50+
export default FAQItem

src/components/FAQ/FAQItem.scss

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
@import '~tc-ui/src/styles/tc-includes';
2+
3+
.accordion {
4+
border: 1px solid $tc-gray-neutral-dark;
5+
border-radius: 3px;
6+
padding-left: 5 * $base-unit;
7+
8+
& + & {
9+
margin-top: 2 * $base-unit;
10+
}
11+
}
12+
13+
14+
.accordion .header {
15+
align-items: center;
16+
cursor: pointer;
17+
display: flex;
18+
justify-content: space-between;
19+
height: 8 * $base-unit;
20+
padding: 0;
21+
text-align: left;
22+
width: 100%;
23+
}
24+
25+
.accordion .title {
26+
@include roboto-bold;
27+
font-size: $tc-label-md;
28+
overflow: hidden;
29+
line-height: 3 * $base-unit;
30+
text-overflow: ellipsis;
31+
white-space: nowrap;
32+
}
33+
34+
.accordion .value {
35+
@include roboto;
36+
color: $tc-gray-80;
37+
flex: 1 0 auto;
38+
font-size: $tc-label-lg;
39+
text-overflow: ellipsis;
40+
white-space: nowrap;
41+
width: 0;
42+
}
43+
44+
.accordion .toggle {
45+
align-items: center;
46+
display: flex;
47+
justify-content: center;
48+
height: 36px;
49+
width: 36px;
50+
}
51+
52+
.accordion .toggle-icon {
53+
height: auto;
54+
width: 10px;
55+
}
56+
57+
.accordion .content {
58+
display: none;
59+
color: $tc-gray-70;
60+
@include roboto;
61+
font-size: $tc-label-md;
62+
line-height: 20px;
63+
text-align: left;
64+
margin-bottom: 2 * $base-unit;
65+
66+
a {
67+
cursor: pointer;
68+
color: $tc-dark-blue;
69+
&:hover {
70+
text-decoration: underline;
71+
}
72+
}
73+
}
74+
75+
.accordion.is-open .content {
76+
display: block;
77+
}

src/components/Footer/Footer.jsx

+8-8
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
11
import React from 'react'
2-
import MenuBar from 'appirio-tech-react-components/components/MenuBar/MenuBar'
2+
//import MenuBar from 'appirio-tech-react-components/components/MenuBar/MenuBar'
33
import moment from 'moment'
44
import MediaQuery from 'react-responsive'
5-
import FooterV2 from '../FooterV2/FooterV2'
5+
//import FooterV2 from '../FooterV2/FooterV2'
66
import { NEW_PROJECT_PATH, SCREEN_BREAKPOINT_MD } from '../../config/constants'
77

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

1010
const Footer = () => {
1111
const currentYear = moment().format('YYYY')
12-
const otherNavigationItems = [
13-
{img: '', text: 'About', link: 'https://www.topcoder.com/company/', target: '_blank'},
12+
/*const otherNavigationItems = [
13+
{img: '', text: 'Aboutss', link: 'https://www.topcoder.com/company/', target: '_blank'},
1414
{img: '', text: 'Contact us', link: 'https://www.topcoder.com/contact-us/', target: '_blank'},
1515
{img: '', text: 'Privacy', link: 'https://www.topcoder.com/privacy-policy/', target: '_blank'},
1616
{img: '', text: 'Terms', link: 'https://connect.topcoder.com/terms', target: '_blank'},
1717
{img: '', text: 'Our Process', link: 'https://www.topcoder.com/solutions/how-it-works/', target: '_blank'}
18-
]
18+
]*/
1919
const isProjectDetails = /projects\/\d+/.test(window.location.pathname)
2020
const isCreateProject = window.location.pathname.startsWith(NEW_PROJECT_PATH)
2121
const isNotificationsPage = window.location.pathname.startsWith('/notifications')
@@ -33,14 +33,14 @@ const Footer = () => {
3333
return (shouldHideOnDesktop ? null :
3434
<div className="Footer">
3535
<p className="copyright-notice">© Topcoder { currentYear }</p>
36-
<div className="footer-menu">
36+
{/*<div className="footer-menu">
3737
<MenuBar items={otherNavigationItems} orientation="horizontal" mobileBreakPoint={SCREEN_BREAKPOINT_MD - 1} />
38-
</div>
38+
</div>*/}
3939
</div>
4040
)
4141
} else {
4242
return (shouldHideOnMobile ? null :
43-
<FooterV2 />
43+
{/*<FooterV2 />*/}
4444
)
4545
}
4646
}}

0 commit comments

Comments
 (0)