Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 2 additions & 2 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -128,15 +128,15 @@ workflows:
- build-dev
filters:
branches:
only: ['dev', 'dev-msinteg']
only: ['dev']

- deployTest01:
context : org-global
requires:
- build-dev
filters:
branches:
only: ['feature/bulk-milestone-updates']
only: ['feature/faqs']

- deployProd:
context : org-global
Expand Down
6 changes: 5 additions & 1 deletion config/constants/dev.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,9 @@ module.exports = {
TC_SYSTEM_USERID: process.env.DEV_TC_SYSTEM_USERID,
MAINTENANCE_MODE: process.env.DEV_MAINTENANCE_MODE,

TC_CDN_URL: process.env.TC_CDN_URL
TC_CDN_URL: process.env.TC_CDN_URL,

DASHBOARD_FAQ_CONTENT_ID : process.env.DASHBOARD_FAQ_CONTENT_ID,
CONTENTFUL_DELIVERY_KEY : process.env.CONTENTFUL_DELIVERY_KEY,
CONTENTFUL_SPACE_ID : process.env.CONTENTFUL_SPACE_ID
}
6 changes: 5 additions & 1 deletion config/constants/master.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,9 @@ module.exports = {
TC_SYSTEM_USERID: process.env.PROD_TC_SYSTEM_USERID,
MAINTENANCE_MODE: process.env.PROD_MAINTENANCE_MODE,

TC_CDN_URL: process.env.TC_CDN_URL
TC_CDN_URL: process.env.TC_CDN_URL,

DASHBOARD_FAQ_CONTENT_ID : process.env.DASHBOARD_FAQ_CONTENT_ID,
CONTENTFUL_DELIVERY_KEY : process.env.CONTENTFUL_DELIVERY_KEY,
CONTENTFUL_SPACE_ID : process.env.CONTENTFUL_SPACE_ID
}
766 changes: 372 additions & 394 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,13 @@
"webpack-merge": "^4.1.1"
},
"dependencies": {
"@contentful/rich-text-react-renderer": "^13.4.0",
"appirio-tech-react-components": "git+https://github.com/appirio-tech/react-components.git#feature/connectv2",
"axios": "^0.19.2",
"brace": "^0.11.1",
"classnames": "^2.2.3",
"coffeescript": "^1.12.7",
"contentful": "^7.14.4",
"draft-js": "0.10.5",
"draft-js-drag-n-drop-plugin": "^2.0.0-rc2",
"draft-js-image-plugin": "^2.0.0-rc2",
Expand Down
14 changes: 14 additions & 0 deletions src/api/contentful.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { createClient } from 'contentful'
import { CONTENTFUL_DELIVERY_KEY, CONTENTFUL_SPACE_ID } from '../config/constants'

export function getClient() {
return createClient({
space: CONTENTFUL_SPACE_ID,
accessToken: CONTENTFUL_DELIVERY_KEY,
})
}

export function getEntry(id) {
const client = getClient()
return client.getEntry(id, { include: 10 })
}
18 changes: 18 additions & 0 deletions src/assets/icons/faq.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
54 changes: 54 additions & 0 deletions src/components/FAQ/FAQContainer.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import React, { Component } from 'react'
import FAQItem from './FAQItem'
import { getEntry } from '../../api/contentful'
import spinnerWhileLoading from '../../components/LoadingSpinner'
import './FAQContainer.scss'


const FAQList = ({ entry }) => (
<div styleName="faq-list-container">
{
entry.fields.items.map((item, idx) => {
return (
<FAQItem key={idx} item={item} />
)}
)
}
</div>
)

const EnhancedFAQContainer = spinnerWhileLoading(props => {
return !props.isLoading
})(FAQList)

class FAQContainer extends Component {
constructor(props) {
super(props)
this.state = {
faqs: null,
isLoading: true
}
}

componentWillMount() {
getEntry(this.props.contentKey).then((entry) => {
this.setState({ faqs: entry, isLoading: false })
})
}

render() {
const { pageTitle } = this.props
const { faqs, isLoading } = this.state

return (
<div styleName="main">
<h1 styleName="title">{pageTitle}</h1>
<div styleName="content">
<EnhancedFAQContainer entry={faqs} isLoading={isLoading} />
</div>
</div>
)
}
}

export default FAQContainer
52 changes: 52 additions & 0 deletions src/components/FAQ/FAQContainer.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
@import '~tc-ui/src/styles/tc-includes';
@import "../../styles/includes";


.faq-list-container {

}

.accordion {
& + & {
margin-top: 2 * $base-unit;
}
}

.main {
background-color: $tc-white;
border-radius: 6px;
max-width: 960px;
padding: 35px 35px 20px 35px;
flex-grow: 1;
margin: auto;
margin-top: 20px;
margin-bottom: 260px; // gives space to show country selection list

@media screen and (max-width: $screen-md - 1px) {
padding: 0;
margin: 0;
max-width: none;
margin-bottom: 260px; // gives space to show country selection list in mobile view
}
}

.title {
font-weight: 400;
@include roboto-condensed;
color: $tc-black;
font-size: 20px;
line-height: 30px;
text-align: left;
text-transform: uppercase;

@media screen and (max-width: $screen-md - 1px) {
display: none;
}
}

.content {
margin-top: 25px;
@media screen and (max-width: $screen-md - 1px) {
margin-top: 0;
}
}
42 changes: 42 additions & 0 deletions src/components/FAQ/FAQItem.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import React, { Component } from 'react'
import cn from 'classnames'
import { documentToReactComponents } from '@contentful/rich-text-react-renderer'
import IconX from ' ../../assets/icons/ui-x-mark.svg'
import IconCarretDown from '../../assets/icons/arrow-6px-carret-down-normal.svg'
import './FAQItem.scss'


class FAQItem extends Component {
constructor(props) {
super(props)
this.state = { isOpen : false }

this.toggle = this.toggle.bind(this)
}

toggle(evt) {
evt.preventDefault()

this.setState({
isOpen: !this.state.isOpen
})
}

render() {
const {item} = this.props
const {isOpen} = this.state
return (
<div styleName={cn('accordion', { 'is-open': isOpen })}>
<div styleName="header" onClick={this.toggle}>
<div styleName="title">{item.fields.question}</div>
<div styleName="toggle">
{isOpen ? <IconX styleName="toggle-icon" /> : <IconCarretDown styleName="toggle-icon" />}
</div>
</div>
<div styleName="content">{documentToReactComponents(item.fields.answer)}</div>
</div>
)
}
}

export default FAQItem
69 changes: 69 additions & 0 deletions src/components/FAQ/FAQItem.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
@import '~tc-ui/src/styles/tc-includes';

.accordion {
border: 1px solid $tc-gray-neutral-dark;
border-radius: 3px;
padding-left: 5 * $base-unit;

& + & {
margin-top: 2 * $base-unit;
}
}


.accordion .header {
align-items: center;
cursor: pointer;
display: flex;
justify-content: space-between;
height: 8 * $base-unit;
padding: 0;
text-align: left;
width: 100%;
}

.accordion .title {
@include roboto-bold;
font-size: $tc-label-md;
overflow: hidden;
line-height: 3 * $base-unit;
text-overflow: ellipsis;
white-space: nowrap;
}

.accordion .value {
@include roboto;
color: $tc-gray-80;
flex: 1 0 auto;
font-size: $tc-label-lg;
text-overflow: ellipsis;
white-space: nowrap;
width: 0;
}

.accordion .toggle {
align-items: center;
display: flex;
justify-content: center;
height: 36px;
width: 36px;
}

.accordion .toggle-icon {
height: auto;
width: 10px;
}

.accordion .content {
display: none;
color: $tc-gray-70;
@include roboto;
font-size: $tc-label-md;
line-height: 20px;
text-align: left;
margin-bottom: 2 * $base-unit;
}

.accordion.is-open .content {
display: block;
}
6 changes: 6 additions & 0 deletions src/components/UserSidebar/UserSidebar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { withRouter } from 'react-router-dom'
import UserSummary from '../UserSummary/UserSummary'
import MenuList from '../MenuList/MenuList'
import NotificationsIcon from '../../assets/icons/ui-bell.svg'
import FAQIcon from '../../assets/icons/faq.svg'
import AllProjectsIcon from '../../assets/icons/v.2.5/icon-all-projects.svg'
import MyProfileIcon from '../../assets/icons/v.2.5/icon-my-profile.svg'
import ReportsIcon from '../../assets/icons/v.2.5/icon-reports.svg'
Expand Down Expand Up @@ -56,6 +57,11 @@ const navLinks = [{
to: '/notifications',
Icon: NotificationsIcon,
iconClassName: 'fill',
}, {
label: 'HOW TOPCODER WORKS',
to: '/faqs',
Icon: FAQIcon,
iconClassName: 'fill',
}]

class UserSidebar extends React.Component {
Expand Down
8 changes: 8 additions & 0 deletions src/config/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -985,3 +985,11 @@ export const PROJECT_REPORTS = {
* Report session length in seconds
*/
export const REPORT_SESSION_LENGTH = 25 * 60 // 25 minutes (5 minutes less than the report session)


/**
* Contentful Content Ids
*/
export const DASHBOARD_FAQ_CONTENT_ID = process.env.DASHBOARD_FAQ_CONTENT_ID
export const CONTENTFUL_DELIVERY_KEY = process.env.CONTENTFUL_DELIVERY_KEY
export const CONTENTFUL_SPACE_ID = process.env.CONTENTFUL_SPACE_ID
2 changes: 2 additions & 0 deletions src/helpers/projectHelper.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import DashboardIcon from '../assets/icons/v.2.5/icon-dashboard.svg'
import MessagesIcon from '../assets/icons/v.2.5/icon-messages.svg'
import ReportsIcon from '../assets/icons/v.2.5/icon-reports.svg'
import AssetsLibraryIcon from '../assets/icons/v.2.5/icon-assets-library.svg'
import FAQIcon from '../assets/icons/faq.svg'
import InvisibleIcon from '../assets/icons/invisible.svg'

import { formatNumberWithCommas } from './format'
Expand Down Expand Up @@ -282,6 +283,7 @@ export function getProjectNavLinks(project, projectId) {
// Commented out till it needs to go live.
{ label: 'Reports', to: `/projects/${projectId}/reports`, Icon: ReportsIcon, iconClassName: 'stroke' },
{ label: 'Assets Library', to: `/projects/${projectId}/assets`, Icon: AssetsLibraryIcon, iconClassName: 'stroke' },
{ label: 'FAQ', to: `/projects/${projectId}/faqs`, Icon: FAQIcon, iconClassName: 'fill' },
] : [
{ label: 'Dashboard', to: `/projects/${projectId}`, Icon: DashboardIcon, iconClassName: 'stroke' },
messagesTab,
Expand Down
Loading