@jbrowse/plugin-linear-genome-view 1.7.8 → 1.7.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/BaseLinearDisplay/components/BaseLinearDisplay.d.ts +1 -5
- package/dist/BaseLinearDisplay/components/BaseLinearDisplay.js +32 -120
- package/dist/BaseLinearDisplay/components/Tooltip.d.ts +8 -0
- package/dist/BaseLinearDisplay/components/Tooltip.js +125 -0
- package/dist/BaseLinearDisplay/models/BaseLinearDisplayModel.d.ts +4 -4
- package/dist/BaseLinearDisplay/models/BaseLinearDisplayModel.js +3 -2
- package/dist/LinearBareDisplay/model.d.ts +1 -1
- package/dist/LinearBasicDisplay/model.d.ts +1 -2
- package/dist/LinearBasicDisplay/model.js +2 -2
- package/dist/LinearGenomeView/components/ExportSvgDialog.js +35 -25
- package/dist/LinearGenomeView/components/Header.d.ts +0 -1
- package/dist/LinearGenomeView/components/Header.js +3 -1
- package/dist/LinearGenomeView/components/HelpDialog.js +2 -3
- package/dist/LinearGenomeView/components/ImportForm.d.ts +0 -1
- package/dist/LinearGenomeView/components/ImportForm.js +40 -70
- package/dist/LinearGenomeView/components/LinearGenomeView.js +6 -2
- package/dist/LinearGenomeView/components/LinearGenomeView.test.js +2 -2
- package/dist/LinearGenomeView/components/OverviewScaleBar.d.ts +21 -5
- package/dist/LinearGenomeView/components/OverviewScaleBar.js +25 -18
- package/dist/LinearGenomeView/components/ScaleBar.d.ts +6 -2
- package/dist/LinearGenomeView/components/ScaleBar.js +8 -3
- package/dist/LinearGenomeView/components/SearchBox.js +36 -72
- package/dist/LinearGenomeView/components/SearchResultsDialog.d.ts +1 -1
- package/dist/LinearGenomeView/components/SearchResultsDialog.js +0 -1
- package/dist/LinearGenomeView/components/TrackLabel.js +25 -41
- package/dist/LinearGenomeView/components/util.d.ts +12 -0
- package/dist/LinearGenomeView/components/util.js +59 -0
- package/dist/LinearGenomeView/index.d.ts +7 -11
- package/dist/LinearGenomeView/index.js +60 -33
- package/dist/LinearGenomeView/index.test.js +22 -5
- package/dist/index.d.ts +3 -3
- package/dist/index.js +22 -11
- package/package.json +3 -2
- package/src/BaseLinearDisplay/components/BaseLinearDisplay.tsx +4 -89
- package/src/BaseLinearDisplay/components/Tooltip.tsx +97 -0
- package/src/BaseLinearDisplay/models/BaseLinearDisplayModel.tsx +11 -4
- package/src/LinearBasicDisplay/model.ts +2 -4
- package/src/LinearGenomeView/components/ExportSvgDialog.tsx +24 -11
- package/src/LinearGenomeView/components/Header.tsx +2 -1
- package/src/LinearGenomeView/components/HelpDialog.tsx +5 -4
- package/src/LinearGenomeView/components/ImportForm.tsx +18 -25
- package/src/LinearGenomeView/components/LinearGenomeView.test.js +2 -2
- package/src/LinearGenomeView/components/LinearGenomeView.tsx +16 -10
- package/src/LinearGenomeView/components/OverviewScaleBar.tsx +42 -34
- package/src/LinearGenomeView/components/ScaleBar.tsx +6 -9
- package/src/LinearGenomeView/components/SearchBox.tsx +18 -29
- package/src/LinearGenomeView/components/SearchResultsDialog.tsx +0 -1
- package/src/LinearGenomeView/components/TrackLabel.tsx +25 -28
- package/src/LinearGenomeView/components/__snapshots__/LinearGenomeView.test.js.snap +4 -21
- package/src/LinearGenomeView/components/util.ts +43 -0
- package/src/LinearGenomeView/index.test.ts +20 -5
- package/src/LinearGenomeView/index.tsx +56 -27
- package/src/index.ts +35 -30
|
@@ -67,6 +67,7 @@ export interface BpOffset {
|
|
|
67
67
|
|
|
68
68
|
export interface ExportSvgOptions {
|
|
69
69
|
rasterizeLayers?: boolean
|
|
70
|
+
filename?: string
|
|
70
71
|
}
|
|
71
72
|
|
|
72
73
|
function calculateVisibleLocStrings(contentBlocks: BaseBlock[]) {
|
|
@@ -126,6 +127,7 @@ export function stateModelFactory(pluginManager: PluginManager) {
|
|
|
126
127
|
),
|
|
127
128
|
hideHeader: false,
|
|
128
129
|
hideHeaderOverview: false,
|
|
130
|
+
hideNoTracksActive: false,
|
|
129
131
|
trackSelectorType: types.optional(
|
|
130
132
|
types.enumeration(['hierarchical']),
|
|
131
133
|
'hierarchical',
|
|
@@ -176,11 +178,18 @@ export function stateModelFactory(pluginManager: PluginManager) {
|
|
|
176
178
|
get interRegionPaddingWidth() {
|
|
177
179
|
return INTER_REGION_PADDING_WIDTH
|
|
178
180
|
},
|
|
181
|
+
|
|
182
|
+
get assemblyNames() {
|
|
183
|
+
return [
|
|
184
|
+
...new Set(self.displayedRegions.map(region => region.assemblyName)),
|
|
185
|
+
]
|
|
186
|
+
},
|
|
179
187
|
}))
|
|
180
188
|
.views(self => ({
|
|
181
189
|
get assemblyErrors() {
|
|
182
190
|
const { assemblyManager } = getSession(self)
|
|
183
|
-
|
|
191
|
+
const { assemblyNames } = self
|
|
192
|
+
return assemblyNames
|
|
184
193
|
.map(a => assemblyManager.get(a)?.error)
|
|
185
194
|
.filter(f => !!f)
|
|
186
195
|
.join(', ')
|
|
@@ -188,9 +197,8 @@ export function stateModelFactory(pluginManager: PluginManager) {
|
|
|
188
197
|
|
|
189
198
|
get assembliesInitialized() {
|
|
190
199
|
const { assemblyManager } = getSession(self)
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
)
|
|
200
|
+
const { assemblyNames } = self
|
|
201
|
+
return assemblyNames.every(a => assemblyManager.get(a)?.initialized)
|
|
194
202
|
},
|
|
195
203
|
get initialized() {
|
|
196
204
|
return self.volatileWidth !== undefined && this.assembliesInitialized
|
|
@@ -272,11 +280,6 @@ export function stateModelFactory(pluginManager: PluginManager) {
|
|
|
272
280
|
}
|
|
273
281
|
},
|
|
274
282
|
|
|
275
|
-
get assemblyNames() {
|
|
276
|
-
return [
|
|
277
|
-
...new Set(self.displayedRegions.map(region => region.assemblyName)),
|
|
278
|
-
]
|
|
279
|
-
},
|
|
280
283
|
searchScope(assemblyName: string) {
|
|
281
284
|
return {
|
|
282
285
|
assemblyName,
|
|
@@ -285,13 +288,6 @@ export function stateModelFactory(pluginManager: PluginManager) {
|
|
|
285
288
|
}
|
|
286
289
|
},
|
|
287
290
|
|
|
288
|
-
/**
|
|
289
|
-
* @param refName - refName of the displayedRegion
|
|
290
|
-
* @param coord - coordinate at the displayed Region
|
|
291
|
-
* @param regionNumber - optional param used as identifier when
|
|
292
|
-
* there are multiple displayedRegions with the same refName
|
|
293
|
-
* @returns offsetPx of the displayed region that it lands in
|
|
294
|
-
*/
|
|
295
291
|
bpToPx({
|
|
296
292
|
refName,
|
|
297
293
|
coord,
|
|
@@ -395,10 +391,8 @@ export function stateModelFactory(pluginManager: PluginManager) {
|
|
|
395
391
|
track => track.configuration.trackId,
|
|
396
392
|
)
|
|
397
393
|
results.forEach(result => {
|
|
398
|
-
if (openTrackIds
|
|
399
|
-
|
|
400
|
-
result.updateScore(result.getScore() + 1)
|
|
401
|
-
}
|
|
394
|
+
if (openTrackIds.includes(result.trackId)) {
|
|
395
|
+
result.updateScore(result.getScore() + 1)
|
|
402
396
|
}
|
|
403
397
|
})
|
|
404
398
|
return results
|
|
@@ -406,7 +400,7 @@ export function stateModelFactory(pluginManager: PluginManager) {
|
|
|
406
400
|
|
|
407
401
|
// modifies view menu action onClick to apply to all tracks of same type
|
|
408
402
|
rewriteOnClicks(trackType: string, viewMenuActions: MenuItem[]) {
|
|
409
|
-
viewMenuActions.forEach(
|
|
403
|
+
viewMenuActions.forEach(action => {
|
|
410
404
|
// go to lowest level menu
|
|
411
405
|
if ('subMenu' in action) {
|
|
412
406
|
this.rewriteOnClicks(trackType, action.subMenu)
|
|
@@ -463,6 +457,9 @@ export function stateModelFactory(pluginManager: PluginManager) {
|
|
|
463
457
|
toggleHeaderOverview() {
|
|
464
458
|
self.hideHeaderOverview = !self.hideHeaderOverview
|
|
465
459
|
},
|
|
460
|
+
toggleNoTracksActive() {
|
|
461
|
+
self.hideNoTracksActive = !self.hideNoTracksActive
|
|
462
|
+
},
|
|
466
463
|
|
|
467
464
|
scrollTo(offsetPx: number) {
|
|
468
465
|
const newOffsetPx = clamp(offsetPx, self.minOffset, self.maxOffset)
|
|
@@ -674,13 +671,38 @@ export function stateModelFactory(pluginManager: PluginManager) {
|
|
|
674
671
|
const { assemblyManager } = getSession(self)
|
|
675
672
|
const { isValidRefName } = assemblyManager
|
|
676
673
|
const assemblyName = optAssemblyName || assemblyNames[0]
|
|
674
|
+
let parsedLocStrings
|
|
675
|
+
const inputs = locString
|
|
676
|
+
.split(/(\s+)/)
|
|
677
|
+
.map(f => f.trim())
|
|
678
|
+
.filter(f => !!f)
|
|
677
679
|
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
.map(l =>
|
|
680
|
+
// first try interpreting as a whitespace-separated sequence of
|
|
681
|
+
// multiple locstrings
|
|
682
|
+
try {
|
|
683
|
+
parsedLocStrings = inputs.map(l =>
|
|
684
|
+
parseLocString(l, ref => isValidRefName(ref, assemblyName)),
|
|
685
|
+
)
|
|
686
|
+
} catch (e) {
|
|
687
|
+
// if this fails, try interpreting as a whitespace-separated refname,
|
|
688
|
+
// start, end if start and end are integer inputs
|
|
689
|
+
const [refName, start, end] = inputs
|
|
690
|
+
if (
|
|
691
|
+
`${e}`.match(/Unknown reference sequence/) &&
|
|
692
|
+
Number.isInteger(+start) &&
|
|
693
|
+
Number.isInteger(+end)
|
|
694
|
+
) {
|
|
695
|
+
parsedLocStrings = [
|
|
696
|
+
parseLocString(refName + ':' + start + '..' + end, ref =>
|
|
697
|
+
isValidRefName(ref, assemblyName),
|
|
698
|
+
),
|
|
699
|
+
]
|
|
700
|
+
} else {
|
|
701
|
+
throw e
|
|
702
|
+
}
|
|
703
|
+
}
|
|
682
704
|
|
|
683
|
-
const locations = parsedLocStrings
|
|
705
|
+
const locations = parsedLocStrings?.map(region => {
|
|
684
706
|
const asmName = region.assemblyName || assemblyName
|
|
685
707
|
const asm = assemblyManager.get(asmName)
|
|
686
708
|
const { refName } = region
|
|
@@ -1206,6 +1228,13 @@ export function stateModelFactory(pluginManager: PluginManager) {
|
|
|
1206
1228
|
onClick: self.toggleHeaderOverview,
|
|
1207
1229
|
disabled: self.hideHeader,
|
|
1208
1230
|
},
|
|
1231
|
+
{
|
|
1232
|
+
label: 'Show no tracks active button',
|
|
1233
|
+
icon: VisibilityIcon,
|
|
1234
|
+
type: 'checkbox',
|
|
1235
|
+
checked: !self.hideNoTracksActive,
|
|
1236
|
+
onClick: self.toggleNoTracksActive,
|
|
1237
|
+
},
|
|
1209
1238
|
{
|
|
1210
1239
|
label: 'Track labels',
|
|
1211
1240
|
icon: LabelIcon,
|
|
@@ -1330,7 +1359,7 @@ export function stateModelFactory(pluginManager: PluginManager) {
|
|
|
1330
1359
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1331
1360
|
const html = await renderToSvg(self as any, opts)
|
|
1332
1361
|
const blob = new Blob([html], { type: 'image/svg+xml' })
|
|
1333
|
-
saveAs(blob, 'image.svg')
|
|
1362
|
+
saveAs(blob, opts.filename || 'image.svg')
|
|
1334
1363
|
},
|
|
1335
1364
|
}))
|
|
1336
1365
|
.views(self => ({
|
package/src/index.ts
CHANGED
|
@@ -137,42 +137,47 @@ export default class LinearGenomeViewPlugin extends Plugin {
|
|
|
137
137
|
loc: string
|
|
138
138
|
tracks?: string[]
|
|
139
139
|
}) => {
|
|
140
|
-
|
|
141
|
-
|
|
140
|
+
try {
|
|
141
|
+
const { assemblyManager } = session
|
|
142
|
+
const view = session.addView('LinearGenomeView', {}) as LGV
|
|
142
143
|
|
|
143
|
-
|
|
144
|
+
await when(() => !!view.volatileWidth)
|
|
144
145
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
146
|
+
if (!assembly) {
|
|
147
|
+
throw new Error(
|
|
148
|
+
'No assembly provided when launching linear genome view',
|
|
149
|
+
)
|
|
150
|
+
}
|
|
150
151
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
152
|
+
const asm = await assemblyManager.waitForAssembly(assembly)
|
|
153
|
+
if (!asm) {
|
|
154
|
+
throw new Error(
|
|
155
|
+
`Assembly "${assembly}" not found when launching linear genome view`,
|
|
156
|
+
)
|
|
157
|
+
}
|
|
157
158
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
159
|
+
view.navToLocString(loc, assembly)
|
|
160
|
+
|
|
161
|
+
const idsNotFound = [] as string[]
|
|
162
|
+
tracks.forEach(track => {
|
|
163
|
+
try {
|
|
164
|
+
view.showTrack(track)
|
|
165
|
+
} catch (e) {
|
|
166
|
+
if (`${e}`.match('Could not resolve identifier')) {
|
|
167
|
+
idsNotFound.push(track)
|
|
168
|
+
} else {
|
|
169
|
+
throw e
|
|
170
|
+
}
|
|
169
171
|
}
|
|
172
|
+
})
|
|
173
|
+
if (idsNotFound.length) {
|
|
174
|
+
throw new Error(
|
|
175
|
+
`Could not resolve identifiers: ${idsNotFound.join(',')}`,
|
|
176
|
+
)
|
|
170
177
|
}
|
|
171
|
-
})
|
|
172
|
-
|
|
173
|
-
throw
|
|
174
|
-
`Could not resolve identifiers: ${idsNotFound.join(',')}`,
|
|
175
|
-
)
|
|
178
|
+
} catch (e) {
|
|
179
|
+
session.notify(`${e}`, 'error')
|
|
180
|
+
throw e
|
|
176
181
|
}
|
|
177
182
|
},
|
|
178
183
|
)
|