Skip to content

Commit bce8a79

Browse files
authored
Merge pull request #1190 from yoution/issue-1169
Issue 1169
2 parents 290f1be + b286fc8 commit bce8a79

File tree

19 files changed

+1462
-243
lines changed

19 files changed

+1462
-243
lines changed

config/constants/development.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,10 @@ module.exports = {
1818
TERMS_API_URL: `${DEV_API_HOSTNAME}/v5/terms`,
1919
RESOURCES_API_URL: `${DEV_API_HOSTNAME}/v5/resources`,
2020
RESOURCE_ROLES_API_URL: `${DEV_API_HOSTNAME}/v5/resource-roles`,
21+
SUBMISSIONS_API_URL: `${DEV_API_HOSTNAME}/v5/submissions`,
2122
PLATFORMS_V4_API_URL: `${DEV_API_HOSTNAME}/v4/platforms`,
2223
TECHNOLOGIES_V4_API_URL: `${DEV_API_HOSTNAME}/v4/technologies`,
24+
STUDIO_URL: `https://studio.${DOMAIN}`,
2325
CONNECT_APP_URL: `https://connect.${DOMAIN}`,
2426
DIRECT_PROJECT_URL: `https://www.${DOMAIN}/direct`,
2527
ONLINE_REVIEW_URL: `https://software.${DOMAIN}`,

config/constants/production.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,10 @@ module.exports = {
1818
TERMS_API_URL: `${PROD_API_HOSTNAME}/v5/terms`,
1919
RESOURCES_API_URL: `${PROD_API_HOSTNAME}/v5/resources`,
2020
RESOURCE_ROLES_API_URL: `${PROD_API_HOSTNAME}/v5/resource-roles`,
21+
SUBMISSIONS_API_URL: `${PROD_API_HOSTNAME}/v5/submissions`,
2122
PLATFORMS_V4_API_URL: `${PROD_API_HOSTNAME}/v4/platforms`,
2223
TECHNOLOGIES_V4_API_URL: `${PROD_API_HOSTNAME}/v4/technologies`,
24+
STUDIO_URL: `https://studio.${DOMAIN}`,
2325
CONNECT_APP_URL: `https://connect.${DOMAIN}`,
2426
DIRECT_PROJECT_URL: `https://www.${DOMAIN}/direct`,
2527
ONLINE_REVIEW_URL: `https://software.${DOMAIN}`,
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { fetchSubmissions } from '../services/challenges'
2+
3+
import { LOAD_CHALLENGE_SUBMISSIONS } from '../config/constants'
4+
5+
export function loadSubmissions (challengeId) {
6+
return dispatch => {
7+
if (challengeId) {
8+
dispatch({
9+
type: LOAD_CHALLENGE_SUBMISSIONS,
10+
payload: fetchSubmissions(challengeId)
11+
})
12+
}
13+
}
14+
}

src/assets/images/lock.svg

Lines changed: 9 additions & 0 deletions
Loading

src/components/ChallengeEditor/ChallengeView/index.js

Lines changed: 1 addition & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
import React, { useState, useEffect } from 'react'
22
import _ from 'lodash'
3-
import { Helmet } from 'react-helmet'
43
import PropTypes from 'prop-types'
54
import cn from 'classnames'
65
import { withRouter } from 'react-router-dom'
76
import styles from './ChallengeView.module.scss'
87
import xss from 'xss'
9-
import { PrimaryButton } from '../../Buttons'
108
import Track from '../../Track'
119
import NDAField from '../NDAField'
1210
import UseSchedulingAPIField from '../UseSchedulingAPIField'
@@ -19,13 +17,11 @@ import CopilotFeeField from '../CopilotFee-Field'
1917
import ChallengeTotalField from '../ChallengeTotal-Field'
2018
import Loader from '../../Loader'
2119
import PhaseInput from '../../PhaseInput'
22-
import LegacyLinks from '../../LegacyLinks'
2320
import AssignedMemberField from '../AssignedMember-Field'
2421
import { getResourceRoleByName } from '../../../util/tc'
2522
import { isBetaMode } from '../../../util/cookie'
2623
import { loadGroupDetails } from '../../../actions/challenges'
27-
import Tooltip from '../../Tooltip'
28-
import { MESSAGE, REVIEW_TYPES } from '../../../config/constants'
24+
import { REVIEW_TYPES } from '../../../config/constants'
2925

3026
const ChallengeView = ({
3127
projectDetail,
@@ -86,47 +82,6 @@ const ChallengeView = ({
8682
const isTask = _.get(challenge, 'task.isTask', false)
8783
return (
8884
<div className={styles.wrapper}>
89-
<Helmet title='View Details' />
90-
{!isTask && (
91-
<div className={cn(styles.actionButtons, styles.button, styles.actionButtonsLeft)}>
92-
<LegacyLinks challenge={challenge} challengeView />
93-
</div>
94-
)}
95-
<div className={styles.title}>View Details</div>
96-
<div className={cn(styles.actionButtons, styles.button, styles.actionButtonsRight)}>
97-
{
98-
challenge.status === 'Draft' && (
99-
<div className={styles.button}>
100-
{(challenge.legacyId || isTask) ? (
101-
<PrimaryButton text={'Launch'} type={'info'} onClick={onLaunchChallenge} />
102-
) : (
103-
<Tooltip content={MESSAGE.NO_LEGACY_CHALLENGE}>
104-
{/* Don't disable button for real inside tooltip, otherwise mouseEnter/Leave events work not good */}
105-
<PrimaryButton text={'Launch'} type={'disabled'} />
106-
</Tooltip>
107-
)}
108-
</div>
109-
)
110-
}
111-
{
112-
isTask && challenge.status === 'Active' && (
113-
<div className={styles.button}>
114-
{ assignedMemberDetails ? (
115-
<Tooltip content={MESSAGE.MARK_COMPLETE}>
116-
<PrimaryButton text={'Mark Complete'} type={'success'} onClick={onCloseTask} />
117-
</Tooltip>
118-
) : (
119-
<Tooltip content={MESSAGE.NO_TASK_ASSIGNEE}>
120-
{/* Don't disable button for real inside tooltip, otherwise mouseEnter/Leave events work not good */}
121-
<PrimaryButton text={'Mark Complete'} type={'disabled'} />
122-
</Tooltip>
123-
)}
124-
</div>
125-
)
126-
}
127-
{ enableEdit && <PrimaryButton text={'Edit'} type={'info'} submit link={`./edit`} /> }
128-
<PrimaryButton text={'Back'} type={'info'} submit link={`..`} />
129-
</div>
13085
<div className={styles.container}>
13186
<div className={styles.formContainer}>
13287
<div className={styles.group}>

src/components/ChallengeEditor/ChallengeViewTabs/ChallengeViewTabs.module.scss

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,90 @@
11
@import '../../../styles/includes';
22

3+
$tc-dark-blue: #0681ff;
4+
$tc-white: #FFFFFF;
5+
6+
.actionButtons {
7+
display: flex;
8+
position: absolute;
9+
top: 30px;
10+
margin-top: 53px;
11+
}
12+
13+
.actionButtonsLeft {
14+
left: 20px;
15+
}
16+
17+
.actionButtonsRight {
18+
right: 20px;
19+
20+
.button:not(:last-child),
21+
a:not(:last-child) {
22+
margin-right: 20px;
23+
}
24+
25+
button {
26+
white-space: nowrap;
27+
}
28+
}
29+
30+
.button {
31+
height: 40px;
32+
span {
33+
padding: 0 20px;
34+
}
35+
}
36+
37+
.title {
38+
@include roboto-bold();
39+
40+
font-size: 24px;
41+
font-weight: 700;
42+
line-height: 29px;
43+
color: $challenges-title;
44+
margin-top: 25px;
45+
text-align: center;
46+
47+
span {
48+
color: $tc-red;
49+
}
50+
}
51+
52+
.challenge-view-selector {
53+
display: flex;
54+
flex-wrap: wrap;
55+
justify-content: center;
56+
margin-top: 20px;
57+
position: relative;
58+
border-bottom: 1px solid silver;
59+
60+
@include xs-to-sm {
61+
flex-wrap: nowrap;
62+
justify-content: flex-start;
63+
overflow: auto;
64+
}
65+
66+
.challenge-selector-common {
67+
font-family: roboto, sans-serif;
68+
font-size: 13px;
69+
line-height: 30px;
70+
margin: 10px 20px 0;
71+
cursor: pointer;
72+
white-space: nowrap;
73+
}
74+
75+
.challenge-selected-view {
76+
font-weight: 700;
77+
color: $tc-dark-blue;
78+
border-bottom: 3px solid $tc-dark-blue;
79+
}
80+
81+
.challenge-unselected-view {
82+
font-weight: 400;
83+
color: $tc-gray-70;
84+
border-bottom: 3px hidden $tc-white;
85+
}
86+
}
87+
388
.list {
489
width: 100%;
590
display: flex;

src/components/ChallengeEditor/ChallengeViewTabs/index.js

Lines changed: 119 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,36 @@
33
*/
44
import React, { useState, useMemo } from 'react'
55
import PropTypes from 'prop-types'
6-
import { Tab, Tabs, TabList, TabPanel } from 'react-tabs'
6+
import { Helmet } from 'react-helmet'
7+
import cn from 'classnames'
8+
import _ from 'lodash'
79

810
import ChallengeViewComponent from '../ChallengeView'
11+
import { PrimaryButton } from '../../Buttons'
12+
import LegacyLinks from '../../LegacyLinks'
913
import Registrants from '../Registrants'
14+
import Submissions from '../Submissions'
1015
import { getResourceRoleByName } from '../../../util/tc'
16+
import { MESSAGE } from '../../../config/constants'
17+
import Tooltip from '../../Tooltip'
1118
import 'react-tabs/style/react-tabs.css'
1219
import styles from './ChallengeViewTabs.module.scss'
1320

21+
function getSelectorStyle (selectedView, currentView) {
22+
return cn(styles['challenge-selector-common'], {
23+
[styles['challenge-selected-view']]: selectedView === currentView,
24+
[styles['challenge-unselected-view']]: selectedView !== currentView
25+
})
26+
}
27+
1428
const ChallengeViewTabs = ({
1529
projectDetail,
1630
challenge,
1731
attachments,
1832
isBillingAccountExpired,
1933
metadata,
2034
challengeResources,
35+
challengeSubmissions,
2136
token,
2237
isLoading,
2338
challengeId,
@@ -38,23 +53,106 @@ const ChallengeViewTabs = ({
3853
}
3954
}, [metadata, challengeResources])
4055

56+
const submissions = useMemo(() => {
57+
return _.map(challengeSubmissions, s => {
58+
s.registrant = _.find(registrants, r => {
59+
return +r.memberId === s.memberId
60+
})
61+
return s
62+
})
63+
}, [challengeSubmissions, registrants])
64+
65+
const isTask = _.get(challenge, 'task.isTask', false)
66+
4167
return (
4268
<div className={styles.list}>
43-
<Tabs
44-
selectedIndex={selectedTab}
45-
className={styles.tabsContainer}
46-
onSelect={index => {
47-
setSelectedTab(index)
48-
}}
49-
>
50-
<TabList>
51-
<Tab>DETAILS</Tab>
52-
<Tab>REGISTRANTS({registrants.length})</Tab>
53-
</TabList>
54-
<TabPanel />
55-
<TabPanel />
56-
<TabPanel />
57-
</Tabs>
69+
<Helmet title='View Details' />
70+
{!isTask && (
71+
<div className={cn(styles.actionButtons, styles.button, styles.actionButtonsLeft)}>
72+
<LegacyLinks challenge={challenge} />
73+
</div>
74+
)}
75+
<div className={styles.title}>View Details</div>
76+
<div className={cn(styles.actionButtons, styles.button, styles.actionButtonsRight)}>
77+
{
78+
challenge.status === 'Draft' && (
79+
<div className={styles.button}>
80+
{(challenge.legacyId || isTask) ? (
81+
<PrimaryButton text={'Launch'} type={'info'} onClick={onLaunchChallenge} />
82+
) : (
83+
<Tooltip content={MESSAGE.NO_LEGACY_CHALLENGE}>
84+
{/* Don't disable button for real inside tooltip, otherwise mouseEnter/Leave events work not good */}
85+
<PrimaryButton text={'Launch'} type={'disabled'} />
86+
</Tooltip>
87+
)}
88+
</div>
89+
)
90+
}
91+
{
92+
isTask && challenge.status === 'Active' && (
93+
<div className={styles.button}>
94+
{ assignedMemberDetails ? (
95+
<PrimaryButton text={'Close Task'} type={'danger'} onClick={onCloseTask} />
96+
) : (
97+
<Tooltip content={MESSAGE.NO_TASK_ASSIGNEE}>
98+
{/* Don't disable button for real inside tooltip, otherwise mouseEnter/Leave events work not good */}
99+
<PrimaryButton text={'Close Task'} type={'disabled'} />
100+
</Tooltip>
101+
)}
102+
</div>
103+
)
104+
}
105+
{ enableEdit && <PrimaryButton text={'Edit'} type={'info'} submit link={`./edit`} /> }
106+
<PrimaryButton text={'Back'} type={'info'} submit link={`..`} />
107+
</div>
108+
<div className={styles['challenge-view-selector']}>
109+
<a
110+
tabIndex='0'
111+
role='tab'
112+
aria-selected={selectedTab === 0}
113+
onClick={e => {
114+
setSelectedTab(0)
115+
}}
116+
onKeyPress={e => {
117+
setSelectedTab(0)
118+
}}
119+
className={getSelectorStyle(selectedTab, 0)}
120+
>
121+
DETAILS
122+
</a>
123+
{registrants.length ? (
124+
<a
125+
tabIndex='1'
126+
role='tab'
127+
aria-selected={selectedTab === 1}
128+
onClick={e => {
129+
setSelectedTab(1)
130+
}}
131+
onKeyPress={e => {
132+
setSelectedTab(1)
133+
}}
134+
className={getSelectorStyle(selectedTab, 1)}
135+
>
136+
REGISTRANTS ({registrants.length})
137+
</a>
138+
) : null}
139+
{challengeSubmissions.length ? (
140+
<a
141+
tabIndex='2'
142+
role='tab'
143+
aria-selected={selectedTab === 2}
144+
onClick={e => {
145+
setSelectedTab(2)
146+
}}
147+
onKeyPress={e => {
148+
setSelectedTab(2)
149+
}}
150+
className={getSelectorStyle(selectedTab, 2)}
151+
>
152+
SUBMISSIONS ({submissions.length})
153+
</a>
154+
) : null}
155+
</div>
58156
{selectedTab === 0 && (
59157
<ChallengeViewComponent
60158
isLoading={isLoading}
@@ -73,10 +171,10 @@ const ChallengeViewTabs = ({
73171
/>
74172
)}
75173
{selectedTab === 1 && (
76-
<Registrants
77-
challenge={challenge}
78-
registrants={registrants}
79-
/>
174+
<Registrants challenge={challenge} registrants={registrants} />
175+
)}
176+
{selectedTab === 2 && (
177+
<Submissions challenge={challenge} submissions={submissions} />
80178
)}
81179
</div>
82180
)
@@ -100,6 +198,7 @@ ChallengeViewTabs.propTypes = {
100198
isLoading: PropTypes.bool.isRequired,
101199
challengeId: PropTypes.string.isRequired,
102200
challengeResources: PropTypes.arrayOf(PropTypes.object),
201+
challengeSubmissions: PropTypes.arrayOf(PropTypes.object),
103202
assignedMemberDetails: PropTypes.shape(),
104203
enableEdit: PropTypes.bool,
105204
onLaunchChallenge: PropTypes.func,

0 commit comments

Comments
 (0)