Skip to content

Commit

Permalink
Modularize
Browse files Browse the repository at this point in the history
  • Loading branch information
cmdcolin committed Jul 25, 2022
1 parent 8c7d532 commit 98d484e
Show file tree
Hide file tree
Showing 3 changed files with 228 additions and 220 deletions.
236 changes: 20 additions & 216 deletions plugins/data-management/src/AddTrackWidget/components/AddTrackWidget.tsx
Original file line number Diff line number Diff line change
@@ -1,210 +1,13 @@
import React, { useState } from 'react'
import {
Alert,
Button,
MenuItem,
Select,
Step,
StepContent,
StepLabel,
Stepper,
Typography,
} from '@mui/material'
import { makeStyles } from 'tss-react/mui'

import { useLocalStorage } from '@jbrowse/core/util'
import {
getSession,
isElectron,
supportedIndexingAdapters,
} from '@jbrowse/core/util'
import { getConf } from '@jbrowse/core/configuration'
import React from 'react'
import { observer } from 'mobx-react'
import { FormControl, FormHelperText, Select, MenuItem } from '@mui/material'
import { AddTrackWorkflowType } from '@jbrowse/core/pluggableElementTypes'
import { useLocalStorage } from '@jbrowse/core/util'
import { getEnv } from 'mobx-state-tree'

// locals
import ConfirmTrack from './ConfirmTrack'
import TrackSourceSelect from './TrackSourceSelect'
import { AddTrackModel } from '../model'
import { AddTrackWorkflowType } from '@jbrowse/core/pluggableElementTypes'

const useStyles = makeStyles()(theme => ({
root: {
marginTop: theme.spacing(1),
},
stepper: {
backgroundColor: theme.palette.background.default,
},
button: {
marginTop: theme.spacing(1),
marginRight: theme.spacing(1),
},
actionsContainer: {
marginBottom: theme.spacing(2),
},
stepContent: {
margin: theme.spacing(1),
},
alertContainer: {
padding: `${theme.spacing(2)}px 0px ${theme.spacing(2)}px 0px`,
},
}))

const steps = ['Enter track data', 'Confirm track type']

const AddTrackWorkflow = observer(({ model }: { model: AddTrackModel }) => {
const [activeStep, setActiveStep] = useState(0)
const { classes } = useStyles()
const { pluginManager } = getEnv(model)
const { rootModel } = pluginManager
const { jobsManager } = rootModel
const session = getSession(model)
const {
assembly,
trackAdapter,
trackData,
trackName,
trackType,
textIndexTrack,
textIndexingConf,
} = model
const [trackErrorMessage, setTrackErrorMessage] = useState<string>()

function getStepContent(step: number) {
switch (step) {
case 0:
return <TrackSourceSelect model={model} />
case 1:
return <ConfirmTrack model={model} />
default:
return <Typography>Unknown step</Typography>
}
}

async function handleNext() {
if (activeStep !== steps.length - 1) {
setActiveStep(activeStep + 1)
return
}

const trackId = [
`${trackName.toLowerCase().replace(/ /g, '_')}-${Date.now()}`,
`${session.adminMode ? '' : '-sessionTrack'}`,
].join('')

const assemblyInstance = session.assemblyManager.get(assembly)

if (trackAdapter && trackAdapter.type !== 'UNKNOWN') {
session.addTrackConf({
trackId,
type: trackType,
name: trackName,
assemblyNames: [assembly],
adapter: {
...trackAdapter,
sequenceAdapter: getConf(assemblyInstance, ['sequence', 'adapter']),
},
})
if (model.view) {
model.view.showTrack(trackId)
if (
isElectron &&
textIndexTrack &&
supportedIndexingAdapters(trackAdapter.type)
) {
const attr = textIndexingConf || {
attributes: ['Name', 'ID'],
exclude: ['CDS', 'exon'],
}
const indexName = trackName + '-index'
const newEntry = {
indexingParams: {
...attr,
assemblies: [assembly],
tracks: [trackId],
indexType: 'perTrack',
name: indexName,
timestamp: new Date().toISOString(),
},
name: indexName,
cancelCallback: () => jobsManager.abortJob(),
}
jobsManager.queueJob(newEntry)
}
} else {
session.notify(
'Open a new view, or use the track selector in an existing view, to view this track',
'info',
)
}
model.clearData()
session.hideWidget(model)
} else {
setTrackErrorMessage(
'Failed to add track.\nThe configuration of this file is not currently supported.',
)
}
}

function handleBack() {
setTrackErrorMessage(undefined)
setActiveStep(activeStep - 1)
}

function isNextDisabled() {
switch (activeStep) {
case 0:
return !trackData
case 1:
return !(trackName && trackType && trackAdapter?.type && assembly)
default:
return true
}
}

return (
<div className={classes.root}>
<Stepper
className={classes.stepper}
activeStep={activeStep}
orientation="vertical"
>
{steps.map((label, idx) => (
<Step key={label}>
<StepLabel>{label}</StepLabel>
<StepContent>
{getStepContent(idx)}
<div className={classes.actionsContainer}>
<Button
disabled={activeStep === 0}
onClick={handleBack}
className={classes.button}
>
Back
</Button>
<Button
disabled={isNextDisabled()}
variant="contained"
color="primary"
onClick={handleNext}
className={classes.button}
data-testid="addTrackNextButton"
>
{activeStep === steps.length - 1 ? 'Add' : 'Next'}
</Button>
</div>
{trackErrorMessage ? (
<div className={classes.alertContainer}>
<Alert severity="error">{trackErrorMessage}</Alert>
</div>
) : null}
</StepContent>
</Step>
))}
</Stepper>
</div>
)
})
import DefaultAddTrackWorkflow from './DefaultAddTrackWorkflow'

function AddTrackSelector({ model }: { model: AddTrackModel }) {
const [val, setVal] = useLocalStorage('trackSelector-choice', 'Default')
Expand All @@ -213,25 +16,26 @@ function AddTrackSelector({ model }: { model: AddTrackModel }) {
'add track workflow',
) as AddTrackWorkflowType[]
const ComponentMap = {
Default: AddTrackWorkflow,
Default: DefaultAddTrackWorkflow,
...Object.fromEntries(widgets.map(w => [w.name, w.ReactComponent])),
} as { [key: string]: React.FC<{ model: AddTrackModel }> }

// make sure it is in the list
const effectiveVal = ComponentMap[val] ? val : 'Default'
const Component = ComponentMap[effectiveVal]
// make sure the selected value is in the list
const val2 = ComponentMap[val] ? val : 'Default'
const Component = ComponentMap[val2]
return (
<>
<Select
value={effectiveVal}
onChange={event => setVal(event.target.value)}
>
{Object.keys(ComponentMap).map(e => (
<MenuItem key={e} value={e}>
{e}
</MenuItem>
))}
</Select>
<FormControl>
<Select value={val2} onChange={event => setVal(event.target.value)}>
{Object.keys(ComponentMap).map(e => (
<MenuItem key={e} value={e}>
{e}
</MenuItem>
))}
</Select>
<FormHelperText>Type of add track workflow</FormHelperText>
</FormControl>

<br />
<Component model={model} />
</>
Expand Down
Loading

0 comments on commit 98d484e

Please sign in to comment.