Skip to content

Commit 5e12890

Browse files
authored
Merge pull request #1536 from topcoder-platform/develop
v0.20.8
2 parents afa9d19 + 75c7bdd commit 5e12890

File tree

10 files changed

+222
-35
lines changed

10 files changed

+222
-35
lines changed

.circleci/config.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ install_test_dependency: &install_test_dependency
3636
install_deploysuite: &install_deploysuite
3737
name: Installation of install_deploysuite.
3838
command: |
39-
git clone --branch v1.4 https://github.com/topcoder-platform/tc-deploy-scripts ../buildscript
39+
git clone --branch v1.4.15 https://github.com/topcoder-platform/tc-deploy-scripts ../buildscript
4040
cp ./../buildscript/master_deploy.sh .
4141
cp ./../buildscript/buildenv.sh .
4242
cp ./../buildscript/awsconfiguration.sh .
Lines changed: 3 additions & 0 deletions
Loading

src/components/ChallengeEditor/ChallengeView/index.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ const ChallengeView = ({
4949
showRejectChallengeModal,
5050
loggedInUser
5151
}) => {
52+
const challengeBillingAccount = _.get(challenge, 'billing.billingAccountId')
5253
const selectedType = _.find(metadata.challengeTypes, { id: challenge.typeId })
5354
const challengeTrack = _.find(metadata.challengeTracks, { id: challenge.trackId })
5455
const selectedMilestone = challenge.milestoneId
@@ -196,7 +197,7 @@ const ChallengeView = ({
196197
<div className={styles.col}>
197198
<span>
198199
<span className={styles.fieldTitle}>Billing Account Id:</span>
199-
{projectDetail.billingAccountId}
200+
{challengeBillingAccount}
200201
</span>
201202
{isBillingAccountExpired && <span className={styles.expiredMessage}>Expired</span>}
202203
</div>

src/components/ChallengeEditor/Submissions/Submissions.module.scss

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,7 @@ $base-unit: 5px;
287287
display: flex;
288288
border-bottom: 1px solid $tc-gray-10;
289289
background: transparent;
290+
gap: 20px;
290291

291292
@include xs-to-sm {
292293
display: none;
@@ -298,6 +299,7 @@ $base-unit: 5px;
298299
display: flex;
299300
border-bottom: 1px solid $tc-gray-10;
300301
font-size: 15px;
302+
gap: 20px;
301303
}
302304

303305
.col-1 {
@@ -317,28 +319,54 @@ $base-unit: 5px;
317319
.col-2 {
318320
// width: 10%;
319321
display: flex;
320-
width: 150px;
322+
width: 50px;
321323
margin-left: 20px;
322324
justify-content: flex-start;
323325
display: flex;
326+
flex-shrink: 0;
324327
}
325328

326329
.col-3 {
327-
width: 298px;
328330
display: flex;
329-
// width: 26.6%;
331+
width: 100px;
332+
flex-shrink: 0;
330333
}
331334

332335
.col-4 {
333336
display: flex;
334-
// width: 26.6%;
335-
width: 317px;
337+
width: 150px;
338+
flex-shrink: 0;
336339
}
337340

338341
.col-5 {
339342
display: flex;
340-
width: 351px;
341-
// width: 26.6%;
343+
width: 150px;
344+
flex-shrink: 0;
345+
}
346+
347+
.col-6 {
348+
display: flex;
349+
width: 280px;
350+
flex-shrink: 0;
351+
}
352+
353+
.col-7 {
354+
display: flex;
355+
width: 150px;
356+
flex-shrink: 0;
357+
}
358+
359+
.col-8 {
360+
display: flex;
361+
width: 50px;
362+
flex-shrink: 0;
363+
364+
button {
365+
padding: 0;
366+
border: none;
367+
background-color: transparent;
368+
outline: none;
369+
}
342370
}
343371

344372
.handle {
@@ -350,7 +378,9 @@ $base-unit: 5px;
350378
.submissionsContainer {
351379
display: flex;
352380
flex-direction: column;
353-
max-width: 966px;
381+
max-width: 1100px;
382+
width: 100%;
383+
overflow: auto;
354384
}
355385

356386
.tooltip {

src/components/ChallengeEditor/Submissions/index.js

Lines changed: 53 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ import {
1515
getRatingLevel,
1616
sortList,
1717
getProvisionalScore,
18-
getFinalScore
18+
getFinalScore,
19+
checkManageRoles
1920
} from '../../../util/tc'
2021
import {
2122
getTopcoderReactLib
@@ -27,6 +28,7 @@ import styles from './Submissions.module.scss'
2728
const assets = require.context('../../../assets/images', false, /svg/)
2829
const ArrowDown = './arrow-down.svg'
2930
const Lock = './lock.svg'
31+
const Download = './IconSquareDownload.svg'
3032

3133
class SubmissionsComponent extends React.Component {
3234
constructor (props) {
@@ -206,6 +208,7 @@ class SubmissionsComponent extends React.Component {
206208
render () {
207209
const { challenge, token } = this.props
208210
const { checkpoints, track, type, tags } = challenge
211+
const haveManagePermission = checkManageRoles(token)
209212

210213
const { field, sort } = this.getSubmissionsSortParam()
211214
const revertSort = sort === 'desc' ? 'asc' : 'desc'
@@ -306,7 +309,7 @@ class SubmissionsComponent extends React.Component {
306309

307310
return (
308311
<div className={cn(styles.container, styles.dev, styles['non-mm'])}>
309-
<div className={styles['empty-left']} />
312+
{haveManagePermission ? (<div className={styles['empty-left']} />) : null}
310313
<div className={styles.submissionsContainer}>
311314
<div className={styles.head}>
312315
{!isF2F && !isBugHunt && (
@@ -393,6 +396,21 @@ class SubmissionsComponent extends React.Component {
393396
<ReactSVG path={assets(`${ArrowDown}`)} />
394397
</div>
395398
</button>
399+
<div
400+
className={cn(styles['col-6'])}
401+
>
402+
<span>Submission ID (UUID)</span>
403+
</div>
404+
<div
405+
className={cn(styles['col-7'])}
406+
>
407+
<span>Legacy submission ID</span>
408+
</div>
409+
{haveManagePermission ? (<div
410+
className={cn(styles['col-8'])}
411+
>
412+
<span>Actions</span>
413+
</div>) : null}
396414
</div>
397415
{sortedSubmissions.map(s => (
398416
<div
@@ -441,19 +459,40 @@ class SubmissionsComponent extends React.Component {
441459
: 'N/A'}
442460
</a>
443461
</div>
462+
<div className={styles['col-6']}>
463+
{s.id}
464+
</div>
465+
<div className={styles['col-7']}>
466+
{s.legacySubmissionId}
467+
</div>
468+
{haveManagePermission ? (<div className={styles['col-8']}>
469+
<button
470+
onClick={() => {
471+
// download submission
472+
const reactLib = getTopcoderReactLib()
473+
const { getService } = reactLib.services.submissions
474+
const submissionsService = getService(token)
475+
submissionsService.downloadSubmission(s.id)
476+
.then((blob) => {
477+
// eslint-disable-next-line no-undef
478+
const url = window.URL.createObjectURL(new Blob([blob]))
479+
const link = document.createElement('a')
480+
link.href = url
481+
link.setAttribute('download', `${s.legacySubmissionId}.zip`)
482+
document.body.appendChild(link)
483+
link.click()
484+
link.parentNode.removeChild(link)
485+
})
486+
}}
487+
>
488+
<ReactSVG path={assets(`${Download}`)} />
489+
</button>
490+
</div>) : null}
444491
</div>
445492
))}
446493
</div>
447494

448-
<div className={styles['top-title']} >
449-
<div className={styles.btnManageSubmissions} >
450-
<PrimaryButton
451-
text='Manage Submissions'
452-
type='info'
453-
href={`${SUBMISSION_REVIEW_APP_URL}/${challenge.legacyId}`}
454-
/>
455-
</div>
456-
495+
{haveManagePermission ? (<div className={styles['top-title']} >
457496
<div className={styles.btnManageSubmissions} >
458497
<PrimaryButton
459498
text='Download All'
@@ -486,10 +525,9 @@ class SubmissionsComponent extends React.Component {
486525
}
487526
checkToCompressFiles()
488527
_.forEach(sortedSubmissions, (submission) => {
489-
const mmSubmissionId = submission.id
490-
submissionsService.downloadSubmission(mmSubmissionId)
528+
submissionsService.downloadSubmission(submission.id)
491529
.then((blob) => {
492-
const file = new window.File([blob], `submission-${mmSubmissionId}.zip`)
530+
const file = new window.File([blob], `${submission.legacySubmissionId}.zip`)
493531
allFiles.push(file)
494532
downloadedFile += 1
495533
checkToCompressFiles()
@@ -501,7 +539,7 @@ class SubmissionsComponent extends React.Component {
501539
}}
502540
/>
503541
</div>
504-
</div>
542+
</div>) : null}
505543
</div>
506544
)
507545
}

src/components/DateInput/index.js

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import React, { useEffect, useState, useImperativeHandle, forwardRef } from 'react'
2+
import PropTypes from 'prop-types'
3+
import 'react-day-picker/lib/style.css'
4+
import 'rc-time-picker/assets/index.css'
5+
import DateTime from '@nateradebaugh/react-datetime'
6+
import '@nateradebaugh/react-datetime/scss/styles.scss'
7+
8+
const DateInput = forwardRef(({
9+
onChange,
10+
value,
11+
isValidDate,
12+
dateFormat,
13+
timeFormat,
14+
className
15+
}, ref) => {
16+
const [localValue, setLocalValue] = useState(value)
17+
useEffect(() => {
18+
setLocalValue(value)
19+
}, [value])
20+
21+
useImperativeHandle(ref, () => ({
22+
forceReset: () => {
23+
setLocalValue(value)
24+
}
25+
}))
26+
27+
return (
28+
<DateTime
29+
className={className}
30+
value={localValue}
31+
onChange={newValue => {
32+
setLocalValue(newValue)
33+
}}
34+
onBlur={onChange}
35+
isValidDate={isValidDate}
36+
dateFormat={dateFormat}
37+
timeFormat={timeFormat}
38+
/>
39+
)
40+
})
41+
42+
DateInput.defaultProps = {
43+
onChange: () => {},
44+
isValidDate: () => true,
45+
value: null,
46+
dateFormat: null,
47+
timeFormat: null,
48+
className: null
49+
}
50+
51+
DateInput.propTypes = {
52+
onChange: PropTypes.func,
53+
isValidDate: PropTypes.func,
54+
value: PropTypes.any,
55+
dateFormat: PropTypes.string,
56+
timeFormat: PropTypes.string,
57+
className: PropTypes.string
58+
}
59+
export default DateInput

src/components/PhaseInput/index.js

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,13 @@
11
import moment from 'moment'
2-
import React, { useEffect, useMemo } from 'react'
2+
import React, { useEffect, useMemo, useRef } from 'react'
33
import PropTypes from 'prop-types'
44
import styles from './PhaseInput.module.scss'
55
import cn from 'classnames'
6-
import 'react-day-picker/lib/style.css'
7-
import 'rc-time-picker/assets/index.css'
8-
import DateTime from '@nateradebaugh/react-datetime'
96
import isAfter from 'date-fns/isAfter'
107
import subDays from 'date-fns/subDays'
11-
import '@nateradebaugh/react-datetime/scss/styles.scss'
128
import DurationInput from '../DurationInput'
13-
import { getPhaseHoursMinutes, getPhaseEndDate } from '../../util/date'
9+
import { getPhaseHoursMinutes, getPhaseEndDate, getPhaseDuration } from '../../util/date'
10+
import DateInput from '../DateInput'
1411

1512
const dateFormat = 'MM/DD/YYYY HH:mm'
1613
const inputDateFormat = 'MM/dd/yyyy'
@@ -21,6 +18,7 @@ const PhaseInput = ({ onUpdatePhase, phase, readOnly, phaseIndex }) => {
2118
const { scheduledStartDate: startDate, scheduledEndDate: endDate, duration, isStartTimeActive, isDurationActive } = phase
2219

2320
const durationHoursMinutes = useMemo(() => getPhaseHoursMinutes(duration), [duration])
21+
const endDateInputRef = useRef()
2422

2523
const onStartDateChange = (e) => {
2624
let startDate = moment(e).format(dateFormat)
@@ -32,6 +30,20 @@ const PhaseInput = ({ onUpdatePhase, phase, readOnly, phaseIndex }) => {
3230
})
3331
}
3432

33+
const onEndDateChange = (e) => {
34+
let endDate = moment(e).format(dateFormat)
35+
let duration = getPhaseDuration(startDate, endDate)
36+
if (duration > 0) {
37+
onUpdatePhase({
38+
startDate,
39+
endDate,
40+
duration
41+
})
42+
} else {
43+
endDateInputRef.current.forceReset()
44+
}
45+
}
46+
3547
useEffect(() => {
3648
if (!startDate && onUpdatePhase) {
3749
let startDate = moment().format(dateFormat)
@@ -71,9 +83,9 @@ const PhaseInput = ({ onUpdatePhase, phase, readOnly, phaseIndex }) => {
7183
<span className={styles.readOnlyValue}>{moment(startDate).format(dateFormat)}</span>
7284
)
7385
: (
74-
<DateTime
86+
<DateInput
7587
className={styles.dateTimeInput}
76-
value={moment(startDate).format(dateFormat)}
88+
value={moment(startDate).toDate()}
7789
onChange={onStartDateChange}
7890
isValidDate={(current) => {
7991
const yesterday = subDays(new Date(), 1)
@@ -87,7 +99,21 @@ const PhaseInput = ({ onUpdatePhase, phase, readOnly, phaseIndex }) => {
8799
<div className={cn(styles.field, styles.col2)}>
88100
<span className={styles.title}>End Date:</span>
89101
<div className={styles.dayPicker}>
90-
<span className={styles.readOnlyValue}>{moment(endDate).format(dateFormat)}</span>
102+
{(readOnly || !isDurationActive) ? (
103+
<span className={styles.readOnlyValue}>{moment(endDate).format(dateFormat)}</span>
104+
) : (
105+
<DateInput
106+
ref={endDateInputRef}
107+
className={styles.dateTimeInput}
108+
value={moment(endDate).toDate()}
109+
onChange={onEndDateChange}
110+
isValidDate={(current) => {
111+
return isAfter(current, moment(startDate).toDate())
112+
}}
113+
dateFormat={inputDateFormat}
114+
timeFormat={inputTimeFormat}
115+
/>
116+
)}
91117
</div>
92118
</div>
93119
<div className={cn(styles.field, styles.col2)}>

0 commit comments

Comments
 (0)