Skip to content

Commit 82c2815

Browse files
author
vikasrohit
authored
Merge pull request #928 from topcoder-platform/develop
Prod push
2 parents 26852da + a0c938a commit 82c2815

File tree

18 files changed

+306
-10124
lines changed

18 files changed

+306
-10124
lines changed

.nvmrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
10.22.1

package-lock.json

Lines changed: 30 additions & 10073 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"@fortawesome/fontawesome-svg-core": "^1.2.14",
88
"@fortawesome/free-solid-svg-icons": "^5.7.1",
99
"@fortawesome/react-fontawesome": "^0.1.4",
10+
"@popperjs/core": "^2.5.4",
1011
"@svgr/webpack": "2.4.1",
1112
"axios": "^0.19.0",
1213
"babel-core": "7.0.0-bridge.0",
@@ -74,6 +75,7 @@
7475
"react-google-charts": "^3.0.13",
7576
"react-helmet": "^5.2.0",
7677
"react-js-pagination": "^3.0.3",
78+
"react-popper": "^2.2.4",
7779
"react-redux": "^6.0.0",
7880
"react-redux-toastr": "^7.5.1",
7981
"react-router-dom": "^4.3.1",

src/components/Buttons/PrimaryButton/PrimaryButton.module.scss

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,16 @@
4444
background-color: $inactive;
4545
}
4646
}
47+
48+
/* this style just visually simulates the disable status of the button */
49+
&.disabled {
50+
cursor: default;
51+
background-color: $inactive;
52+
53+
// override possible styles for
54+
&:not(:disabled),
55+
&:disabled {
56+
cursor: default;
57+
}
58+
}
4759
}

src/components/Buttons/PrimaryButton/index.js

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,28 +6,50 @@ import cn from 'classnames'
66

77
import styles from './PrimaryButton.module.scss'
88

