Skip to content

Commit 8f5bca9

Browse files
committed
feat: artifacts download modal
1 parent 158140b commit 8f5bca9

File tree

4 files changed

+196
-35
lines changed

4 files changed

+196
-35
lines changed
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
@import "../../../styles/includes";
2+
3+
.container {
4+
box-sizing: border-box;
5+
background: $white;
6+
opacity: 1;
7+
position: relative;
8+
display: flex;
9+
flex-direction: column;
10+
justify-content: flex-start;
11+
border-radius: 6px;
12+
margin: 0 auto;
13+
width: 800px;
14+
min-height: 350px;
15+
padding-top: 60px;
16+
.list {
17+
.header {
18+
border-bottom: 1px solid $tc-gray-60;
19+
padding-bottom: 10px;
20+
display: flex;
21+
padding-left: 40px;
22+
padding-right: 40px;
23+
color: $tc-gray-70;
24+
font-weight: 500;
25+
26+
.header-title {
27+
flex: 1;
28+
}
29+
}
30+
.list-item {
31+
border-bottom: 1px solid $tc-gray-60;
32+
padding-bottom: 10px;
33+
padding-top: 10px;
34+
display: flex;
35+
padding-left: 40px;
36+
padding-right: 40px;
37+
color: $tc-gray-70;
38+
.artifact-name {
39+
display: flex;
40+
flex: 1;
41+
}
42+
.icon-download {
43+
cursor: pointer;
44+
}
45+
}
46+
}
47+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import React, { useEffect, useState } from 'react'
2+
import Modal from '../../Modal'
3+
4+
import styles from './ArtifactsListModal.module.scss'
5+
import PropTypes from 'prop-types'
6+
import ReactSVG from 'react-svg'
7+
import { getTopcoderReactLib } from '../../../util/topcoder-react-lib'
8+
import Loader from '../../Loader'
9+
const assets = require.context('../../../assets/images', false, /svg/)
10+
11+
export const ArtifactsListModal = ({ onClose, submissionId, token, theme }) => {
12+
const [artifacts, setArtifacts] = useState([])
13+
const [loading, setLoading] = useState(false)
14+
15+
const getArtifacts = async () => {
16+
const reactLib = getTopcoderReactLib()
17+
const { getService } = reactLib.services.submissions
18+
const submissionsService = getService(token)
19+
const { artifacts: resp } = await submissionsService.getSubmissionArtifacts(submissionId)
20+
setArtifacts(resp)
21+
setLoading(false)
22+
}
23+
24+
useEffect(() => {
25+
setLoading(true)
26+
getArtifacts()
27+
}, [submissionId])
28+
29+
return (
30+
<Modal theme={theme} onCancel={onClose}>
31+
<div className={styles['container']}>
32+
<div className={styles['list']}>
33+
<div className={styles['header']}>
34+
<div className={styles['header-title']}>Artifact ID</div>
35+
<div className={styles['header-action']}>Action</div>
36+
</div>
37+
{
38+
!loading && artifacts.map((item) => {
39+
return (
40+
<div className={styles['list-item']}>
41+
<div className={styles['artifact-name']}>{item}</div>
42+
<ReactSVG className={styles['icon-download']} path={assets('./IconSquareDownload.svg')} />
43+
</div>
44+
)
45+
})
46+
}
47+
48+
{
49+
loading && <Loader />
50+
}
51+
</div>
52+
</div>
53+
</Modal>
54+
)
55+
}
56+
57+
ArtifactsListModal.defaultProps = {
58+
onClose: () => {},
59+
submissionId: '',
60+
token: '',
61+
theme: ''
62+
}
63+
64+
ArtifactsListModal.propTypes = {
65+
onClose: PropTypes.func,
66+
submissionId: PropTypes.string,
67+
token: PropTypes.string,
68+
theme: PropTypes.shape()
69+
}

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,11 +240,21 @@ $base-unit: 5px;
240240
}
241241

