From cc4679d0487014a79df85e29699de00a20424b2d Mon Sep 17 00:00:00 2001 From: Paul Bienkowski Date: Fri, 26 Feb 2021 23:10:10 +0100 Subject: [PATCH] frontend: Replace tracks with new file through upload in edit page --- frontend/src/components/FileUploadField.tsx | 64 ++++++++++++++++++ frontend/src/components/index.js | 1 + frontend/src/pages/TrackEditor.tsx | 39 +++++++++-- frontend/src/pages/UploadPage.tsx | 74 ++++----------------- 4 files changed, 112 insertions(+), 66 deletions(-) create mode 100644 frontend/src/components/FileUploadField.tsx diff --git a/frontend/src/components/FileUploadField.tsx b/frontend/src/components/FileUploadField.tsx new file mode 100644 index 0000000..36c8f68 --- /dev/null +++ b/frontend/src/components/FileUploadField.tsx @@ -0,0 +1,64 @@ +import React from 'react' +import {Icon, Segment, Header, Button} from 'semantic-ui-react' + +import {FileDrop} from 'components' + +export default function FileUploadField({onSelect: onSelect_, multiple}) { + const labelRef = React.useRef() + const [labelRefState, setLabelRefState] = React.useState() + + const onSelect = multiple ? onSelect_ : (files) => onSelect_(files?.[0]) + + React.useLayoutEffect( + () => { + setLabelRefState(labelRef.current) + }, + // eslint-disable-next-line react-hooks/exhaustive-deps + [labelRef.current] + ) + + function onChangeField(e) { + if (e.target.files && e.target.files.length) { + onSelect(e.target.files) + } + e.target.value = '' // reset the form field for uploading again + } + + return ( + <> + + + + ) +} diff --git a/frontend/src/components/index.js b/frontend/src/components/index.js index 533d682..638194f 100644 --- a/frontend/src/components/index.js +++ b/frontend/src/components/index.js @@ -1,4 +1,5 @@ export {default as FileDrop} from './FileDrop' +export {default as FileUploadField} from './FileUploadField' export {default as FormattedDate} from './FormattedDate' export {default as LoginButton} from './LoginButton' export {default as Map} from './Map' diff --git a/frontend/src/pages/TrackEditor.tsx b/frontend/src/pages/TrackEditor.tsx index db4dbc9..62e0962 100644 --- a/frontend/src/pages/TrackEditor.tsx +++ b/frontend/src/pages/TrackEditor.tsx @@ -1,8 +1,8 @@ import React from 'react' import _ from 'lodash' import {connect} from 'react-redux' -import {Confirm, Grid, Button, Icon, Popup, Form, Ref, TextArea, Checkbox} from 'semantic-ui-react' -import {useHistory, useParams} from 'react-router-dom' +import {Divider, Message, Confirm, Grid, Button, Icon, Popup, Form, Ref, TextArea, Checkbox} from 'semantic-ui-react' +import {useHistory, useParams, Link} from 'react-router-dom' import {concat, of, from} from 'rxjs' import {pluck, distinctUntilChanged, map, switchMap} from 'rxjs/operators' import {useObservable} from 'rxjs-hooks' @@ -10,9 +10,32 @@ import {findInput} from 'utils' import {useForm, Controller} from 'react-hook-form' import api from 'api' -import {Page} from 'components' +import {Page, FileUploadField} from 'components' import type {Track} from 'types' +import {FileUploadStatus} from 'pages/UploadPage' + +function ReplaceTrackData({slug}) { + const [file, setFile] = React.useState(null) + const [result, setResult] = React.useState(null) + const onComplete = React.useCallback((_id, r) => setResult(r), [setResult]) + + return ( + <> +

Replace track data

+ {!file ? ( + + ) : result ? ( + + Upload complete. Show track + + ) : ( + + )} + + ) +} + const TrackEditor = connect((state) => ({login: state.login}))(function TrackEditor({login}) { const [busy, setBusy] = React.useState(false) const {register, control, handleSubmit} = useForm() @@ -75,7 +98,7 @@ const TrackEditor = connect((state) => ({login: state.login}))(function TrackEdi -

Edit {track ? (track.title || 'Unnamed track') : 'track'}

+

Edit {track ? track.title || 'Unnamed track' : 'track'}

@@ -136,13 +159,19 @@ const TrackEditor = connect((state) => ({login: state.login}))(function TrackEdi
+ + + +

Danger zone

You can remove this track from your account and the portal if you like. However, if at any point you have published this track, we cannot guarantee that there are no versions of it in the public data repository, or any copy thereof.

- + setConfirmDelete(false)} onConfirm={onDelete} />
diff --git a/frontend/src/pages/UploadPage.tsx b/frontend/src/pages/UploadPage.tsx index 77aab2e..762f665 100644 --- a/frontend/src/pages/UploadPage.tsx +++ b/frontend/src/pages/UploadPage.tsx @@ -1,9 +1,9 @@ import _ from 'lodash' import React from 'react' -import {List, Loader, Table, Icon, Segment, Header, Button} from 'semantic-ui-react' +import {List, Loader, Table, Icon} from 'semantic-ui-react' import {Link} from 'react-router-dom' -import {FileDrop, Page} from 'components' +import {FileUploadField, Page} from 'components' import type {Track} from 'types' import api from 'api' @@ -40,14 +40,16 @@ type FileUploadResult = errors: Record } -function FileUploadStatus({ +export function FileUploadStatus({ id, file, onComplete, + slug, }: { id: string file: File onComplete: (result: FileUploadResult) => void + slug?: string }) { const [progress, setProgress] = React.useState(0) @@ -70,7 +72,11 @@ function FileUploadStatus({ xhr.responseType = 'json' xhr.onload = onLoad xhr.upload.onprogress = onProgress - xhr.open('POST', '/api/tracks') + if (slug) { + xhr.open('PUT', `/api/tracks/${slug}`) + } else { + xhr.open('POST', '/api/tracks') + } api.getValidAccessToken().then((accessToken) => { xhr.setRequestHeader('Authorization', accessToken) @@ -85,7 +91,8 @@ function FileUploadStatus({ return ( - {progress < 1 ? `Uploading ${(progress * 100).toFixed(0)}%` : 'Processing...'} + {' '} + {progress < 1 ? `Uploading ${(progress * 100).toFixed(0)}%` : 'Processing...'} ) } @@ -99,9 +106,6 @@ type FileEntry = { } export default function UploadPage() { - const labelRef = React.useRef() - const [labelRefState, setLabelRefState] = React.useState() - const [files, setFiles] = React.useState([]) const onCompleteFileUpload = React.useCallback( @@ -111,14 +115,6 @@ export default function UploadPage() { [setFiles] ) - React.useLayoutEffect( - () => { - setLabelRefState(labelRef.current) - }, - // eslint-disable-next-line react-hooks/exhaustive-deps - [labelRef.current] - ) - function onSelectFiles(fileList) { const newFiles = Array.from(fileList).map((file) => ({ id: 'file-' + String(Math.floor(Math.random() * 1000000)), @@ -129,18 +125,6 @@ export default function UploadPage() { setFiles(files.filter((a) => !newFiles.some((b) => isSameFile(a, b))).concat(newFiles)) } - function onChangeField(e) { - if (e.target.files && e.target.files.length) { - onSelectFiles(e.target.files) - } - e.target.value = '' // reset the form field for uploading again - } - - async function onDeleteTrack(slug: string) { - await api.delete(`/tracks/${slug}`) - setFiles((files) => files.filter((t) => t.result?.track?.slug !== slug)) - } - return ( {files.length ? ( @@ -192,39 +176,7 @@ export default function UploadPage() { ) : null} - - + ) }