Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

386 - Refactor MoveToDatasetButton / MoveToDatasetModal components #435

Open
wants to merge 14 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
14 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 45 additions & 50 deletions src/components/Dataset/MoveToDatasetButton.js
Original file line number Diff line number Diff line change
@@ -1,74 +1,69 @@
import { useState } from 'react'
import { useRouter } from 'next/router'
import { useDatasetManager } from 'hooks/useDatasetManager'
import { useModal } from 'hooks/useModal'
import formatNumbers from 'helpers/formatNumbers'
import { Button } from 'components/shared/Button'
import { Button as SharedButton } from 'components/shared/Button'
import { Modal } from 'components/shared/Modal'
import { MoveToDatasetModal } from './MoveToDatasetModal'

const Button = ({ onClick }) => (
<SharedButton
label="Move to Dataset"
secondary
responsive
onClick={onClick}
/>
)

export const MoveToDatasetButton = ({ dataset }) => {
const { push } = useRouter()
const { openModal, closeModal } = useModal()
const modalId = `move-to-dataset-${dataset.id}`
const {
dataset: myDataset,
addSamples,
getTotalSamples
getTotalSamples,
replaceSamples
} = useDatasetManager()
const { openModal, closeModal } = useModal()
const id = `move-to-dataset-${dataset.id}`
const radioOptions = [
{ label: 'Append samples to My Dataset', value: 'append' },
{ label: 'Replace samples in My Dataset', value: 'replace' }
]
const defaultValue = radioOptions[0].value
const [value, setValue] = useState(defaultValue)
const newTotalSamples = getTotalSamples(dataset.data)
const totalSamples = getTotalSamples(myDataset?.data)
const pathname = '/download'
const myDatasetTotalSamples = getTotalSamples(myDataset?.data)

const getRedirect = (prefix) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const getRedirect = (prefix) => {
const downloadRedirectWithPrefix = (prefix) => {

push({
pathname: '/download',
query: {
message: `${prefix} ${formatNumbers(
getTotalSamples(dataset.data) // display the shared dataset total samples
)} samples to My Dataset`,
status: 'success'
}
})
}

const handleMoveToDataset = async () => {
if (totalSamples > 0) {
openModal(id)
} else {
await addSamples(dataset.data)
push(
{
pathname,
query: {
message: `Appended ${formatNumbers(
newTotalSamples
)} samples to My Dataset`,
status: 'success'
}
},
pathname
)
}
const handleAppend = async () => {
await addSamples(dataset.data)
getRedirect('Appended')
}

const handleReplace = async () => {
await replaceSamples(dataset.data)
getRedirect('Moved')
}
Comment on lines +47 to +50
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const handleReplace = async () => {
await replaceSamples(dataset.data)
getRedirect('Moved')
}
const handlers = {
append: handleAppend,
replace: async () => {
await replaceSamples(dataset.data)
downloadRedirectWithPrefix('Moved')
}
}
const handleSelectAction = (action) => {
await handlers[action]()
// analytics
// close modal
}


// if no samples in myDataset, add shared samples on click without opening modal
if (myDatasetTotalSamples === 0) {
return <Button onClick={handleAppend} />
}

return (
<Modal
id={id}
button={
<Button
label="Move to Dataset"
secondary
responsive
onClick={handleMoveToDataset}
/>
}
id={modalId}
button={<Button onClick={() => openModal(modalId)} />}
fullHeight={false}
cleanUp={() => setValue(defaultValue)}
>
<MoveToDatasetModal
id={id}
closeModal={closeModal}
defaultValue={defaultValue}
dataset={dataset}
pathname={pathname}
radioOptions={radioOptions}
value={value}
setValue={setValue}
onAppend={handleAppend}
onReplace={handleReplace}
onCloseModal={() => closeModal(modalId)}
/>
</Modal>
)
Expand Down
76 changes: 23 additions & 53 deletions src/components/Dataset/MoveToDatasetModal.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useRouter } from 'next/router'
import { useState } from 'react'
import { Box, Heading } from 'grommet'
import gtag from 'analytics/gtag'
import { useDatasetManager } from 'hooks/useDatasetManager'
Expand All @@ -10,61 +10,31 @@ import { Icon } from 'components/shared/Icon'
import { RadioButtonGroup } from 'components/shared/RadioButtonGroup'
import { Row } from 'components/shared/Row'

export const MoveToDatasetModal = ({
id,
closeModal,
defaultValue,
dataset,
pathname,
radioOptions,
value,
setValue
}) => {
const {
dataset: datasetState,
loading,
addSamples,
getTotalSamples,
replaceSamples
} = useDatasetManager()
export const MoveToDatasetModal = ({ onAppend, onReplace, onCloseModal }) => {
const { setResponsive } = useResponsive()
const { push } = useRouter()
const totalSamples = formatNumbers(getTotalSamples(datasetState.data))
const newDatasetTotalSamples = formatNumbers(getTotalSamples(dataset.data))
const { dataset: myDataset, loading, getTotalSamples } = useDatasetManager()
const myDatasetTotalSamples = formatNumbers(getTotalSamples(myDataset?.data))

const handleMoveSamples = async (action = 'append') => {
const radioOptions = [
{ label: 'Append samples to My Dataset', value: 'append' },
{ label: 'Replace samples in My Dataset', value: 'replace' }
]
const defaultAction = radioOptions[0].value
const [action, setAction] = useState(defaultAction)

const handleMoveSamples = async () => {
if (action === 'append') {
await addSamples(dataset.data)
push(
{
pathname,
query: {
message: `Appended ${newDatasetTotalSamples} samples to My Dataset`,
status: 'success'
}
},
pathname
)
onAppend()
} else {
await replaceSamples(dataset.data)
push(
{
pathname,
query: {
message: `Moved ${newDatasetTotalSamples} samples to My Dataset`,
status: 'success'
}
},
pathname
)
onReplace()
}
gtag.trackDatasetAction(MoveToDatasetModal)
closeModal(id)
onCloseModal()
}

const handleClose = () => {
setValue(defaultValue)
closeModal(id)
const handleCancel = () => {
setAction(defaultAction)
onCloseModal()
}

return (
Expand All @@ -77,7 +47,7 @@ export const MoveToDatasetModal = ({
<Box direction="row" gap="xsmall" margin={{ bottom: 'medium' }}>
<Icon color="error" name="Warning" size="medium" />
<Heading level={2} size="small">
There are {totalSamples} samples in{' '}
There are {myDatasetTotalSamples} samples in{' '}
<Anchor href="/download" label="My Dataset" target="_blank" />
</Heading>
</Box>
Expand All @@ -88,18 +58,18 @@ export const MoveToDatasetModal = ({
<RadioButtonGroup
options={radioOptions}
name="move-to-dataset"
value={value}
onChange={(e) => setValue(e.target.value)}
value={action}
onChange={(e) => setAction(e.target.value)}
/>
</Box>
<Row justify="center" gap="small" width="100%">
<Button label="Cancel" secondary responsive onClick={handleClose} />
<Button label="Cancel" secondary responsive onClick={handleCancel} />
<Button
label="Move Samples"
isLoading={loading}
primary
responsive
onClick={() => handleMoveSamples(value)}
onClick={handleMoveSamples}
/>
</Row>
</Box>
Expand Down
39 changes: 39 additions & 0 deletions src/hooks/useWaitFor.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { useEffect, useRef } from 'react'

export const useWaitFor = (condition) => {
const resolveRef = useRef(null)
const promiseRef = useRef(null)
const latestConditionRef = useRef(condition)
const isPromiseInitialized = useRef(false)

const setupPromise = () => {
if (isPromiseInitialized.current) return
promiseRef.current = new Promise((resolve) => {
resolveRef.current = resolve
})

isPromiseInitialized.current = true
}

// initialize the promise when condition changes
useEffect(() => {
if (condition) {
setupPromise()
resolveRef.current()
}

latestConditionRef.current = condition
}, [condition])

return (cb) => {
return async (...args) => {
// ensure promise is initialized before executing callback
if (!isPromiseInitialized.current) {
setupPromise()
}

await promiseRef.current
return cb(...args, latestConditionRef.current)
}
}
}