@jbrowse/plugin-data-management 2.0.0 → 2.1.2

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.
Files changed (140) hide show
  1. package/dist/AddConnectionWidget/components/AddConnectionWidget.js +23 -40
  2. package/dist/AddConnectionWidget/components/AddConnectionWidget.js.map +1 -1
  3. package/dist/AddConnectionWidget/components/ConfigureConnection.js +6 -6
  4. package/dist/AddConnectionWidget/components/ConfigureConnection.js.map +1 -1
  5. package/dist/AddConnectionWidget/components/ConnectionTypeSelect.js +7 -9
  6. package/dist/AddConnectionWidget/components/ConnectionTypeSelect.js.map +1 -1
  7. package/dist/AddConnectionWidget/index.js +1 -1
  8. package/dist/AddConnectionWidget/index.js.map +1 -1
  9. package/dist/AddConnectionWidget/model.js +2 -2
  10. package/dist/AddConnectionWidget/model.js.map +1 -1
  11. package/dist/AddTrackWidget/components/AddTrackWidget.d.ts +2 -2
  12. package/dist/AddTrackWidget/components/AddTrackWidget.js +24 -220
  13. package/dist/AddTrackWidget/components/AddTrackWidget.js.map +1 -1
  14. package/dist/AddTrackWidget/components/ConfirmTrack.js +72 -99
  15. package/dist/AddTrackWidget/components/ConfirmTrack.js.map +1 -1
  16. package/dist/AddTrackWidget/components/DefaultAddTrackWorkflow.d.ts +7 -0
  17. package/dist/AddTrackWidget/components/DefaultAddTrackWorkflow.js +162 -0
  18. package/dist/AddTrackWidget/components/DefaultAddTrackWorkflow.js.map +1 -0
  19. package/dist/AddTrackWidget/components/TrackSourceSelect.js +11 -12
  20. package/dist/AddTrackWidget/components/TrackSourceSelect.js.map +1 -1
  21. package/dist/AddTrackWidget/index.js +1 -1
  22. package/dist/AddTrackWidget/index.js.map +1 -1
  23. package/dist/AddTrackWidget/model.js +34 -30
  24. package/dist/AddTrackWidget/model.js.map +1 -1
  25. package/dist/AssemblyManager/AssemblyAddForm.js +42 -61
  26. package/dist/AssemblyManager/AssemblyAddForm.js.map +1 -1
  27. package/dist/AssemblyManager/AssemblyEditor.js +4 -5
  28. package/dist/AssemblyManager/AssemblyEditor.js.map +1 -1
  29. package/dist/AssemblyManager/AssemblyManager.js +24 -41
  30. package/dist/AssemblyManager/AssemblyManager.js.map +1 -1
  31. package/dist/AssemblyManager/AssemblyTable.js +17 -18
  32. package/dist/AssemblyManager/AssemblyTable.js.map +1 -1
  33. package/dist/HierarchicalTrackSelectorWidget/components/CloseConnectionDialog.js +9 -29
  34. package/dist/HierarchicalTrackSelectorWidget/components/CloseConnectionDialog.js.map +1 -1
  35. package/dist/HierarchicalTrackSelectorWidget/components/DeleteConnectionDialog.js +7 -8
  36. package/dist/HierarchicalTrackSelectorWidget/components/DeleteConnectionDialog.js.map +1 -1
  37. package/dist/HierarchicalTrackSelectorWidget/components/Header.d.ts +10 -0
  38. package/dist/HierarchicalTrackSelectorWidget/components/Header.js +177 -0
  39. package/dist/HierarchicalTrackSelectorWidget/components/Header.js.map +1 -0
  40. package/dist/HierarchicalTrackSelectorWidget/components/HierarchicalTrackSelector.js +79 -365
  41. package/dist/HierarchicalTrackSelectorWidget/components/HierarchicalTrackSelector.js.map +1 -1
  42. package/dist/HierarchicalTrackSelectorWidget/components/ManageConnectionsDialog.js +17 -18
  43. package/dist/HierarchicalTrackSelectorWidget/components/ManageConnectionsDialog.js.map +1 -1
  44. package/dist/HierarchicalTrackSelectorWidget/components/Node.d.ts +29 -0
  45. package/dist/HierarchicalTrackSelectorWidget/components/Node.js +173 -0
  46. package/dist/HierarchicalTrackSelectorWidget/components/Node.js.map +1 -0
  47. package/dist/HierarchicalTrackSelectorWidget/components/ToggleConnectionsDialog.js +19 -20
  48. package/dist/HierarchicalTrackSelectorWidget/components/ToggleConnectionsDialog.js.map +1 -1
  49. package/dist/HierarchicalTrackSelectorWidget/components/util.d.ts +3 -0
  50. package/dist/HierarchicalTrackSelectorWidget/components/util.js +9 -0
  51. package/dist/HierarchicalTrackSelectorWidget/components/util.js.map +1 -0
  52. package/dist/HierarchicalTrackSelectorWidget/configSchema.d.ts +2 -0
  53. package/dist/HierarchicalTrackSelectorWidget/configSchema.js +6 -0
  54. package/dist/HierarchicalTrackSelectorWidget/configSchema.js.map +1 -0
  55. package/dist/HierarchicalTrackSelectorWidget/index.d.ts +4 -2
  56. package/dist/HierarchicalTrackSelectorWidget/index.js +4 -4
  57. package/dist/HierarchicalTrackSelectorWidget/index.js.map +1 -1
  58. package/dist/HierarchicalTrackSelectorWidget/model.d.ts +10 -2
  59. package/dist/HierarchicalTrackSelectorWidget/model.js +102 -153
  60. package/dist/HierarchicalTrackSelectorWidget/model.js.map +1 -1
  61. package/dist/PluginStoreWidget/components/CustomPluginForm.js +25 -43
  62. package/dist/PluginStoreWidget/components/CustomPluginForm.js.map +1 -1
  63. package/dist/PluginStoreWidget/components/InstalledPlugin.js +29 -47
  64. package/dist/PluginStoreWidget/components/InstalledPlugin.js.map +1 -1
  65. package/dist/PluginStoreWidget/components/InstalledPluginsList.js +12 -15
  66. package/dist/PluginStoreWidget/components/InstalledPluginsList.js.map +1 -1
  67. package/dist/PluginStoreWidget/components/PluginCard.js +23 -40
  68. package/dist/PluginStoreWidget/components/PluginCard.js.map +1 -1
  69. package/dist/PluginStoreWidget/components/PluginStoreWidget.js +49 -117
  70. package/dist/PluginStoreWidget/components/PluginStoreWidget.js.map +1 -1
  71. package/dist/PluginStoreWidget/index.js +1 -1
  72. package/dist/PluginStoreWidget/index.js.map +1 -1
  73. package/dist/PluginStoreWidget/model.js +6 -6
  74. package/dist/PluginStoreWidget/model.js.map +1 -1
  75. package/dist/SetDefaultSession/SetDefaultSession.js +9 -10
  76. package/dist/SetDefaultSession/SetDefaultSession.js.map +1 -1
  77. package/dist/index.d.ts +4 -1
  78. package/dist/index.js +38 -60
  79. package/dist/index.js.map +1 -1
  80. package/dist/ucsc-trackhub/configSchema.js +2 -2
  81. package/dist/ucsc-trackhub/configSchema.js.map +1 -1
  82. package/dist/ucsc-trackhub/model.js +33 -97
  83. package/dist/ucsc-trackhub/model.js.map +1 -1
  84. package/dist/ucsc-trackhub/ucscAssemblies.js +197 -1
  85. package/dist/ucsc-trackhub/ucscAssemblies.js.map +1 -1
  86. package/dist/ucsc-trackhub/ucscTrackHub.js +43 -132
  87. package/dist/ucsc-trackhub/ucscTrackHub.js.map +1 -1
  88. package/esm/AddTrackWidget/components/AddTrackWidget.d.ts +2 -2
  89. package/esm/AddTrackWidget/components/AddTrackWidget.js +22 -135
  90. package/esm/AddTrackWidget/components/AddTrackWidget.js.map +1 -1
  91. package/esm/AddTrackWidget/components/ConfirmTrack.js +5 -6
  92. package/esm/AddTrackWidget/components/ConfirmTrack.js.map +1 -1
  93. package/esm/AddTrackWidget/components/DefaultAddTrackWorkflow.d.ts +7 -0
  94. package/esm/AddTrackWidget/components/DefaultAddTrackWorkflow.js +134 -0
  95. package/esm/AddTrackWidget/components/DefaultAddTrackWorkflow.js.map +1 -0
  96. package/esm/HierarchicalTrackSelectorWidget/components/Header.d.ts +10 -0
  97. package/esm/HierarchicalTrackSelectorWidget/components/Header.js +149 -0
  98. package/esm/HierarchicalTrackSelectorWidget/components/Header.js.map +1 -0
  99. package/esm/HierarchicalTrackSelectorWidget/components/HierarchicalTrackSelector.js +24 -223
  100. package/esm/HierarchicalTrackSelectorWidget/components/HierarchicalTrackSelector.js.map +1 -1
  101. package/esm/HierarchicalTrackSelectorWidget/components/Node.d.ts +29 -0
  102. package/esm/HierarchicalTrackSelectorWidget/components/Node.js +144 -0
  103. package/esm/HierarchicalTrackSelectorWidget/components/Node.js.map +1 -0
  104. package/esm/HierarchicalTrackSelectorWidget/components/util.d.ts +3 -0
  105. package/esm/HierarchicalTrackSelectorWidget/components/util.js +5 -0
  106. package/esm/HierarchicalTrackSelectorWidget/components/util.js.map +1 -0
  107. package/esm/HierarchicalTrackSelectorWidget/configSchema.d.ts +2 -0
  108. package/esm/HierarchicalTrackSelectorWidget/configSchema.js +4 -0
  109. package/esm/HierarchicalTrackSelectorWidget/configSchema.js.map +1 -0
  110. package/esm/HierarchicalTrackSelectorWidget/index.d.ts +4 -2
  111. package/esm/HierarchicalTrackSelectorWidget/index.js +3 -3
  112. package/esm/HierarchicalTrackSelectorWidget/index.js.map +1 -1
  113. package/esm/HierarchicalTrackSelectorWidget/model.d.ts +10 -2
  114. package/esm/HierarchicalTrackSelectorWidget/model.js +36 -32
  115. package/esm/HierarchicalTrackSelectorWidget/model.js.map +1 -1
  116. package/esm/PluginStoreWidget/components/PluginStoreWidget.js +1 -2
  117. package/esm/PluginStoreWidget/components/PluginStoreWidget.js.map +1 -1
  118. package/esm/index.d.ts +4 -1
  119. package/esm/index.js +1 -1
  120. package/esm/index.js.map +1 -1
  121. package/package.json +4 -5
  122. package/src/AddConnectionWidget/components/__snapshots__/AddConnectionWidget.test.js.snap +7 -7
  123. package/src/AddTrackWidget/components/{AddTrackWidget.test.js → AddTrackWidget.test.tsx} +17 -32
  124. package/src/AddTrackWidget/components/AddTrackWidget.tsx +36 -200
  125. package/src/AddTrackWidget/components/ConfirmTrack.tsx +10 -10
  126. package/src/AddTrackWidget/components/DefaultAddTrackWorkflow.tsx +205 -0
  127. package/src/HierarchicalTrackSelectorWidget/components/Header.tsx +287 -0
  128. package/src/HierarchicalTrackSelectorWidget/components/HierarchicalTrackSelector.test.js +5 -4
  129. package/src/HierarchicalTrackSelectorWidget/components/HierarchicalTrackSelector.tsx +19 -438
  130. package/src/HierarchicalTrackSelectorWidget/components/Node.tsx +282 -0
  131. package/src/HierarchicalTrackSelectorWidget/components/__snapshots__/HierarchicalTrackSelector.test.js.snap +24 -48
  132. package/src/HierarchicalTrackSelectorWidget/components/util.ts +11 -0
  133. package/src/HierarchicalTrackSelectorWidget/configSchema.ts +3 -0
  134. package/src/HierarchicalTrackSelectorWidget/index.ts +4 -6
  135. package/src/HierarchicalTrackSelectorWidget/model.ts +45 -41
  136. package/src/PluginStoreWidget/components/PluginStoreWidget.test.js +16 -4
  137. package/src/PluginStoreWidget/components/PluginStoreWidget.tsx +1 -2
  138. package/src/PluginStoreWidget/components/__snapshots__/PluginStoreWidget.test.js.snap +111 -123
  139. package/src/index.ts +4 -1
  140. package/src/AddTrackWidget/components/__snapshots__/AddTrackWidget.test.js.snap +0 -331