9-
const PrimaryButton = ({ type, text, link, onClick, submit, disabled }) => {
10-
if (_.isEmpty(link)) {
9+
const PrimaryButton = React.forwardRef(
10+
(
11+
{ type, text, link, onClick, submit, disabled, onMouseEnter, onMouseLeave },
12+
ref
13+
) => {
14+
if (_.isEmpty(link)) {
15+
return (
16+
<button
17+
type={submit ? 'submit' : 'button'}
18+
className={cn(styles.container, styles[type])}
19+
onClick={submit ? null : onClick}
20+
disabled={disabled}
21+
onMouseEnter={onMouseEnter}
22+
onMouseLeave={onMouseLeave}
23+
ref={ref}
24+
>
25+
<span>{text}</span>
26+
</button>
27+
)
28+
}
1129
return (
12-
<button type={submit ? 'submit' : 'button'} className={cn(styles.container, styles[type])} onClick={submit ? null : onClick} disabled={disabled}>
30+
<Link
31+
className={cn(styles.container, styles[type])}
32+
to={`${link}`}
33+
ref={ref}
34+
onMouseEnter={onMouseEnter}
35+
onMouseLeave={onMouseLeave}
36+
>
1337
<span>{text}</span>
14-
</button>
38+
</Link>
1539
)
1640
}
17-
return (
18-
<Link className={cn(styles.container, styles[type])} to={`${link}`}>
19-
<span>{text}</span>
20-
</Link>
21-
)
22-
}
41+
)
2342

2443
PrimaryButton.propTypes = {
2544
type: PropTypes.string.isRequired,
2645
text: PropTypes.string.isRequired,
2746
link: PropTypes.string,
2847
onClick: PropTypes.func,
2948
submit: PropTypes.bool,
30-
disabled: PropTypes.bool
49+
disabled: PropTypes.bool,
50+
onMouseEnter: PropTypes.func,
51+
onMouseLeave: PropTypes.func,
52+
innerRef: PropTypes.any
3153
}
3254

3355
export default PrimaryButton

src/components/ChallengeEditor/ChallengePrizes-Field/index.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import PrizeInput from '../../PrizeInput'
88
import styles from './ChallengePrizes-Field.module.scss'
99
import cn from 'classnames'
1010
import { PrimaryButton } from '../../Buttons'
11-
import { CHALLENGE_PRIZE_TYPE, VALIDATION_VALUE_TYPE, PRIZE_SETS_TYPE } from '../../../config/constants'
11+
import { CHALLENGE_PRIZE_TYPE, VALIDATION_VALUE_TYPE, PRIZE_SETS_TYPE, CHALLENGE_TYPES_WITH_MULTIPLE_PRIZES } from '../../../config/constants'
1212
import { validateValue } from '../../../util/input-check'
1313

1414
class ChallengePrizesField extends Component {
@@ -61,12 +61,12 @@ class ChallengePrizesField extends Component {
6161
renderPrizes () {
6262
const { currentPrizeIndex } = this.state
6363
const { readOnly, challenge } = this.props
64-
const isTask = _.get(challenge, 'task.isTask', false)
64+
const allowMultiplePrizes = _.includes(CHALLENGE_TYPES_WITH_MULTIPLE_PRIZES, challenge.type)
6565
return _.map(this.getChallengePrize().prizes, (prize, index, { length }) => (
6666
<div key={`${index}-${prize.amount}-edit`}>
6767
<div className={styles.row}>
6868
<div className={cn(styles.field, styles.col1)}>
69-
<label htmlFor={`${index}-prize`}>Prize {!isTask ? index + 1 : ''} {!readOnly && (<span>*</span>)}:</label>
69+
<label htmlFor={`${index}-prize`}>Prize {allowMultiplePrizes ? index + 1 : ''} {!readOnly && (<span>*</span>)}:</label>
7070
</div>
7171
{readOnly ? (
7272
<span>${prize.value}</span>
@@ -101,7 +101,7 @@ class ChallengePrizesField extends Component {
101101

102102
render () {
103103
const { readOnly, challenge } = this.props
104-
const isTask = _.get(challenge, 'task.isTask', false)
104+
const allowMultiplePrizes = _.includes(CHALLENGE_TYPES_WITH_MULTIPLE_PRIZES, challenge.type)
105105
return (
106106
<div className={styles.container}>
107107
<div className={styles.row}>
@@ -110,7 +110,7 @@ class ChallengePrizesField extends Component {
110110
</div>
111111
</div>
112112
{ this.renderPrizes() }
113-
{!readOnly && !isTask && (<div className={styles.button} onClick={this.addNewPrize}>
113+
{!readOnly && allowMultiplePrizes && (<div className={styles.button} onClick={this.addNewPrize}>
114114
<PrimaryButton text={'Add New Prize'} type={'info'} />
115115
</div>)}
116116
</div>

src/components/ChallengeEditor/ChallengeView/ChallengeView.module.scss

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,11 @@
244244

245245
.actionButtonsRight {
246246
right: 20px;
247+
248+
button:not(:last-child),
249+
a:not(:last-child) {
250+
margin-right: 20px;
251+
}
247252
}
248253

249254
.button {

src/components/ChallengeEditor/MaximumSubmissions-Field/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ class MaximumSubmissionsField extends Component {
7575
placeholder=''
7676
value={count}
7777
maxLength='200'
78-
onChange={(e) => onUpdateMetadata('submissionLimit', e.target.value, 'count')}
78+
onChange={(e) => onUpdateMetadata('submissionLimit', e.target.value.replace(/[^\d]+/g, ''), 'count')}
7979
/>
8080
</div>
8181
</div>

src/components/ChallengeEditor/TextEditor-Field/index.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,7 @@ class TextEditorField extends Component {
115115

116116
TextEditorField.defaultProps = {
117117
challengeTags: [],
118-
// TODO: For our first go-live, we're probably going to have this UI in production before the Community App work to display data from V5 is available. Only hide the UI elements for private description for now. Don't take out any code or functionality.
119-
shouldShowPrivateDescription: false,
118+
shouldShowPrivateDescription: true,
120119
onUpdateMetadata: () => {},
121120
onUpdateCheckbox: () => {},
122121
addFileType: () => {},

src/components/ChallengeEditor/index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1002,7 +1002,7 @@ class ChallengeEditor extends Component {
10021002
const { challengeTimelines, timelineTemplates } = metadata
10031003

10041004
// all timeline template ids available for the challenge type
1005-
const availableTemplateIds = _.filter(challengeTimelines, tt => tt.typeId === challenge.typeId).map(tt => tt.timelineTemplateId)
1005+
const availableTemplateIds = _.filter(challengeTimelines, ct => ct.typeId === challenge.typeId && ct.trackId === challenge.trackId).map(tt => tt.timelineTemplateId)
10061006
// filter and return timeline templates that are available for this challenge type
10071007
return _.filter(timelineTemplates, tt => availableTemplateIds.indexOf(tt.id) !== -1)
10081008
}
@@ -1344,7 +1344,7 @@ class ChallengeEditor extends Component {
13441344
<div className={styles.wrapper}>
13451345
<Helmet title={getTitle(isNew)} />
13461346
<div className={cn(styles.actionButtons, styles.actionButtonsLeft)}>
1347-
<LegacyLinks challenge={challenge} />
1347+
{!isNew && <LegacyLinks challenge={challenge} />}
13481348
</div>
13491349
<div className={styles.title}>{getTitle(isNew)}</div>
13501350
<div className={cn(styles.actionButtons, styles.actionButtonsRight)}>

src/components/ChallengesComponent/ChallengesComponent.module.scss

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,15 @@
2424
padding: 0 20px;
2525
}
2626

27+
.titleLinks {
28+
align-items: center;
29+
display: flex;
30+
31+
> a + a {
32+
margin-left: 20px;
33+
}
34+
}
35+
2736
.buttonLaunchNew {
2837
min-width: 135px;
2938
height: 40px;

src/components/ChallengesComponent/index.js

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import PropTypes from 'prop-types'
66
import Sticky from 'react-stickynode'
77
import { Helmet } from 'react-helmet'
88
import { Link } from 'react-router-dom'
9-
import { CONNECT_APP_URL } from '../../config/constants'
9+
import { CONNECT_APP_URL, DIRECT_PROJECT_URL } from '../../config/constants'
1010

1111
import { PrimaryButton } from '../Buttons'
1212
import ChallengeList from './ChallengeList'
@@ -32,17 +32,26 @@ const ChallengesComponent = ({
3232
<div>
3333
<Helmet title={activeProject ? activeProject.name : ''} />
3434
<div className={styles.titleContainer}>
35-
{(activeProject && activeProject.id) ? (
36-
<a
37-
className={styles.buttonLaunchNew}
38-
href={`${CONNECT_APP_URL}/projects/${activeProject.id}`}
39-
target={'_blank'}
40-
>
41-
<PrimaryButton text={'View Project in Connect'} type={'info'} />
42-
</a>
43-
) : (
44-
<span />
45-
)}
35+
<div className={styles.titleLinks}>
36+
{activeProject && activeProject.id && (
37+
<a
38+
className={styles.buttonLaunchNew}
39+
href={`${CONNECT_APP_URL}/projects/${activeProject.id}`}
40+
target={'_blank'}
41+
>
42+
<PrimaryButton text={'View Project in Connect'} type={'info'} />
43+
</a>
44+
)}
45+
{activeProject && activeProject.directProjectId && (
46+
<a
47+
className={styles.buttonLaunchNew}
48+
href={`${DIRECT_PROJECT_URL}/projectOverview?formData.projectId=${activeProject.directProjectId}`}
49+
target={'_blank'}
50+
>
51+
<PrimaryButton text={'View Project in Direct'} type={'info'} />
52+
</a>
53+
)}
54+
</div>
4655
<div
4756
className={styles.title}
4857
dangerouslySetInnerHTML={{

src/components/LegacyLinks/LegacyLinks.module.scss

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,18 @@
33
display: flex;
44
margin-top: auto;
55

6-
a {
6+
button:not(:first-child),
7+
a:not(:first-child) {
8+
margin-left: 20px;
9+
}
10+
11+
button {
712
height: 40px;
13+
outline: none;
14+
white-space: nowrap;
15+
}
16+
17+
a {
818
&:hover {
919
text-decoration: none;
1020
}
@@ -18,4 +28,4 @@
1828
outline: none;
1929
}
2030
}
21-
}
31+
}

src/components/LegacyLinks/index.js

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,43 @@
11
/**
22
* Component to render LegacyLinks of the app
33
*/
4-
import React from 'react'
4+
import React, { useCallback } from 'react'
55
import PropTypes from 'prop-types'
66
import styles from './LegacyLinks.module.scss'
77
import { DIRECT_PROJECT_URL, ONLINE_REVIEW_URL } from '../../config/constants'
88
import PrimaryButton from '../Buttons/PrimaryButton'
9+
import Tooltip from '../Tooltip'
910

1011
const LegacyLinks = ({ challenge }) => {
12+
const onClick = useCallback((e) => {
13+
e.stopPropagation()
14+
}, [])
15+
1116
const directUrl = `${DIRECT_PROJECT_URL}/contest/detail?projectId=${challenge.legacyId}`
1217
const orUrl = `${ONLINE_REVIEW_URL}/review/actions/ViewProjectDetails?pid=${challenge.legacyId}`
1318
return (
1419
<div className={styles.container}>
15-
<a
16-
href={directUrl}
17-
target={'_blank'}
18-
onClick={(e) => e.stopPropagation()}
19-
>
20-
<PrimaryButton text={'Direct'} type={'info'} />
21-
</a>
22-
<a
23-
href={orUrl}
24-
target={'_blank'}
25-
onClick={(e) => e.stopPropagation()}
26-
>
27-
<PrimaryButton text={'Online Review'} type={'info'} />
28-
</a>
20+
{challenge.legacyId ? (
21+
<>
22+
<a href={directUrl} target={'_blank'} onClick={onClick}>
23+
<PrimaryButton text={'Direct'} type={'info'} />
24+
</a>
25+
<a href={orUrl} target={'_blank'} onClick={onClick}>
26+
<PrimaryButton text={'Online Review'} type={'info'} />
27+
</a>
28+
</>
29+
) : (
30+
<>
31+
<Tooltip content='Legacy project is not yet created'>
32+
{/* Don't disable button for real inside tooltip, otherwise mouseEnter/Leave events work not good */}
33+
<PrimaryButton text={'Direct'} type={'disabled'} />
34+
</Tooltip>
35+
<Tooltip content='Legacy project is not yet created'>
36+
{/* Don't disable button for real inside tooltip, otherwise mouseEnter/Leave events work not good */}
37+
<PrimaryButton text={'Online Review'} type={'disabled'} />
38+
</Tooltip>
39+
</>
40+
)}
2941
</div>
3042
)
3143
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
@import "../../styles/includes";
2+
3+
.popover {
4+
background-color: $darker-gray;
5+
border-radius: 7px;
6+
z-index: 1000;
7+
}
8+
9+
.popoverArrow {
10+
border-style: solid;
11+
border-width: 7px 7px 0 7px;
12+
border-color: $darker-gray transparent transparent transparent;
13+
height: 0;
14+
bottom: -6px;
15+
width: 0;
16+
}
17+
18+
.content {
19+
color: #fff;
20+
font-size: 12px;
21+
padding: 10px;
22+
}

0 commit comments

Comments
 (0)