Skip to content
This repository has been archived by the owner on Oct 4, 2023. It is now read-only.

Commit

Permalink
[C-2684 C-2955] Improve upload component hierarchy, state, and valida…
Browse files Browse the repository at this point in the history
…tion (#3891)
  • Loading branch information
dylanjeffers authored Aug 17, 2023
1 parent 3138da3 commit 3fca3c9
Show file tree
Hide file tree
Showing 17 changed files with 419 additions and 285 deletions.
7 changes: 6 additions & 1 deletion packages/web/src/components/data-entry/InputV2.module.css
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
.root {
display: flex;
flex-direction: column;
width: 100%;
}

.inputRoot {
display: flex;
align-items: center;
gap: var(--unit-2);
width: 100%;
padding: 0 var(--unit-4);
border: 1px solid var(--neutral-light-8);
border-radius: var(--unit-1);
Expand Down
7 changes: 3 additions & 4 deletions packages/web/src/components/data-entry/InputV2.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,6 @@ export const InputV2 = (props: InputV2Props) => {
onFocus={handleFocus}
onBlur={handleBlur}
ref={inputRef}
required={required}
className={cn(styles.textInput, inputClassName)}
value={value}
maxLength={maxLength}
Expand All @@ -119,8 +118,8 @@ export const InputV2 = (props: InputV2Props) => {
)

return (
<>
<div className={cn(styles.root, style, className)}>
<div className={cn(styles.root, className)}>
<div className={cn(styles.inputRoot, style)}>
{elevatePlaceholder ? (
<label className={styles.elevatedLabel}>
<span
Expand All @@ -147,6 +146,6 @@ export const InputV2 = (props: InputV2Props) => {
{children}
</div>
{helperText ? <HelperText error={error}>{helperText}</HelperText> : null}
</>
</div>
)
}
4 changes: 2 additions & 2 deletions packages/web/src/components/form-fields/ArtworkField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export const ArtworkField = (props: ArtworkFieldProps) => {
const hasError = Boolean(touched && error)

return (
<>
<div>
<UploadArtwork
{...otherField}
artworkUrl={value?.url}
Expand All @@ -46,6 +46,6 @@ export const ArtworkField = (props: ArtworkFieldProps) => {
{...other}
/>
{hasError ? <HelperText error={hasError}>{error}</HelperText> : null}
</>
</div>
)
}
91 changes: 51 additions & 40 deletions packages/web/src/pages/upload-page/UploadPageNew.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,19 @@
import { useCallback, useEffect, useMemo, useState } from 'react'

import { uploadActions, UploadType } from '@audius/common'
import { UploadType, uploadActions } from '@audius/common'
import { useDispatch } from 'react-redux'

import Header from 'components/header/desktop/Header'
import Page from 'components/page/Page'

import styles from './UploadPage.module.css'
import { EditPageNew } from './components/EditPageNew'
import { FinishPageNew } from './components/FinishPageNew'
import SelectPageNew from './components/SelectPageNew'
import { TrackForUpload } from './components/types'
import { EditPage } from './pages/EditPage'
import { UploadFormState } from './types'

const { uploadTracks } = uploadActions

type UploadPageProps = {
uploadType: UploadType
}

enum Phase {
SELECT,
EDIT,
FINISH
}

const messages = {
selectPageTitle: 'Upload Your Music',
editSingleTrackPageTitle: 'Complete Your Track',
Expand All @@ -32,10 +22,22 @@ const messages = {
finishMultiTrackPageTitle: 'Uploading Your Tracks'
}

export const UploadPageNew = (props: UploadPageProps) => {
enum Phase {
SELECT,
EDIT,
FINISH
}

export const UploadPageNew = () => {
const dispatch = useDispatch()
const [phase, setPhase] = useState(Phase.SELECT)
const [tracks, setTracks] = useState<TrackForUpload[]>([])
const [formState, setFormState] = useState<UploadFormState>({
uploadType: undefined,
metadata: undefined,
tracks: undefined
})

const { tracks } = formState

// Pretty print json just for testing
useEffect(() => {
Expand Down Expand Up @@ -64,11 +66,11 @@ export const UploadPageNew = (props: UploadPageProps) => {
const pageTitle = useMemo(() => {
switch (phase) {
case Phase.EDIT:
return tracks.length > 1
return tracks && tracks.length > 1
? messages.editMultiTrackPageTitle
: messages.editSingleTrackPageTitle
case Phase.FINISH:
return tracks.length > 1
return tracks && tracks.length > 1
? messages.finishMultiTrackPageTitle
: messages.finishSingleTrackPageTitle
case Phase.SELECT:
Expand All @@ -82,39 +84,48 @@ export const UploadPageNew = (props: UploadPageProps) => {
case Phase.SELECT:
page = (
<SelectPageNew
tracks={tracks}
setTracks={setTracks}
onContinue={() => {
formState={formState}
onContinue={(formState: UploadFormState) => {
setFormState(formState)
setPhase(Phase.EDIT)
}}
/>
)
break
case Phase.EDIT:
page = (
<EditPageNew
tracks={tracks}
setTracks={setTracks}
onContinue={() => {
setPhase(Phase.FINISH)
}}
/>
)
if (formState.uploadType) {
page = (
<EditPage
formState={formState}
onContinue={(formState: UploadFormState) => {
setFormState(formState)
setPhase(Phase.FINISH)
}}
/>
)
}
break
case Phase.FINISH:
page = (
<FinishPageNew
tracks={tracks}
onContinue={() => {
setTracks([])
setPhase(Phase.SELECT)
}}
/>
)
if (formState.uploadType) {
page = (
<FinishPageNew
formState={formState}
onContinue={() => {
setFormState({
tracks: undefined,
uploadType: undefined,
metadata: undefined
})
setPhase(Phase.SELECT)
}}
/>
)
}
}

const handleUpload = useCallback(() => {
console.log('Handling upload')
if (!formState.tracks) return
const { tracks } = formState
const trackStems = tracks.reduce((acc, track) => {
// @ts-ignore - This has stems in it sometimes
acc = [...acc, ...(track.metadata.stems ?? [])]
Expand All @@ -133,7 +144,7 @@ export const UploadPageNew = (props: UploadPageProps) => {
trackStems
)
)
}, [dispatch, tracks])
}, [dispatch, formState])

useEffect(() => {
if (phase === Phase.FINISH) handleUpload()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,10 @@ import { Tile } from 'components/tile'
import { Text } from 'components/typography'
import { profilePage } from 'utils/route'

import { CollectionFormState, TrackFormState, TrackForUpload } from '../types'

import styles from './FinishPage.module.css'
import { ShareBannerNew } from './ShareBannerNew'
import { TrackForUpload } from './types'

const { getAccountUser } = accountSelectors
const { getUploadPercentage } = uploadSelectors
Expand Down Expand Up @@ -93,12 +94,13 @@ const UploadTrackItem = (props: UploadTrackItemProps) => {
}

type FinishPageProps = {
tracks: TrackForUpload[]
formState: TrackFormState | CollectionFormState
onContinue: () => void
}

export const FinishPageNew = (props: FinishPageProps) => {
const { tracks, onContinue } = props
const { formState, onContinue } = props
const { tracks } = formState
const accountUser = useSelector(getAccountUser)
const upload = useSelector((state: CommonState) => state.upload)
const user = useSelector(getAccountUser)
Expand Down
43 changes: 29 additions & 14 deletions packages/web/src/pages/upload-page/components/SelectPageNew.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import {
playerActions,
playerSelectors,
UploadType,
removeNullable
removeNullable,
newCollectionMetadata
} from '@audius/common'
import { Button, ButtonType, IconArrow } from '@audius/stems'
import cn from 'classnames'
Expand All @@ -16,33 +17,32 @@ import { Dropzone } from 'components/upload/Dropzone'
import InvalidFileType from 'components/upload/InvalidFileType'

import { processFiles } from '../store/utils/processFiles'
import { UploadFormState } from '../types'

import styles from './SelectPage.module.css'
import TracksPreview from './TracksPreview'
import { TrackForUpload } from './types'
const { pause } = playerActions

const { getPlaying } = playerSelectors

type ErrorType = { reason: 'size' | 'type' } | null

type SelectPageProps = {
tracks: TrackForUpload[]
setTracks: (tracks: TrackForUpload[]) => void
onContinue: () => void
formState: UploadFormState
onContinue: (formState: UploadFormState) => void
}

export const SelectPageNew = (props: SelectPageProps) => {
const { tracks, setTracks, onContinue } = props
const { formState, onContinue } = props
const dispatch = useDispatch()
const playing = useSelector(getPlaying)

const [tracks, setTracks] = useState(formState.tracks ?? [])
const [uploadType, setUploadType] = useState(
formState.uploadType ?? UploadType.INDIVIDUAL_TRACK
)
const [uploadTrackError, setUploadTrackError] =
useState<Nullable<ErrorType>>(null)
// TODO: support upload types when directing to next page
const [uploadType, setUploadType] = useState<UploadType>(
UploadType.INDIVIDUAL_TRACK
)
const [previewIndex, setPreviewIndex] = useState(-1)
const [preview, setPreview] = useState<Nullable<HTMLAudioElement>>()

Expand Down Expand Up @@ -72,14 +72,14 @@ export const SelectPageNew = (props: SelectPageProps) => {

if (
uploadType === UploadType.INDIVIDUAL_TRACK &&
tracks.length + processedTracks.length > 1
selectedFiles.length + processedTracks.length > 1
) {
setUploadType(UploadType.INDIVIDUAL_TRACKS)
}

setTracks([...tracks, ...processedTracks])
},
[setTracks, tracks, uploadType]
[setTracks, tracks, uploadType, setUploadType]
)

const onRemoveTrack = useCallback(
Expand All @@ -89,7 +89,7 @@ export const SelectPageNew = (props: SelectPageProps) => {
tracks.length === 2 ? UploadType.INDIVIDUAL_TRACK : uploadType
)
},
[setTracks, tracks, uploadType]
[setTracks, setUploadType, tracks, uploadType]
)

const stopPreview = useCallback(() => {
Expand Down Expand Up @@ -121,6 +121,21 @@ export const SelectPageNew = (props: SelectPageProps) => {
stopPreview()
})

const handleContinue = useCallback(() => {
if (uploadType !== undefined && tracks) {
switch (uploadType) {
case UploadType.INDIVIDUAL_TRACK:
case UploadType.INDIVIDUAL_TRACKS:
onContinue({ tracks, uploadType })
break
case UploadType.ALBUM:
case UploadType.PLAYLIST:
onContinue({ tracks, uploadType, metadata: newCollectionMetadata() })
break
}
}
}, [onContinue, tracks, uploadType])

const textAboveIcon = tracks.length > 0 ? 'More to Upload?' : undefined
return (
<div className={cn(styles.page)}>
Expand Down Expand Up @@ -165,7 +180,7 @@ export const SelectPageNew = (props: SelectPageProps) => {
text='Continue'
name='continue'
rightIcon={<IconArrow />}
onClick={onContinue}
onClick={handleContinue}
textClassName={styles.continueButtonText}
className={styles.continueButton}
/>
Expand Down
7 changes: 0 additions & 7 deletions packages/web/src/pages/upload-page/components/types.ts

This file was deleted.

Loading

0 comments on commit 3fca3c9

Please sign in to comment.