Skip to content

Commit

Permalink
Add ability to get refNames for a track in the "About track" panel (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
cmdcolin committed Jun 4, 2024
1 parent 286aa90 commit be77b18
Show file tree
Hide file tree
Showing 6 changed files with 164 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ export function BaseCard({
<AccordionSummary
expandIcon={<ExpandMore className={classes.expandIcon} />}
>
<Typography variant="button"> {title}</Typography>
<Typography variant="button">{title}</Typography>
</AccordionSummary>
<AccordionDetails className={classes.expansionPanelDetails}>
{children}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@ exports[`open up a widget 1`] = `
>
<span
class="MuiTypography-root MuiTypography-button css-1f0on15-MuiTypography-root"
>
</span>
/>
</div>
<div
class="MuiAccordionSummary-expandIconWrapper Mui-expanded css-yw020d-MuiAccordionSummary-expandIconWrapper"
Expand Down
50 changes: 36 additions & 14 deletions packages/product-core/src/ui/AboutDialogContents.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React, { useState } from 'react'
import { observer } from 'mobx-react'
import clone from 'clone'
import copy from 'copy-to-clipboard'
import { Button } from '@mui/material'
Expand All @@ -14,11 +15,15 @@ import {
Attributes,
} from '@jbrowse/core/BaseFeatureWidget/BaseFeatureDetail'
import FileInfoPanel from './FileInfoPanel'
import RefNameInfoDialog from './RefNameInfoDialog'

const useStyles = makeStyles()({
content: {
minWidth: 800,
},
button: {
float: 'right',
},
})

function removeAttr(obj: Record<string, unknown>, attr: string) {
Expand All @@ -32,7 +37,7 @@ function removeAttr(obj: Record<string, unknown>, attr: string) {
return obj
}

export default function AboutContents({
const AboutDialogContents = observer(function ({
config,
}: {
config: AnyConfigurationModel
Expand All @@ -41,6 +46,7 @@ export default function AboutContents({
const conf = readConfObject(config)
const session = getSession(config)
const { classes } = useStyles()
const [showRefNames, setShowRefNames] = useState(false)

const hideUris =
getConf(session, ['formatAbout', 'hideUris']) ||
Expand Down Expand Up @@ -71,18 +77,26 @@ export default function AboutContents({
<div className={classes.content}>
<BaseCard title="Configuration">
{!hideUris ? (
<Button
variant="contained"
style={{ float: 'right' }}
onClick={() => {
const snap = removeAttr(clone(conf), 'baseUri')
copy(JSON.stringify(snap, null, 2))
setCopied(true)
setTimeout(() => setCopied(false), 1000)
}}
>
{copied ? 'Copied to clipboard!' : 'Copy config'}
</Button>
<span className={classes.button}>
<Button
variant="contained"
color="secondary"
onClick={() => setShowRefNames(true)}
>
Show ref names
</Button>
<Button
variant="contained"
onClick={() => {
const snap = removeAttr(clone(conf), 'baseUri')
copy(JSON.stringify(snap, null, 2))
setCopied(true)
setTimeout(() => setCopied(false), 1000)
}}
>
{copied ? 'Copied to clipboard!' : 'Copy config'}
</Button>
</span>
) : null}
<Attributes
attributes={confPostExt}
Expand All @@ -96,6 +110,14 @@ export default function AboutContents({
</BaseCard>
) : null}
<FileInfoPanel config={config} />
{showRefNames ? (
<RefNameInfoDialog
config={config}
onClose={() => setShowRefNames(false)}
/>
) : null}
</div>
)
}
})

export default AboutDialogContents
126 changes: 126 additions & 0 deletions packages/product-core/src/ui/RefNameInfoDialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import React, { useState, useEffect } from 'react'
import { Button, DialogContent, Typography } from '@mui/material'
import {
readConfObject,
AnyConfigurationModel,
} from '@jbrowse/core/configuration'
import { Dialog, LoadingEllipses } from '@jbrowse/core/ui'
import { getSession } from '@jbrowse/core/util'
import { observer } from 'mobx-react'
import { makeStyles } from 'tss-react/mui'
import copy from 'copy-to-clipboard'

const MAX_REF_NAMES = 10_000

const useStyles = makeStyles()(theme => ({
container: {
minWidth: 800,
},
refNames: {
maxHeight: 300,
width: '100%',
overflow: 'auto',
flexGrow: 1,
background: theme.palette.background.default,
},
}))

const RefNameInfoDialog = observer(function ({
config,
onClose,
}: {
config: AnyConfigurationModel
onClose: () => void
}) {
const [error, setError] = useState<unknown>()
const [refNames, setRefNames] = useState<Record<string, string[]>>()
const [copied, setCopied] = useState(false)
const { classes } = useStyles()
const session = getSession(config)
const { rpcManager } = session

useEffect(() => {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
;(async () => {
try {
const assemblyNames = [
...new Set(readConfObject(config, 'assemblyNames') as string[]),
]
const map = await Promise.all(
assemblyNames.map(async assemblyName => {
const adapterConfig = readConfObject(config, 'adapter')
return [
assemblyName,
(await rpcManager.call(config.trackId, 'CoreGetRefNames', {
adapterConfig,
// hack for synteny adapters
regions: [{ assemblyName }],
})) as string[],
] as const
}),
)
setRefNames(Object.fromEntries(map))
} catch (e) {
console.error(e)
setError(e)
}
})()
}, [config, rpcManager])

const names = refNames ? Object.entries(refNames) : []
const result = names
.flatMap(([assemblyName, refNames]) => {
return [
`--- ${assemblyName} ---`,
...refNames.slice(0, MAX_REF_NAMES),
`${
refNames.length > MAX_REF_NAMES
? `\nToo many refNames to show in browser for ${assemblyName}, use "Copy ref names" button to copy to clipboard`
: ''
}`,
]
})
.filter(f => !!f)
.join('\n')

return (
<Dialog
open
title="Reference sequence names used in track"
onClose={onClose}
>
<DialogContent className={classes.container}>
{error ? (
<Typography color="error">{`${error}`}</Typography>
) : refNames === undefined ? (
<LoadingEllipses message="Loading refNames" />
) : (
<>
<Button
variant="contained"
onClick={() => {
copy(
names
.flatMap(([assemblyName, refNames]) => [
`--- ${assemblyName} ---`,
...refNames,
])
.filter(f => !!f)
.join('\n'),
)
setCopied(true)
setTimeout(() => setCopied(false), 1000)
}}
>
{copied ? 'Copied to clipboard!' : 'Copy ref names'}
</Button>

<pre className={classes.refNames}>{result}</pre>
</>
)}
</DialogContent>
</Dialog>
)
})

export default RefNameInfoDialog
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ exports[`open up a widget 1`] = `
<span
class="MuiTypography-root MuiTypography-button css-1f0on15-MuiTypography-root"
>
ctgA_3_555_0:0:0_2:0... - match
</span>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ exports[`renders with just the required model elements 1`] = `
<span
class="MuiTypography-root MuiTypography-button css-1f0on15-MuiTypography-root"
>
rs123
</span>
</div>
Expand Down

0 comments on commit be77b18

Please sign in to comment.