diff --git a/packages/core/BaseFeatureWidget/BaseFeatureDetail/index.tsx b/packages/core/BaseFeatureWidget/BaseFeatureDetail/index.tsx index 753f380d3c..619b229d1f 100644 --- a/packages/core/BaseFeatureWidget/BaseFeatureDetail/index.tsx +++ b/packages/core/BaseFeatureWidget/BaseFeatureDetail/index.tsx @@ -68,7 +68,7 @@ export function BaseCard({ } > - {title} + {title} {children} diff --git a/packages/product-core/src/ui/AboutDialogContents.tsx b/packages/product-core/src/ui/AboutDialogContents.tsx index 44434327c7..f45e0a323d 100644 --- a/packages/product-core/src/ui/AboutDialogContents.tsx +++ b/packages/product-core/src/ui/AboutDialogContents.tsx @@ -14,11 +14,15 @@ import { Attributes, } from '@jbrowse/core/BaseFeatureWidget/BaseFeatureDetail' import FileInfoPanel from './FileInfoPanel' +import RefNamePanel from './RefNameInfoPanel' const useStyles = makeStyles()({ content: { minWidth: 800, }, + button: { + float: 'right', + }, }) function removeAttr(obj: Record, attr: string) { @@ -73,7 +77,7 @@ export default function AboutContents({ {!hideUris ? ( { const snap = removeAttr(clone(conf), 'baseUri') copy(JSON.stringify(snap, null, 2)) @@ -96,6 +100,7 @@ export default function AboutContents({ ) : null} + ) } diff --git a/packages/product-core/src/ui/RefNameInfoPanel.tsx b/packages/product-core/src/ui/RefNameInfoPanel.tsx new file mode 100644 index 0000000000..1989599fdc --- /dev/null +++ b/packages/product-core/src/ui/RefNameInfoPanel.tsx @@ -0,0 +1,108 @@ +import React, { useState, useEffect } from 'react' +import { Button, Typography } from '@mui/material' +import { + readConfObject, + AnyConfigurationModel, +} from '@jbrowse/core/configuration' +import LoadingEllipses from '@jbrowse/core/ui/LoadingEllipses' +import { getSession } from '@jbrowse/core/util' +import { BaseCard } from '@jbrowse/core/BaseFeatureWidget/BaseFeatureDetail' +import { observer } from 'mobx-react' +import { makeStyles } from 'tss-react/mui' +import FieldName from '@jbrowse/core/BaseFeatureWidget/BaseFeatureDetail/FieldName' +import copy from 'copy-to-clipboard' + +const MAX_REF_NAMES = 10_000 + +const useStyles = makeStyles()(theme => ({ + refNames: { + maxHeight: 300, + overflow: 'auto', + flexGrow: 1, + background: theme.palette.background.default, + }, + button: { + float: 'right', + }, +})) + +const RefNamePanel = observer(function ({ + config, +}: { + config: AnyConfigurationModel +}) { + const [error, setError] = useState() + const [refNames, setRefNames] = useState() + const [copied, setCopied] = useState(false) + const { classes } = useStyles() + const session = getSession(config) + const { rpcManager } = session + + useEffect(() => { + const aborter = new AbortController() + const { signal } = aborter + let cancelled = false + // eslint-disable-next-line @typescript-eslint/no-floating-promises + ;(async () => { + try { + const adapterConfig = readConfObject(config, 'adapter') + const refNames = await rpcManager.call( + config.trackId, + 'CoreGetRefNames', + { + adapterConfig, + signal, + }, + ) + if (!cancelled) { + setRefNames(refNames as string[]) + } + } catch (e) { + if (!cancelled) { + console.error(e) + setError(e) + } + } + })() + + return () => { + aborter.abort() + cancelled = true + } + }, [config, rpcManager]) + + return ( + + {error ? ( + {`${error}`} + ) : refNames === undefined ? ( + + ) : ( + <> + { + copy(JSON.stringify(refNames.join('\n'), null, 2)) + setCopied(true) + setTimeout(() => setCopied(false), 1000) + }} + > + {copied ? 'Copied to clipboard!' : 'Copy ref names'} + + + + + {refNames.slice(0, MAX_REF_NAMES).join('\n')} + {refNames.length > MAX_REF_NAMES + ? '\nToo many refNames to show in browser, use "Copy ref names" button to copy to clipboard' + : ''} + + + > + )} + + ) +}) + +export default RefNamePanel
+ {refNames.slice(0, MAX_REF_NAMES).join('\n')} + {refNames.length > MAX_REF_NAMES + ? '\nToo many refNames to show in browser, use "Copy ref names" button to copy to clipboard' + : ''} +