@@ -0,0 +1,282 @@
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
+ background: theme.palette.tertiary.main,
64
+ color: theme.palette.tertiary.contrastText,
65
+ width: '100%',
66
+ display: 'flex',
67
+ paddingLeft: 5,
68
+ },
69
+
70
+ // margin:auto 0 to center text vertically
71
+ accordionText: {
72
+ margin: 'auto 0',
73
+ },
74
+ }))
75
+
76
+ export interface InfoArgs {
77
+ target: HTMLElement
78
+ id: string
79
+ conf: AnyConfigurationModel
80
+ }
81
+
82
+ function treeToMap(tree: TreeNode, map = new Map<string, TreeNode>()) {
83
+ if (tree.id && tree.children.length) {
84
+ map.set(tree.id, tree)
85
+ }
86
+ for (let i = 0; i < tree.children.length; i++) {
87
+ const node = tree.children[i]
88
+ treeToMap(node, map)
89
+ }
90
+ return map
91
+ }
92
+
93
+ function isUnsupported(name = '') {
94
+ return name.endsWith('(Unsupported)') || name.endsWith('(Unknown)')
95
+ }
96
+
97
+ // An individual node in the track selector. Note: manually sets cursor:
98
+ // pointer improves usability for what can be clicked
99
+ export default function Node(props: {
100
+ data: {
101
+ nestingLevel: number
102
+ checked: boolean
103
+ conf: AnyConfigurationModel
104
+ drawerPosition: unknown
105
+ id: string
106
+ isLeaf: boolean
107
+ name: string
108
+ onChange: Function
109
+ toggleCollapse: (arg: string) => void
110
+ tree: TreeNode
111
+ selected: boolean
112
+ model: HierarchicalTrackSelectorModel
113
+ }
114
+ isOpen: boolean
115
+ style?: { height: number }
116
+ setOpen: (arg: boolean) => void
117
+ }) {
118
+ const { data, isOpen, style, setOpen } = props
119
+ const {
120
+ checked,
121
+ conf,
122
+ drawerPosition,
123
+ id,
124
+ isLeaf,
125
+ model,
126
+ name,
127
+ nestingLevel,
128
+ onChange,
129
+ selected,
130
+ toggleCollapse,
131
+ tree,
132
+ } = data
133
+
134
+ const { classes } = useStyles()
135
+ const width = 10
136
+ const [menuEl, setMenuEl] = useState<HTMLElement | null>(null)
137
+ const [info, setInfo] = useState<InfoArgs>()
138
+ const marginLeft = nestingLevel * width + (isLeaf ? width : 0)
139
+ const description = (conf && readConfObject(conf, ['description'])) || ''
140
+
141
+ return (
142
+ <div style={style} className={!isLeaf ? classes.accordionBase : undefined}>
143
+ {new Array(nestingLevel).fill(0).map((_, idx) => (
144
+ <div
145
+ key={`mark-${idx}`}
146
+ style={{ left: idx * width + 4, height: style?.height }}
147
+ className={classes.nestingLevelMarker}
148
+ />
149
+ ))}
150
+ <div
151
+ className={!isLeaf ? classes.accordionCard : undefined}
152
+ onClick={() => {
153
+ if (!menuEl) {
154
+ toggleCollapse(id)
155
+ setOpen(!isOpen)
156
+ }
157
+ }}
158
+ style={{
159
+ marginLeft,
160
+ whiteSpace: 'nowrap',
161
+ width: '100%',
162
+ }}
163
+ >
164
+ <div className={!isLeaf ? classes.accordionColor : undefined}>
165
+ {!isLeaf ? (
166
+ <div className={classes.accordionText}>
167
+ <Typography>
168
+ {isOpen ? <ArrowDropDownIcon /> : <ArrowRightIcon />}
169
+ {name}
170
+ <IconButton
171
+ onClick={event => {
172
+ setMenuEl(event.currentTarget)
173
+ event.stopPropagation()
174
+ }}
175
+ className={classes.contrastColor}
176
+ >
177
+ <MoreHorizIcon />
178
+ </IconButton>
179
+ </Typography>
180
+ </div>
181
+ ) : (
182
+ <>
183
+ <Tooltip
184
+ title={description + (selected ? ' (in selection)' : '')}
185
+ placement={drawerPosition === 'left' ? 'right' : 'left'}
186
+ >
187
+ <FormControlLabel
188
+ className={classes.checkboxLabel}
189
+ control={
190
+ <Checkbox
191
+ className={classes.compactCheckbox}
192
+ checked={checked}
193
+ onChange={() => onChange(id)}
194
+ disabled={isUnsupported(name)}
195
+ inputProps={{
196
+ // @ts-ignore
197
+ 'data-testid': `htsTrackEntry-${id}`,
198
+ }}
199
+ />
200
+ }
201
+ label={
202
+ <div
203
+ style={{
204
+ background: selected ? '#cccc' : undefined,
205
+ padding: 1,
206
+ }}
207
+ >
208
+ {name}
209
+ </div>
210
+ }
211
+ />
212
+ </Tooltip>
213
+ <IconButton
214
+ onClick={e => setInfo({ target: e.currentTarget, id, conf })}
215
+ style={{ padding: 0 }}
216
+ color="secondary"
217
+ data-testid={`htsTrackEntryMenu-${id}`}
218
+ >
219
+ <MoreHorizIcon />
220
+ </IconButton>
221
+ </>
222
+ )}
223
+ {menuEl ? (
224
+ <JBrowseMenu
225
+ anchorEl={menuEl}
226
+ menuItems={[
227
+ {
228
+ label: 'Add to selection',
229
+ onClick: () =>
230
+ model.addToSelection(
231
+ getAllChildren(treeToMap(tree).get(id)),
232
+ ),
233
+ },
234
+ {
235
+ label: 'Remove from selection',
236
+ onClick: () =>
237
+ model.removeFromSelection(
238
+ getAllChildren(treeToMap(tree).get(id)),
239
+ ),
240
+ },
241
+ ]}
242
+ onMenuItemClick={(_event, callback) => {
243
+ callback()
244
+ setMenuEl(null)
245
+ }}
246
+ open={Boolean(menuEl)}
247
+ onClose={() => setMenuEl(null)}
248
+ />
249
+ ) : null}
250
+
251
+ {info ? (
252
+ <JBrowseMenu
253
+ anchorEl={info?.target}
254
+ menuItems={[
255
+ ...(getSession(model).getTrackActionMenuItems?.(info.conf) ||
256
+ []),
257
+ {
258
+ label: 'Add to selection',
259
+ onClick: () => model.addToSelection([info.conf]),
260
+ },
261
+ ...(selected
262
+ ? [
263
+ {
264
+ label: 'Remove from selection',
265
+ onClick: () => model.removeFromSelection([info.conf]),
266
+ },
267
+ ]
268
+ : []),
269
+ ]}
270
+ onMenuItemClick={(_event, callback) => {
271
+ callback()
272
+ setInfo(undefined)
273
+ }}
274
+ open={Boolean(info)}
275
+ onClose={() => setInfo(undefined)}
276
+ />
277
+ ) : null}
278
+ </div>
279
+ </div>
280
+ </div>
281
+ )
282
+ }
@@ -2,13 +2,13 @@
2
2
 