242242
.col-8Table {
243-
button {
243+
.button-wrapper {
244+
display: flex;
245+
align-items: center;
246+
}
247+
.download-submission-button {
244248
padding: 0;
245249
border: none;
246250
background-color: transparent;
247251
outline: none;
252+
margin-right: 14px;
253+
width: 24px;
254+
}
255+
256+
.download-artifacts-button {
257+
height: 40px;
248258
}
249259
}
250260

src/components/ChallengeEditor/Submissions/index.js

Lines changed: 69 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import PT from 'prop-types'
88
import moment from 'moment'
99
import _ from 'lodash'
1010
import { STUDIO_URL, SUBMISSION_REVIEW_APP_URL, getTCMemberURL } from '../../../config/constants'
11-
import { PrimaryButton } from '../../Buttons'
11+
import { OutlineButton, PrimaryButton } from '../../Buttons'
1212
import AlertModal from '../../Modal/AlertModal'
1313
import cn from 'classnames'
1414
import ReactSVG from 'react-svg'
@@ -29,6 +29,7 @@ import {
2929
} from '../../../util/files'
3030
import styles from './Submissions.module.scss'
3131
import modalStyles from '../../../styles/modal.module.scss'
32+
import { ArtifactsListModal } from '../ArtifactsListModal'
3233
const assets = require.context('../../../assets/images', false, /svg/)
3334
const ArrowDown = './arrow-down.svg'
3435
const Lock = './lock.svg'
@@ -50,7 +51,8 @@ class SubmissionsComponent extends React.Component {
5051
memberOfModal: '',
5152
sortedSubmissions: [],
5253
downloadingAll: false,
53-
alertMessage: ''
54+
alertMessage: '',
55+
selectedSubmissionId: ''
5456
}
5557
this.getSubmissionsSortParam = this.getSubmissionsSortParam.bind(this)
5658
this.updateSortedSubmissions = this.updateSortedSubmissions.bind(this)
@@ -220,6 +222,12 @@ class SubmissionsComponent extends React.Component {
220222
return isReviewPhaseComplete
221223
}
222224

225+
closeArtifactsModal () {
226+
this.setState({
227+
selectedSubmissionId: ''
228+
})
229+
}
230+
223231
render () {
224232
const { challenge, token, loggedInUserResource } = this.props
225233
const { checkpoints, track, type, tags } = challenge
@@ -544,40 +552,52 @@ class SubmissionsComponent extends React.Component {
544552
</span>
545553
</td>
546554
{canDownloadSubmission ? (<td className={cn(styles['col-8Table'], styles['col-bodyTable'])}>
547-
<button
548-
onClick={() => {
549-
// download submission
550-
const reactLib = getTopcoderReactLib()
551-
const { getService } = reactLib.services.submissions
552-
const submissionsService = getService(token)
553-
submissionsService.downloadSubmission(s.id)
554-
.then((blob) => {
555-
isValidDownloadFile(blob).then((isValidFile) => {
556-
if (isValidFile.success) {
557-
// eslint-disable-next-line no-undef
558-
const url = window.URL.createObjectURL(new Blob([blob]))
559-
const link = document.createElement('a')
560-
link.href = url
561-
let fileName = s.legacySubmissionId
562-
if (!fileName) {
563-
fileName = s.id
555+
<div className={styles['button-wrapper']}>
556+
<button
557+
className={styles['download-submission-button']}
558+
onClick={() => {
559+
// download submission
560+
const reactLib = getTopcoderReactLib()
561+
const { getService } = reactLib.services.submissions
562+
const submissionsService = getService(token)
563+
submissionsService.downloadSubmission(s.id)
564+
.then((blob) => {
565+
isValidDownloadFile(blob).then((isValidFile) => {
566+
if (isValidFile.success) {
567+
// eslint-disable-next-line no-undef
568+
const url = window.URL.createObjectURL(new Blob([blob]))
569+
const link = document.createElement('a')
570+
link.href = url
571+
let fileName = s.legacySubmissionId
572+
if (!fileName) {
573+
fileName = s.id
574+
}
575+
fileName = fileName + '.zip'
576+
link.setAttribute('download', `${fileName}`)
577+
document.body.appendChild(link)
578+
link.click()
579+
link.parentNode.removeChild(link)
580+
} else {
581+
this.setState({
582+
alertMessage: isValidFile.message || 'Can not download this submission.'
583+
})
564584
}
565-
fileName = fileName + '.zip'
566-
link.setAttribute('download', `${fileName}`)
567-
document.body.appendChild(link)
568-
link.click()
569-
link.parentNode.removeChild(link)
570-
} else {
571-
this.setState({
572-
alertMessage: isValidFile.message || 'Can not download this submission.'
573-
})
574-
}
585+
})
575586
})
576-
})
577-
}}
578-
>
579-
<ReactSVG path={assets(`${Download}`)} />
580-
</button>
587+
}}
588+
>
589+
<ReactSVG path={assets(`${Download}`)} />
590+
</button>
591+
592+
<OutlineButton
593+
text='Download Artifacts'
594+
type='info'
595+
className={styles['download-artifacts-button']}
596+
onClick={async () => {
597+
this.setState({ selectedSubmissionId: s.id })
598+
}}
599+
/>
600+
</div>
581601
</td>) : null}
582602
</tr>
583603
)
@@ -586,6 +606,21 @@ class SubmissionsComponent extends React.Component {
586606
</table>
587607
</div>
588608

609+
{
610+
this.state.selectedSubmissionId ? (
611+
<ArtifactsListModal
612+
submissionId={this.state.selectedSubmissionId}
613+
token={this.props.token}
614+
theme={theme}
615+
onClose={() => {
616+
this.setState({
617+
selectedSubmissionId: ''
618+
})
619+
}}
620+
/>
621+
) : null
622+
}
623+
589624
{canDownloadSubmission ? (<div className={styles['top-title']} >
590625

591626
<div className={styles.btnManageSubmissions} >

0 commit comments

Comments
 (0)