@jbrowse/plugin-data-management 2.0.1 → 2.1.0
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/AddTrackWidget/components/AddTrackWidget.d.ts +2 -2
- package/dist/AddTrackWidget/components/AddTrackWidget.js +18 -189
- package/dist/AddTrackWidget/components/AddTrackWidget.js.map +1 -1
- package/dist/AddTrackWidget/components/ConfirmTrack.js +5 -6
- package/dist/AddTrackWidget/components/ConfirmTrack.js.map +1 -1
- package/dist/AddTrackWidget/components/DefaultAddTrackWorkflow.d.ts +7 -0
- package/dist/AddTrackWidget/components/DefaultAddTrackWorkflow.js +222 -0
- package/dist/AddTrackWidget/components/DefaultAddTrackWorkflow.js.map +1 -0
- package/dist/HierarchicalTrackSelectorWidget/components/Header.d.ts +10 -0
- package/dist/HierarchicalTrackSelectorWidget/components/Header.js +209 -0
- package/dist/HierarchicalTrackSelectorWidget/components/Header.js.map +1 -0
- package/dist/HierarchicalTrackSelectorWidget/components/HierarchicalTrackSelector.js +22 -231
- package/dist/HierarchicalTrackSelectorWidget/components/HierarchicalTrackSelector.js.map +1 -1
- package/dist/HierarchicalTrackSelectorWidget/components/Node.d.ts +29 -0
- package/dist/HierarchicalTrackSelectorWidget/components/Node.js +207 -0
- package/dist/HierarchicalTrackSelectorWidget/components/Node.js.map +1 -0
- package/dist/HierarchicalTrackSelectorWidget/components/util.d.ts +3 -0
- package/dist/HierarchicalTrackSelectorWidget/components/util.js +11 -0
- package/dist/HierarchicalTrackSelectorWidget/components/util.js.map +1 -0
- package/dist/HierarchicalTrackSelectorWidget/configSchema.d.ts +2 -0
- package/dist/HierarchicalTrackSelectorWidget/configSchema.js +6 -0
- package/dist/HierarchicalTrackSelectorWidget/configSchema.js.map +1 -0
- package/dist/HierarchicalTrackSelectorWidget/index.d.ts +4 -2
- package/dist/HierarchicalTrackSelectorWidget/index.js +4 -4
- package/dist/HierarchicalTrackSelectorWidget/index.js.map +1 -1
- package/dist/HierarchicalTrackSelectorWidget/model.d.ts +10 -2
- package/dist/HierarchicalTrackSelectorWidget/model.js +35 -31
- package/dist/HierarchicalTrackSelectorWidget/model.js.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/esm/AddTrackWidget/components/AddTrackWidget.d.ts +2 -2
- package/esm/AddTrackWidget/components/AddTrackWidget.js +22 -135
- package/esm/AddTrackWidget/components/AddTrackWidget.js.map +1 -1
- package/esm/AddTrackWidget/components/ConfirmTrack.js +5 -6
- package/esm/AddTrackWidget/components/ConfirmTrack.js.map +1 -1
- package/esm/AddTrackWidget/components/DefaultAddTrackWorkflow.d.ts +7 -0
- package/esm/AddTrackWidget/components/DefaultAddTrackWorkflow.js +134 -0
- package/esm/AddTrackWidget/components/DefaultAddTrackWorkflow.js.map +1 -0
- package/esm/HierarchicalTrackSelectorWidget/components/Header.d.ts +10 -0
- package/esm/HierarchicalTrackSelectorWidget/components/Header.js +149 -0
- package/esm/HierarchicalTrackSelectorWidget/components/Header.js.map +1 -0
- package/esm/HierarchicalTrackSelectorWidget/components/HierarchicalTrackSelector.js +24 -223
- package/esm/HierarchicalTrackSelectorWidget/components/HierarchicalTrackSelector.js.map +1 -1
- package/esm/HierarchicalTrackSelectorWidget/components/Node.d.ts +29 -0
- package/esm/HierarchicalTrackSelectorWidget/components/Node.js +149 -0
- package/esm/HierarchicalTrackSelectorWidget/components/Node.js.map +1 -0
- package/esm/HierarchicalTrackSelectorWidget/components/util.d.ts +3 -0
- package/esm/HierarchicalTrackSelectorWidget/components/util.js +5 -0
- package/esm/HierarchicalTrackSelectorWidget/components/util.js.map +1 -0
- package/esm/HierarchicalTrackSelectorWidget/configSchema.d.ts +2 -0
- package/esm/HierarchicalTrackSelectorWidget/configSchema.js +4 -0
- package/esm/HierarchicalTrackSelectorWidget/configSchema.js.map +1 -0
- package/esm/HierarchicalTrackSelectorWidget/index.d.ts +4 -2
- package/esm/HierarchicalTrackSelectorWidget/index.js +3 -3
- package/esm/HierarchicalTrackSelectorWidget/index.js.map +1 -1
- package/esm/HierarchicalTrackSelectorWidget/model.d.ts +10 -2
- package/esm/HierarchicalTrackSelectorWidget/model.js +36 -32
- package/esm/HierarchicalTrackSelectorWidget/model.js.map +1 -1
- package/esm/index.d.ts +4 -1
- package/esm/index.js +1 -1
- package/esm/index.js.map +1 -1
- package/package.json +2 -2
- package/src/AddTrackWidget/components/{AddTrackWidget.test.js → AddTrackWidget.test.tsx} +17 -32
- package/src/AddTrackWidget/components/AddTrackWidget.tsx +36 -200
- package/src/AddTrackWidget/components/ConfirmTrack.tsx +10 -10
- package/src/AddTrackWidget/components/DefaultAddTrackWorkflow.tsx +205 -0
- package/src/HierarchicalTrackSelectorWidget/components/Header.tsx +287 -0
- package/src/HierarchicalTrackSelectorWidget/components/HierarchicalTrackSelector.tsx +19 -438
- package/src/HierarchicalTrackSelectorWidget/components/Node.tsx +284 -0
- package/src/HierarchicalTrackSelectorWidget/components/util.ts +11 -0
- package/src/HierarchicalTrackSelectorWidget/configSchema.ts +3 -0
- package/src/HierarchicalTrackSelectorWidget/index.ts +4 -6
- package/src/HierarchicalTrackSelectorWidget/model.ts +45 -41
- package/src/index.ts +4 -1
- package/src/AddTrackWidget/components/__snapshots__/AddTrackWidget.test.js.snap +0 -331
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
import React, { useState } from 'react'
|
|
2
|
+
import {
|
|
3
|
+
Checkbox,
|
|
4
|
+
FormControlLabel,
|
|
5
|
+
IconButton,
|
|
6
|
+
Tooltip,
|
|
7
|
+
Typography,
|
|
8
|
+
} from '@mui/material'
|
|
9
|
+
import { makeStyles } from 'tss-react/mui'
|
|
10
|
+
|
|
11
|
+
// icons
|
|
12
|
+
import ArrowDropDownIcon from '@mui/icons-material/ArrowDropDown'
|
|
13
|
+
import ArrowRightIcon from '@mui/icons-material/ArrowRight'
|
|
14
|
+
import MoreHorizIcon from '@mui/icons-material/MoreHoriz'
|
|
15
|
+
|
|
16
|
+
// other
|
|
17
|
+
import { HierarchicalTrackSelectorModel, TreeNode } from '../model'
|
|
18
|
+
import JBrowseMenu from '@jbrowse/core/ui/Menu'
|
|
19
|
+
import { getSession } from '@jbrowse/core/util'
|
|
20
|
+
|
|
21
|
+
import {
|
|
22
|
+
AnyConfigurationModel,
|
|
23
|
+
readConfObject,
|
|
24
|
+
} from '@jbrowse/core/configuration'
|
|
25
|
+
import { getAllChildren } from './util'
|
|
26
|
+
|
|
27
|
+
const useStyles = makeStyles()(theme => ({
|
|
28
|
+
compactCheckbox: {
|
|
29
|
+
padding: 0,
|
|
30
|
+
},
|
|
31
|
+
|
|
32
|
+
checkboxLabel: {
|
|
33
|
+
marginRight: 0,
|
|
34
|
+
'&:hover': {
|
|
35
|
+
backgroundColor: '#eee',
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
|
|
39
|
+
contrastColor: {
|
|
40
|
+
color: theme.palette.secondary.contrastText,
|
|
41
|
+
},
|
|
42
|
+
|
|
43
|
+
// this accordionBase element's small padding is used to give a margin to
|
|
44
|
+
// accordionColor it a "margin" because the virtualized elements can't really
|
|
45
|
+
// use margin in a conventional way (it doesn't affect layout)
|
|
46
|
+
accordionBase: {
|
|
47
|
+
display: 'flex',
|
|
48
|
+
},
|
|
49
|
+
|
|
50
|
+
accordionCard: {
|
|
51
|
+
padding: 3,
|
|
52
|
+
cursor: 'pointer',
|
|
53
|
+
display: 'flex',
|
|
54
|
+
},
|
|
55
|
+
|
|
56
|
+
nestingLevelMarker: {
|
|
57
|
+
position: 'absolute',
|
|
58
|
+
borderLeft: '1.5px solid #555',
|
|
59
|
+
},
|
|
60
|
+
// accordionColor set's display:flex so that the child accordionText use
|
|
61
|
+
// vertically centered text
|
|
62
|
+
accordionColor: {
|
|
63
|
+
// @ts-ignore
|
|
64
|
+
background: theme.palette.tertiary?.main,
|
|
65
|
+
// @ts-ignore
|
|
66
|
+
color: theme.palette.tertiary?.contrastText,
|
|
67
|
+
width: '100%',
|
|
68
|
+
display: 'flex',
|
|
69
|
+
paddingLeft: 5,
|
|
70
|
+
},
|
|
71
|
+
|
|
72
|
+
// margin:auto 0 to center text vertically
|
|
73
|
+
accordionText: {
|
|
74
|
+
margin: 'auto 0',
|
|
75
|
+
},
|
|
76
|
+
}))
|
|
77
|
+
|
|
78
|
+
export interface InfoArgs {
|
|
79
|
+
target: HTMLElement
|
|
80
|
+
id: string
|
|
81
|
+
conf: AnyConfigurationModel
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function treeToMap(tree: TreeNode, map = new Map<string, TreeNode>()) {
|
|
85
|
+
if (tree.id && tree.children.length) {
|
|
86
|
+
map.set(tree.id, tree)
|
|
87
|
+
}
|
|
88
|
+
for (let i = 0; i < tree.children.length; i++) {
|
|
89
|
+
const node = tree.children[i]
|
|
90
|
+
treeToMap(node, map)
|
|
91
|
+
}
|
|
92
|
+
return map
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function isUnsupported(name = '') {
|
|
96
|
+
return name.endsWith('(Unsupported)') || name.endsWith('(Unknown)')
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// An individual node in the track selector. Note: manually sets cursor:
|
|
100
|
+
// pointer improves usability for what can be clicked
|
|
101
|
+
export default function Node(props: {
|
|
102
|
+
data: {
|
|
103
|
+
nestingLevel: number
|
|
104
|
+
checked: boolean
|
|
105
|
+
conf: AnyConfigurationModel
|
|
106
|
+
drawerPosition: unknown
|
|
107
|
+
id: string
|
|
108
|
+
isLeaf: boolean
|
|
109
|
+
name: string
|
|
110
|
+
onChange: Function
|
|
111
|
+
toggleCollapse: (arg: string) => void
|
|
112
|
+
tree: TreeNode
|
|
113
|
+
selected: boolean
|
|
114
|
+
model: HierarchicalTrackSelectorModel
|
|
115
|
+
}
|
|
116
|
+
isOpen: boolean
|
|
117
|
+
style?: { height: number }
|
|
118
|
+
setOpen: (arg: boolean) => void
|
|
119
|
+
}) {
|
|
120
|
+
const { data, isOpen, style, setOpen } = props
|
|
121
|
+
const {
|
|
122
|
+
checked,
|
|
123
|
+
conf,
|
|
124
|
+
drawerPosition,
|
|
125
|
+
id,
|
|
126
|
+
isLeaf,
|
|
127
|
+
model,
|
|
128
|
+
name,
|
|
129
|
+
nestingLevel,
|
|
130
|
+
onChange,
|
|
131
|
+
selected,
|
|
132
|
+
toggleCollapse,
|
|
133
|
+
tree,
|
|
134
|
+
} = data
|
|
135
|
+
|
|
136
|
+
const { classes } = useStyles()
|
|
137
|
+
const width = 10
|
|
138
|
+
const [menuEl, setMenuEl] = useState<HTMLElement | null>(null)
|
|
139
|
+
const [info, setInfo] = useState<InfoArgs>()
|
|
140
|
+
const marginLeft = nestingLevel * width + (isLeaf ? width : 0)
|
|
141
|
+
const description = (conf && readConfObject(conf, ['description'])) || ''
|
|
142
|
+
|
|
143
|
+
return (
|
|
144
|
+
<div style={style} className={!isLeaf ? classes.accordionBase : undefined}>
|
|
145
|
+
{new Array(nestingLevel).fill(0).map((_, idx) => (
|
|
146
|
+
<div
|
|
147
|
+
key={`mark-${idx}`}
|
|
148
|
+
style={{ left: idx * width + 4, height: style?.height }}
|
|
149
|
+
className={classes.nestingLevelMarker}
|
|
150
|
+
/>
|
|
151
|
+
))}
|
|
152
|
+
<div
|
|
153
|
+
className={!isLeaf ? classes.accordionCard : undefined}
|
|
154
|
+
onClick={() => {
|
|
155
|
+
if (!menuEl) {
|
|
156
|
+
toggleCollapse(id)
|
|
157
|
+
setOpen(!isOpen)
|
|
158
|
+
}
|
|
159
|
+
}}
|
|
160
|
+
style={{
|
|
161
|
+
marginLeft,
|
|
162
|
+
whiteSpace: 'nowrap',
|
|
163
|
+
width: '100%',
|
|
164
|
+
}}
|
|
165
|
+
>
|
|
166
|
+
<div className={!isLeaf ? classes.accordionColor : undefined}>
|
|
167
|
+
{!isLeaf ? (
|
|
168
|
+
<div className={classes.accordionText}>
|
|
169
|
+
<Typography>
|
|
170
|
+
{isOpen ? <ArrowDropDownIcon /> : <ArrowRightIcon />}
|
|
171
|
+
{name}
|
|
172
|
+
<IconButton
|
|
173
|
+
onClick={event => {
|
|
174
|
+
setMenuEl(event.currentTarget)
|
|
175
|
+
event.stopPropagation()
|
|
176
|
+
}}
|
|
177
|
+
className={classes.contrastColor}
|
|
178
|
+
>
|
|
179
|
+
<MoreHorizIcon />
|
|
180
|
+
</IconButton>
|
|
181
|
+
</Typography>
|
|
182
|
+
</div>
|
|
183
|
+
) : (
|
|
184
|
+
<>
|
|
185
|
+
<Tooltip
|
|
186
|
+
title={description + (selected ? ' (in selection)' : '')}
|
|
187
|
+
placement={drawerPosition === 'left' ? 'right' : 'left'}
|
|
188
|
+
>
|
|
189
|
+
<FormControlLabel
|
|
190
|
+
className={classes.checkboxLabel}
|
|
191
|
+
control={
|
|
192
|
+
<Checkbox
|
|
193
|
+
className={classes.compactCheckbox}
|
|
194
|
+
checked={checked}
|
|
195
|
+
onChange={() => onChange(id)}
|
|
196
|
+
disabled={isUnsupported(name)}
|
|
197
|
+
inputProps={{
|
|
198
|
+
// @ts-ignore
|
|
199
|
+
'data-testid': `htsTrackEntry-${id}`,
|
|
200
|
+
}}
|
|
201
|
+
/>
|
|
202
|
+
}
|
|
203
|
+
label={
|
|
204
|
+
<div
|
|
205
|
+
style={{
|
|
206
|
+
background: selected ? '#cccc' : undefined,
|
|
207
|
+
padding: 1,
|
|
208
|
+
}}
|
|
209
|
+
>
|
|
210
|
+
{name}
|
|
211
|
+
</div>
|
|
212
|
+
}
|
|
213
|
+
/>
|
|
214
|
+
</Tooltip>
|
|
215
|
+
<IconButton
|
|
216
|
+
onClick={e => setInfo({ target: e.currentTarget, id, conf })}
|
|
217
|
+
style={{ padding: 0 }}
|
|
218
|
+
color="secondary"
|
|
219
|
+
data-testid={`htsTrackEntryMenu-${id}`}
|
|
220
|
+
>
|
|
221
|
+
<MoreHorizIcon />
|
|
222
|
+
</IconButton>
|
|
223
|
+
</>
|
|
224
|
+
)}
|
|
225
|
+
{menuEl ? (
|
|
226
|
+
<JBrowseMenu
|
|
227
|
+
anchorEl={menuEl}
|
|
228
|
+
menuItems={[
|
|
229
|
+
{
|
|
230
|
+
label: 'Add to selection',
|
|
231
|
+
onClick: () =>
|
|
232
|
+
model.addToSelection(
|
|
233
|
+
getAllChildren(treeToMap(tree).get(id)),
|
|
234
|
+
),
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
label: 'Remove from selection',
|
|
238
|
+
onClick: () =>
|
|
239
|
+
model.removeFromSelection(
|
|
240
|
+
getAllChildren(treeToMap(tree).get(id)),
|
|
241
|
+
),
|
|
242
|
+
},
|
|
243
|
+
]}
|
|
244
|
+
onMenuItemClick={(_event, callback) => {
|
|
245
|
+
callback()
|
|
246
|
+
setMenuEl(null)
|
|
247
|
+
}}
|
|
248
|
+
open={Boolean(menuEl)}
|
|
249
|
+
onClose={() => setMenuEl(null)}
|
|
250
|
+
/>
|
|
251
|
+
) : null}
|
|
252
|
+
|
|
253
|
+
{info ? (
|
|
254
|
+
<JBrowseMenu
|
|
255
|
+
anchorEl={info?.target}
|
|
256
|
+
menuItems={[
|
|
257
|
+
...(getSession(model).getTrackActionMenuItems?.(info.conf) ||
|
|
258
|
+
[]),
|
|
259
|
+
{
|
|
260
|
+
label: 'Add to selection',
|
|
261
|
+
onClick: () => model.addToSelection([info.conf]),
|
|
262
|
+
},
|
|
263
|
+
...(selected
|
|
264
|
+
? [
|
|
265
|
+
{
|
|
266
|
+
label: 'Remove from selection',
|
|
267
|
+
onClick: () => model.removeFromSelection([info.conf]),
|
|
268
|
+
},
|
|
269
|
+
]
|
|
270
|
+
: []),
|
|
271
|
+
]}
|
|
272
|
+
onMenuItemClick={(_event, callback) => {
|
|
273
|
+
callback()
|
|
274
|
+
setInfo(undefined)
|
|
275
|
+
}}
|
|
276
|
+
open={Boolean(info)}
|
|
277
|
+
onClose={() => setInfo(undefined)}
|
|
278
|
+
/>
|
|
279
|
+
) : null}
|
|
280
|
+
</div>
|
|
281
|
+
</div>
|
|
282
|
+
</div>
|
|
283
|
+
)
|
|
284
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { AnyConfigurationModel } from '@jbrowse/core/configuration'
|
|
2
|
+
import { TreeNode } from '../model'
|
|
3
|
+
|
|
4
|
+
export function getAllChildren(subtree?: TreeNode): AnyConfigurationModel[] {
|
|
5
|
+
// @ts-ignore
|
|
6
|
+
return (
|
|
7
|
+
subtree?.children.map(t =>
|
|
8
|
+
t.children.length ? getAllChildren(t) : (t.conf as AnyConfigurationModel),
|
|
9
|
+
) || []
|
|
10
|
+
).flat(Infinity)
|
|
11
|
+
}
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import stateModelFactory, { HierarchicalTrackSelectorModel } from './model'
|
|
2
|
+
import configSchema from './configSchema'
|
|
2
3
|
|
|
3
|
-
export {
|
|
4
|
-
export
|
|
5
|
-
'HierarchicalTrackSelectorWidget',
|
|
6
|
-
{},
|
|
7
|
-
)
|
|
4
|
+
export { stateModelFactory, configSchema }
|
|
5
|
+
export type { HierarchicalTrackSelectorModel }
|
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
import { types, getParent, Instance } from 'mobx-state-tree'
|
|
1
|
+
import { types, getParent, getEnv, Instance } from 'mobx-state-tree'
|
|
2
2
|
import {
|
|
3
|
-
AnyConfigurationModel,
|
|
4
3
|
getConf,
|
|
5
4
|
readConfObject,
|
|
5
|
+
AnyConfigurationModel,
|
|
6
6
|
} from '@jbrowse/core/configuration'
|
|
7
7
|
import { getSession } from '@jbrowse/core/util'
|
|
8
8
|
import { ElementId } from '@jbrowse/core/util/types/mst'
|
|
9
9
|
import PluginManager from '@jbrowse/core/PluginManager'
|
|
10
|
-
import { AbstractView } from 'react'
|
|
11
10
|
|
|
12
11
|
function hasAnyOverlap<T>(a1: T[] = [], a2: T[] = []) {
|
|
13
12
|
return !!a1.find(value => a2.includes(value))
|
|
@@ -18,11 +17,11 @@ function passesFilter(filter: string, config: AnyConfigurationModel) {
|
|
|
18
17
|
const filterLower = filter.toLowerCase()
|
|
19
18
|
return (
|
|
20
19
|
getTrackName(config).toLowerCase().includes(filterLower) ||
|
|
21
|
-
categories?.filter(c => c.toLowerCase().includes(filterLower)).length
|
|
20
|
+
!!categories?.filter(c => c.toLowerCase().includes(filterLower)).length
|
|
22
21
|
)
|
|
23
22
|
}
|
|
24
23
|
|
|
25
|
-
function getTrackName(config: AnyConfigurationModel) {
|
|
24
|
+
function getTrackName(config: AnyConfigurationModel): string {
|
|
26
25
|
if (!config.trackId) {
|
|
27
26
|
throw new Error('not a track')
|
|
28
27
|
}
|
|
@@ -41,6 +40,32 @@ export type TreeNode = {
|
|
|
41
40
|
children: TreeNode[]
|
|
42
41
|
}
|
|
43
42
|
|
|
43
|
+
function filterTracks(
|
|
44
|
+
tracks: AnyConfigurationModel[],
|
|
45
|
+
self: { view: { type: string } },
|
|
46
|
+
assemblyName: string,
|
|
47
|
+
) {
|
|
48
|
+
const { assemblyManager } = getSession(self)
|
|
49
|
+
const { pluginManager } = getEnv(self)
|
|
50
|
+
const assembly = assemblyManager.get(assemblyName)
|
|
51
|
+
|
|
52
|
+
if (!assembly) {
|
|
53
|
+
return []
|
|
54
|
+
}
|
|
55
|
+
return tracks
|
|
56
|
+
.filter(c => {
|
|
57
|
+
const trackConfAssemblies = readConfObject(c, 'assemblyNames')
|
|
58
|
+
const { allAliases } = assembly
|
|
59
|
+
return hasAnyOverlap(allAliases, trackConfAssemblies)
|
|
60
|
+
})
|
|
61
|
+
.filter(c => {
|
|
62
|
+
const { displayTypes } = pluginManager.getViewType(self.view.type)
|
|
63
|
+
const compatDisplays = displayTypes.map((d: { name: string }) => d.name)
|
|
64
|
+
const trackDisplays = c.displays.map((d: { type: string }) => d.type)
|
|
65
|
+
return hasAnyOverlap(compatDisplays, trackDisplays)
|
|
66
|
+
})
|
|
67
|
+
}
|
|
68
|
+
|
|
44
69
|
export function generateHierarchy(
|
|
45
70
|
model: HierarchicalTrackSelectorModel,
|
|
46
71
|
trackConfigurations: AnyConfigurationModel[],
|
|
@@ -112,8 +137,20 @@ export default function stateTreeFactory(pluginManager: PluginManager) {
|
|
|
112
137
|
pluginManager.pluggableMstType('view', 'stateModel'),
|
|
113
138
|
),
|
|
114
139
|
})
|
|
140
|
+
.volatile(() => ({
|
|
141
|
+
selection: [] as AnyConfigurationModel[],
|
|
142
|
+
}))
|
|
115
143
|
.actions(self => ({
|
|
116
|
-
|
|
144
|
+
addToSelection(elt: AnyConfigurationModel[]) {
|
|
145
|
+
self.selection = [...self.selection, ...elt]
|
|
146
|
+
},
|
|
147
|
+
removeFromSelection(elt: AnyConfigurationModel[]) {
|
|
148
|
+
self.selection = self.selection.filter(f => !elt.includes(f))
|
|
149
|
+
},
|
|
150
|
+
clearSelection() {
|
|
151
|
+
self.selection = []
|
|
152
|
+
},
|
|
153
|
+
setView(view: unknown) {
|
|
117
154
|
self.view = view
|
|
118
155
|
},
|
|
119
156
|
toggleCategory(pathName: string) {
|
|
@@ -156,20 +193,7 @@ export default function stateTreeFactory(pluginManager: PluginManager) {
|
|
|
156
193
|
// filter out tracks that don't match the current assembly (check all
|
|
157
194
|
// assembly aliases) and display types
|
|
158
195
|
return (refseq ? [refseq] : []).concat([
|
|
159
|
-
...tracks
|
|
160
|
-
.filter(c => {
|
|
161
|
-
const trackConfAssemblies = readConfObject(c, 'assemblyNames')
|
|
162
|
-
const { allAliases } = assembly
|
|
163
|
-
return hasAnyOverlap(allAliases, trackConfAssemblies)
|
|
164
|
-
})
|
|
165
|
-
.filter(c => {
|
|
166
|
-
const { displayTypes } = pluginManager.getViewType(self.view.type)
|
|
167
|
-
const compatibleDisplays = displayTypes.map(d => d.name)
|
|
168
|
-
const trackDisplays = c.displays.map(
|
|
169
|
-
(d: { type: string }) => d.type,
|
|
170
|
-
)
|
|
171
|
-
return hasAnyOverlap(compatibleDisplays, trackDisplays)
|
|
172
|
-
}),
|
|
196
|
+
...filterTracks(tracks, self, assemblyName),
|
|
173
197
|
])
|
|
174
198
|
},
|
|
175
199
|
|
|
@@ -184,29 +208,9 @@ export default function stateTreeFactory(pluginManager: PluginManager) {
|
|
|
184
208
|
if (!self.view) {
|
|
185
209
|
return []
|
|
186
210
|
}
|
|
187
|
-
const trackConfigurations = connection.tracks
|
|
188
|
-
const { assemblyManager } = getSession(self)
|
|
189
|
-
const assembly = assemblyManager.get(assemblyName)
|
|
190
|
-
|
|
191
|
-
if (!(assembly && assembly.initialized)) {
|
|
192
|
-
return []
|
|
193
|
-
}
|
|
194
211
|
|
|
195
212
|
// filter out tracks that don't match the current display types
|
|
196
|
-
return
|
|
197
|
-
.filter(c => {
|
|
198
|
-
const trackConfAssemblies = readConfObject(c, 'assemblyNames')
|
|
199
|
-
const { allAliases } = assembly
|
|
200
|
-
return hasAnyOverlap(allAliases, trackConfAssemblies)
|
|
201
|
-
})
|
|
202
|
-
.filter(c => {
|
|
203
|
-
const { displayTypes } = pluginManager.getViewType(self.view.type)
|
|
204
|
-
const compatibleDisplays = displayTypes.map(d => d.name)
|
|
205
|
-
const trackDisplays = c.displays.map(
|
|
206
|
-
(d: { type: string }) => d.type,
|
|
207
|
-
)
|
|
208
|
-
return hasAnyOverlap(compatibleDisplays, trackDisplays)
|
|
209
|
-
})
|
|
213
|
+
return filterTracks(connection.tracks, self, assemblyName)
|
|
210
214
|
},
|
|
211
215
|
}))
|
|
212
216
|
.views(self => ({
|
package/src/index.ts
CHANGED
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
stateModelFactory as AddTrackStateModelFactory,
|
|
12
12
|
configSchema as AddTrackConfigSchema,
|
|
13
13
|
} from './AddTrackWidget'
|
|
14
|
+
import { AddTrackModel } from './AddTrackWidget/model'
|
|
14
15
|
import {
|
|
15
16
|
stateModel as AddConnectionStateModel,
|
|
16
17
|
configSchema as AddConnectionConfigSchema,
|
|
@@ -18,6 +19,7 @@ import {
|
|
|
18
19
|
import {
|
|
19
20
|
stateModelFactory as HierarchicalTrackSelectorStateModelFactory,
|
|
20
21
|
configSchema as HierarchicalTrackSelectorConfigSchema,
|
|
22
|
+
HierarchicalTrackSelectorModel,
|
|
21
23
|
} from './HierarchicalTrackSelectorWidget'
|
|
22
24
|
import {
|
|
23
25
|
stateModelFactory as PluginStoreStateModelFactory,
|
|
@@ -101,7 +103,8 @@ export default class extends Plugin {
|
|
|
101
103
|
})
|
|
102
104
|
}
|
|
103
105
|
|
|
104
|
-
configure(
|
|
106
|
+
configure(_pluginManager: PluginManager) {}
|
|
105
107
|
}
|
|
106
108
|
|
|
107
109
|
export { AssemblyManager, SetDefaultSession }
|
|
110
|
+
export type { HierarchicalTrackSelectorModel, AddTrackModel }
|