3
3
  exports[`HierarchicalTrackSelector widget renders nothing with no assembly 1`] = `
4
4
  <button
5
- class="MuiButtonBase-root MuiFab-root MuiFab-circular MuiFab-sizeLarge MuiFab-secondary tss-jdumxy-fab css-kznubb-MuiButtonBase-root-MuiFab-root"
5
+ class="MuiButtonBase-root MuiFab-root MuiFab-circular MuiFab-sizeSmall MuiFab-secondary tss-805w6w-fab css-10w0o2e-MuiButtonBase-root-MuiFab-root"
6
6
  tabindex="0"
7
7
  type="button"
8
8
  >
9
9
  <svg
10
10
  aria-hidden="true"
11
- class="MuiSvgIcon-root MuiSvgIcon-fontSizeMedium css-i4bv87-MuiSvgIcon-root"
11
+ class="MuiSvgIcon-root MuiSvgIcon-fontSizeMedium css-havevq-MuiSvgIcon-root"
12
12
  data-testid="AddIcon"
13
13
  focusable="false"
14
14
  viewBox="0 0 24 24"
@@ -31,13 +31,13 @@ exports[`HierarchicalTrackSelector widget renders with a couple of categorized t
31
31
  style="display: flex;"
32
32
  >
33
33
  <button
