Skip to content

Commit

Permalink
Add example of using hideSubfeatures on the bigbed example
Browse files Browse the repository at this point in the history
  • Loading branch information
cmdcolin committed Nov 27, 2023
1 parent 957788c commit 3ea0f52
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 19 deletions.
6 changes: 2 additions & 4 deletions packages/core/BaseFeatureWidget/BaseFeatureDetail/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -177,10 +177,8 @@ export function FeatureDetails(props: {
formatter?: (val: unknown, key: string) => React.ReactNode
}) {
const { omit = [], model, feature, depth = 0 } = props
const { maxDepth } = model
const { mate, name = '', id = '', type = '', subfeatures, uniqueId } = feature
// @ts-expect-error
// eslint-disable-next-line no-underscore-dangle
const { hideSubfeatures } = feature.__jbrowsefmt
const pm = getEnv(model).pluginManager
const session = getSession(model)

Expand Down Expand Up @@ -226,7 +224,7 @@ export function FeatureDetails(props: {
</>
) : null}

{!hideSubfeatures && subfeatures?.length ? (
{depth < maxDepth && subfeatures?.length ? (
<BaseCard title="Subfeatures" defaultExpanded={depth < 1}>
{subfeatures.map((sub, idx) => (
<FeatureDetails
Expand Down
86 changes: 75 additions & 11 deletions packages/core/BaseFeatureWidget/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,49 +22,103 @@ function formatSubfeatures(
returnObj = {} as Record<string, unknown>,
) {
if (depth <= currentDepth) {
return returnObj
return
}
returnObj.subfeatures = obj.subfeatures?.map(sub => {
obj.subfeatures?.map(sub => {
formatSubfeatures(sub, depth, parse, currentDepth + 1, returnObj)
return parse(sub)
parse(sub)
})
return returnObj
}

/**
* #stateModel BaseFeatureWidget
* displays data about features, allowing configuration callbacks to modify the
* contents of what is displayed
*
* see: formatDetails-\>feature,formatDetails-\>subfeatures
*/
export default function stateModelFactory(pluginManager: PluginManager) {
return types
.model('BaseFeatureWidget', {
/**
* #property
*/
id: ElementId,
/**
* #property
*/
type: types.literal('BaseFeatureWidget'),
/**
* #property
*/
featureData: types.frozen(),
/**
* #property
*/
formattedFields: types.frozen(),
/**
* #property
*/
unformattedFeatureData: types.frozen(),
/**
* #property
*/
view: types.safeReference(
pluginManager.pluggableMstType('view', 'stateModel'),
),
/**
* #property
*/
track: types.safeReference(
pluginManager.pluggableMstType('track', 'stateModel'),
),
/**
* #property
*/
trackId: types.maybe(types.string),
/**
* #property
*/
trackType: types.maybe(types.string),
/**
* #property
*/
maxDepth: types.maybe(types.number),
})
.volatile(() => ({
error: undefined as unknown,
}))

.actions(self => ({
/**
* #action
*/
setFeatureData(featureData: Record<string, unknown>) {
self.unformattedFeatureData = featureData
},
/**
* #action
*/
clearFeatureData() {
self.featureData = undefined
},
/**
* #action
*/
setFormattedData(feat: Record<string, unknown>) {
self.featureData = feat
},
setExtra(type?: string, trackId?: string) {
/**
* #action
*/
setExtra(type?: string, trackId?: string, maxDepth?: number) {
self.trackId = trackId
self.trackType = type
self.maxDepth = maxDepth
},
/**
* #action
*/
setError(e: unknown) {
self.error = e
},
Expand All @@ -75,9 +129,15 @@ export default function stateModelFactory(pluginManager: PluginManager) {
self,
autorun(() => {
try {
self.setExtra(self.track?.type, self.track?.configuration.trackId)
const { unformattedFeatureData, track } = self
const session = getSession(self)
if (track) {
self.setExtra(
track.type,
track.configuration.trackId,
getConf(track, ['formatDetails', 'maxDepth']),
)
}
if (unformattedFeatureData) {
const feature = clone(unformattedFeatureData)

Expand All @@ -92,11 +152,15 @@ export default function stateModelFactory(pluginManager: PluginManager) {
if (track) {
// eslint-disable-next-line no-underscore-dangle
feature.__jbrowsefmt = combine('feature', feature)
const depth = getConf(track, ['formatDetails', 'depth'])
formatSubfeatures(feature, depth, sub => {
// eslint-disable-next-line no-underscore-dangle
sub.__jbrowsefmt = combine('subfeatures', sub)
})

formatSubfeatures(
feature,
getConf(track, ['formatDetails', 'depth']),
sub => {
// eslint-disable-next-line no-underscore-dangle
sub.__jbrowsefmt = combine('subfeatures', sub)
},
)
}

self.setFormattedData(feature)
Expand Down
10 changes: 8 additions & 2 deletions packages/core/pluggableElementTypes/models/baseTrackConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,6 @@ export function createBaseTrackConfig(pluginManager: PluginManager) {
defaultValue: {},
contextVariable: ['feature'],
},

/**
* #slot formatDetails.subfeatures
*/
Expand All @@ -106,7 +105,6 @@ export function createBaseTrackConfig(pluginManager: PluginManager) {
defaultValue: {},
contextVariable: ['feature'],
},

/**
* #slot formatDetails.depth
*/
Expand All @@ -116,6 +114,14 @@ export function createBaseTrackConfig(pluginManager: PluginManager) {
description:
'depth of subfeatures to iterate the formatter on formatDetails.subfeatures (e.g. you may not want to format the exon/cds subfeatures, so limited to 2',
},
/**
* #slot formatDetails.maxDepth
*/
maxDepth: {
type: 'number',
defaultValue: 99999,
description: 'Maximum depth to render subfeatures',
},
}),
formatAbout: ConfigurationSchema('FormatAbout', {
/**
Expand Down
14 changes: 12 additions & 2 deletions packages/product-core/src/RootModel/FormatDetails.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { ConfigurationSchema } from '@jbrowse/core/configuration'
/**
* #config FormatDetails
* generally exists on the config.json or root config as configuration.formatDetails
* generally exists on the tracks in the config.json or as a 'session' config as
* configuration.formatDetails
*/
export function FormatDetailsConfigSchemaFactory() {
return ConfigurationSchema('FormatDetails', {
Expand Down Expand Up @@ -29,7 +30,16 @@ export function FormatDetailsConfigSchemaFactory() {
depth: {
type: 'number',
defaultValue: 2,
description: 'depth to iterate on subfeatures',
description:
'depth to iterate the formatDetails->subfeatures callback on subfeatures (used for example to only apply the callback to the first layer of subfeatures)',
},
/**
* #slot configuration.formatDetails.maxDepth
*/
maxDepth: {
type: 'number',
defaultValue: 10000,
description: 'hide subfeatures greater than a certain depth',
},
})
}
Original file line number Diff line number Diff line change
Expand Up @@ -2361,6 +2361,9 @@ exports[`JBrowse model creates with non-empty snapshot 1`] = `
"type": "LinearArcDisplay",
},
],
"formatDetails": {
"maxDepth": 0,
},
"name": "BigBed genes",
"trackId": "bigbed_genes",
"type": "FeatureTrack",
Expand Down
3 changes: 3 additions & 0 deletions test_data/volvox/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -1187,6 +1187,9 @@
"type": "FeatureTrack",
"trackId": "bigbed_genes",
"name": "BigBed genes",
"formatDetails": {
"maxDepth": 0
},
"assemblyNames": ["volvox"],
"category": ["Miscellaneous"],
"adapter": {
Expand Down

0 comments on commit 3ea0f52

Please sign in to comment.