34
- class="MuiButtonBase-root MuiIconButton-root MuiIconButton-sizeMedium tss-1imaff4-menuIcon css-78trlr-MuiButtonBase-root-MuiIconButton-root"
34
+ class="MuiButtonBase-root MuiIconButton-root MuiIconButton-sizeSmall tss-1qeitpp-menuIcon css-zubjuh-MuiButtonBase-root-MuiIconButton-root"
35
35
  tabindex="0"
36
36
  type="button"
37
37
  >
38
38
  <svg
39
39
  aria-hidden="true"
40
- class="MuiSvgIcon-root MuiSvgIcon-fontSizeMedium css-i4bv87-MuiSvgIcon-root"
40
+ class="MuiSvgIcon-root MuiSvgIcon-fontSizeMedium css-havevq-MuiSvgIcon-root"
41
41
  data-testid="MenuIcon"
42
42
  focusable="false"
43
43
  viewBox="0 0 24 24"
@@ -51,13 +51,13 @@ exports[`HierarchicalTrackSelector widget renders with a couple of categorized t
51
51
  />
52
52
  </button>
53
53
  <button
54
- class="MuiButtonBase-root MuiIconButton-root MuiIconButton-sizeMedium tss-1imaff4-menuIcon css-78trlr-MuiButtonBase-root-MuiIconButton-root"
54
+ class="MuiButtonBase-root MuiIconButton-root MuiIconButton-sizeSmall tss-1qeitpp-menuIcon css-zubjuh-MuiButtonBase-root-MuiIconButton-root"
55
55
  tabindex="0"
56
56
  type="button"
57
57
  >
58
58
  <svg
59
59
  aria-hidden="true"
60
- class="MuiSvgIcon-root MuiSvgIcon-fontSizeMedium css-i4bv87-MuiSvgIcon-root"
60
+ class="MuiSvgIcon-root MuiSvgIcon-fontSizeMedium css-havevq-MuiSvgIcon-root"
61
61
  focusable="false"
62
62
  viewBox="0 0 24 24"
63
63
  >
@@ -70,10 +70,10 @@ exports[`HierarchicalTrackSelector widget renders with a couple of categorized t
70
70
  />
71
71
  </button>
72
72
  <div
73
- class="MuiFormControl-root MuiFormControl-fullWidth MuiTextField-root tss-11q958z-searchBox css-wb57ya-MuiFormControl-root-MuiTextField-root"
73
+ class="MuiFormControl-root MuiFormControl-marginDense MuiFormControl-fullWidth MuiTextField-root tss-45fwc5-searchBox css-1z10yd4-MuiFormControl-root-MuiTextField-root"
74
74
  >
75
75
  <label
76
- class="MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-outlined MuiFormLabel-root MuiFormLabel-colorPrimary css-14s5rfu-MuiFormLabel-root-MuiInputLabel-root"
76
+ class="MuiFormLabel-root MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-sizeSmall MuiInputLabel-standard MuiFormLabel-colorPrimary css-1s1jvl0-MuiFormLabel-root-MuiInputLabel-root"
77
77
  data-shrink="false"
78
78
  for="mui-5"
79
79
  id="mui-5-label"
@@ -81,26 +81,26 @@ exports[`HierarchicalTrackSelector widget renders with a couple of categorized t
81
81
  Filter tracks
82
82
  </label>
83
83
  <div
84
- class="MuiOutlinedInput-root MuiInputBase-root MuiInputBase-colorPrimary MuiInputBase-fullWidth MuiInputBase-formControl MuiInputBase-adornedEnd css-154xyx0-MuiInputBase-root-MuiOutlinedInput-root"
84
+ class="MuiInputBase-root MuiInput-root MuiInput-underline MuiInputBase-colorPrimary MuiInputBase-fullWidth MuiInputBase-formControl MuiInputBase-sizeSmall MuiInputBase-adornedEnd css-1wz39fi-MuiInputBase-root-MuiInput-root"
85
85
  >
86
86
  <input
87
87
  aria-invalid="false"
88
- class="MuiOutlinedInput-input MuiInputBase-input MuiInputBase-inputAdornedEnd css-nxo287-MuiInputBase-input-MuiOutlinedInput-input"
88
+ class="MuiInputBase-input MuiInput-input MuiInputBase-inputSizeSmall MuiInputBase-inputAdornedEnd css-nz481w-MuiInputBase-input-MuiInput-input"
89
89
  id="mui-5"
90
90
  type="text"
91
91
  value=""
92
92
  />
93
93
  <div
94
- class="MuiInputAdornment-root MuiInputAdornment-positionEnd MuiInputAdornment-outlined MuiInputAdornment-sizeMedium css-1laqsz7-MuiInputAdornment-root"
94
+ class="MuiInputAdornment-root MuiInputAdornment-positionEnd MuiInputAdornment-standard MuiInputAdornment-sizeSmall css-1laqsz7-MuiInputAdornment-root"
95
95
  >
96
96
  <button
97
- class="MuiButtonBase-root MuiIconButton-root MuiIconButton-colorSecondary MuiIconButton-sizeMedium css-1gws2xf-MuiButtonBase-root-MuiIconButton-root"
97
+ class="MuiButtonBase-root MuiIconButton-root MuiIconButton-colorSecondary MuiIconButton-sizeSmall css-16a6k96-MuiButtonBase-root-MuiIconButton-root"
98
98
  tabindex="0"
99
99
  type="button"
100
100
  >
101
101
  <svg
102
102
  aria-hidden="true"
103
- class="MuiSvgIcon-root MuiSvgIcon-fontSizeMedium css-i4bv87-MuiSvgIcon-root"
103
+ class="MuiSvgIcon-root MuiSvgIcon-fontSizeMedium css-havevq-MuiSvgIcon-root"
104
104
  data-testid="ClearIcon"
105
105
  focusable="false"
106
106
  viewBox="0 0 24 24"
@@ -114,18 +114,6 @@ exports[`HierarchicalTrackSelector widget renders with a couple of categorized t
114
114
  />
115
115
  </button>
116
116
  </div>
117
- <fieldset
118
- aria-hidden="true"
119
- class="MuiOutlinedInput-notchedOutline css-1d3z3hw-MuiOutlinedInput-notchedOutline"
120
- >
121
- <legend
122
- class="css-1ftyaf0"
123
- >
124
- <span>
125
- Filter tracks
126
- </span>
127
- </legend>
128
- </fieldset>
129
117
  </div>
130
118
  </div>
131
119
  </div>
@@ -140,13 +128,13 @@ exports[`HierarchicalTrackSelector widget renders with a couple of uncategorized
140
128
  style="display: flex;"
141
129
  >
142
130
  <button
143
- class="MuiButtonBase-root MuiIconButton-root MuiIconButton-sizeMedium tss-1imaff4-menuIcon css-78trlr-MuiButtonBase-root-MuiIconButton-root"
131
+ class="MuiButtonBase-root MuiIconButton-root MuiIconButton-sizeSmall tss-1qeitpp-menuIcon css-zubjuh-MuiButtonBase-root-MuiIconButton-root"
144
132
  tabindex="0"
145
133
  type="button"
146
134
  >
147
135
  <svg
148
136
  aria-hidden="true"
149
- class="MuiSvgIcon-root MuiSvgIcon-fontSizeMedium css-i4bv87-MuiSvgIcon-root"
137
+ class="MuiSvgIcon-root MuiSvgIcon-fontSizeMedium css-havevq-MuiSvgIcon-root"
150
138
  data-testid="MenuIcon"
151
139
  focusable="false"
152
140
  viewBox="0 0 24 24"
@@ -160,13 +148,13 @@ exports[`HierarchicalTrackSelector widget renders with a couple of uncategorized
160
148
  />
161
149
  </button>
162
150
  <button
163
- class="MuiButtonBase-root MuiIconButton-root MuiIconButton-sizeMedium tss-1imaff4-menuIcon css-78trlr-MuiButtonBase-root-MuiIconButton-root"
151
+ class="MuiButtonBase-root MuiIconButton-root MuiIconButton-sizeSmall tss-1qeitpp-menuIcon css-zubjuh-MuiButtonBase-root-MuiIconButton-root"
164
152
  tabindex="0"
165
153
  type="button"
166
154
  >
167
155
  <svg
168
156
  aria-hidden="true"
169
- class="MuiSvgIcon-root MuiSvgIcon-fontSizeMedium css-i4bv87-MuiSvgIcon-root"
157
+ class="MuiSvgIcon-root MuiSvgIcon-fontSizeMedium css-havevq-MuiSvgIcon-root"
170
158
  focusable="false"
171
159
  viewBox="0 0 24 24"
172
160
  >
@@ -179,10 +167,10 @@ exports[`HierarchicalTrackSelector widget renders with a couple of uncategorized
179
167
  />
180
168
  </button>
181
169
  <div
182
- class="MuiFormControl-root MuiFormControl-fullWidth MuiTextField-root tss-11q958z-searchBox css-wb57ya-MuiFormControl-root-MuiTextField-root"
170
+ class="MuiFormControl-root MuiFormControl-marginDense MuiFormControl-fullWidth MuiTextField-root tss-45fwc5-searchBox css-1z10yd4-MuiFormControl-root-MuiTextField-root"
183
171
  >
184
172
  <label
185
- class="MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-outlined MuiFormLabel-root MuiFormLabel-colorPrimary css-14s5rfu-MuiFormLabel-root-MuiInputLabel-root"
173
+ class="MuiFormLabel-root MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-sizeSmall MuiInputLabel-standard MuiFormLabel-colorPrimary css-1s1jvl0-MuiFormLabel-root-MuiInputLabel-root"
186
174
  data-shrink="false"
187
175
  for="mui-1"
188
176
  id="mui-1-label"
@@ -190,26 +178,26 @@ exports[`HierarchicalTrackSelector widget renders with a couple of uncategorized
190
178
  Filter tracks
191
179
  </label>
192
180
  <div
193
- class="MuiOutlinedInput-root MuiInputBase-root MuiInputBase-colorPrimary MuiInputBase-fullWidth MuiInputBase-formControl MuiInputBase-adornedEnd css-154xyx0-MuiInputBase-root-MuiOutlinedInput-root"
181
+ class="MuiInputBase-root MuiInput-root MuiInput-underline MuiInputBase-colorPrimary MuiInputBase-fullWidth MuiInputBase-formControl MuiInputBase-sizeSmall MuiInputBase-adornedEnd css-1wz39fi-MuiInputBase-root-MuiInput-root"
194
182
  >
195
183
  <input
196
184
  aria-invalid="false"
197
- class="MuiOutlinedInput-input MuiInputBase-input MuiInputBase-inputAdornedEnd css-nxo287-MuiInputBase-input-MuiOutlinedInput-input"
185
+ class="MuiInputBase-input MuiInput-input MuiInputBase-inputSizeSmall MuiInputBase-inputAdornedEnd css-nz481w-MuiInputBase-input-MuiInput-input"
198
186
  id="mui-1"
199
187
  type="text"
200
188
  value=""
201
189
  />
202
190
  <div
203
- class="MuiInputAdornment-root MuiInputAdornment-positionEnd MuiInputAdornment-outlined MuiInputAdornment-sizeMedium css-1laqsz7-MuiInputAdornment-root"
191
+ class="MuiInputAdornment-root MuiInputAdornment-positionEnd MuiInputAdornment-standard MuiInputAdornment-sizeSmall css-1laqsz7-MuiInputAdornment-root"
204
192
  >
205
193
  <button
206
- class="MuiButtonBase-root MuiIconButton-root MuiIconButton-colorSecondary MuiIconButton-sizeMedium css-1gws2xf-MuiButtonBase-root-MuiIconButton-root"
194
+ class="MuiButtonBase-root MuiIconButton-root MuiIconButton-colorSecondary MuiIconButton-sizeSmall css-16a6k96-MuiButtonBase-root-MuiIconButton-root"
207
195
  tabindex="0"
208
196
  type="button"
209
197
  >
210
198
  <svg
211
199
  aria-hidden="true"
212
- class="MuiSvgIcon-root MuiSvgIcon-fontSizeMedium css-i4bv87-MuiSvgIcon-root"
200
+ class="MuiSvgIcon-root MuiSvgIcon-fontSizeMedium css-havevq-MuiSvgIcon-root"
213
201
  data-testid="ClearIcon"
214
202
  focusable="false"
215
203
  viewBox="0 0 24 24"
@@ -223,18 +211,6 @@ exports[`HierarchicalTrackSelector widget renders with a couple of uncategorized
223
211
  />
224
212
  </button>
225
213
  </div>
226
- <fieldset
227
- aria-hidden="true"
228
- class="MuiOutlinedInput-notchedOutline css-1d3z3hw-MuiOutlinedInput-notchedOutline"
229
- >
230
- <legend
231
- class="css-1ftyaf0"
232
- >
233
- <span>
234
- Filter tracks
235
- </span>
236
- </legend>
237
- </fieldset>
238
214
  </div>
239
215
  </div>
240
216
  </div>
@@ -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
+ }
@@ -0,0 +1,3 @@
1
+ import { ConfigurationSchema } from '@jbrowse/core/configuration'
2
+ const configSchema = ConfigurationSchema('HierarchicalTrackSelectorWidget', {})
3
+ export default configSchema
@@ -1,7 +1,5 @@
1
- import { ConfigurationSchema } from '@jbrowse/core/configuration'
1
+ import stateModelFactory, { HierarchicalTrackSelectorModel } from './model'
2
+ import configSchema from './configSchema'
2
3
 
3
- export { default as stateModelFactory } from './model'
4
- export const configSchema = ConfigurationSchema(
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
- setView(view: AbstractView) {
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 trackConfigurations
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 => ({