@jbrowse/plugin-data-management 2.5.0 → 2.6.1

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 (136) hide show
  1. package/dist/AddConnectionWidget/components/AddConnectionWidget.d.ts +2 -1
  2. package/dist/AddConnectionWidget/components/ConfigureConnection.d.ts +2 -1
  3. package/dist/AddConnectionWidget/components/ConnectionTypeSelect.d.ts +2 -1
  4. package/dist/AddTrackWidget/components/AddTrackWidget.d.ts +2 -1
  5. package/dist/AddTrackWidget/components/ConfirmTrack.d.ts +2 -1
  6. package/dist/AddTrackWidget/components/DefaultAddTrackWorkflow.d.ts +2 -1
  7. package/dist/AddTrackWidget/components/DefaultAddTrackWorkflow.js +1 -1
  8. package/dist/AddTrackWidget/components/DefaultAddTrackWorkflow.js.map +1 -1
  9. package/dist/AddTrackWidget/components/PasteConfigWorkflow.d.ts +2 -1
  10. package/dist/AddTrackWidget/components/PasteConfigWorkflow.js +1 -0
  11. package/dist/AddTrackWidget/components/PasteConfigWorkflow.js.map +1 -1
  12. package/dist/AddTrackWidget/components/TextIndexingConfig.d.ts +2 -1
  13. package/dist/AddTrackWidget/components/TrackAdapterSelector.d.ts +2 -1
  14. package/dist/AddTrackWidget/components/TrackSourceSelect.d.ts +2 -1
  15. package/dist/AddTrackWidget/components/TrackTypeSelector.d.ts +2 -1
  16. package/dist/AssemblyManager/AssemblyAddForm.d.ts +2 -1
  17. package/dist/AssemblyManager/AssemblyEditor.d.ts +2 -1
  18. package/dist/AssemblyManager/AssemblyManager.d.ts +2 -1
  19. package/dist/AssemblyManager/AssemblyTable.d.ts +2 -1
  20. package/dist/HierarchicalTrackSelectorWidget/components/HierarchicalFab.d.ts +2 -1
  21. package/dist/HierarchicalTrackSelectorWidget/components/HierarchicalTrackSelector.d.ts +2 -1
  22. package/dist/HierarchicalTrackSelectorWidget/components/HierarchicalTrackSelector.js +4 -9
  23. package/dist/HierarchicalTrackSelectorWidget/components/HierarchicalTrackSelector.js.map +1 -1
  24. package/dist/HierarchicalTrackSelectorWidget/components/ShoppingCart.d.ts +2 -1
  25. package/dist/HierarchicalTrackSelectorWidget/components/dialogs/CloseConnectionDialog.d.ts +8 -8
  26. package/dist/HierarchicalTrackSelectorWidget/components/dialogs/CloseConnectionDialog.js +6 -10
  27. package/dist/HierarchicalTrackSelectorWidget/components/dialogs/CloseConnectionDialog.js.map +1 -1
  28. package/dist/HierarchicalTrackSelectorWidget/components/dialogs/DeleteConnectionDialog.d.ts +2 -1
  29. package/dist/HierarchicalTrackSelectorWidget/components/dialogs/ManageConnectionsDialog.d.ts +2 -1
  30. package/dist/HierarchicalTrackSelectorWidget/components/dialogs/ToggleConnectionsDialog.d.ts +3 -3
  31. package/dist/HierarchicalTrackSelectorWidget/components/dialogs/ToggleConnectionsDialog.js +27 -22
  32. package/dist/HierarchicalTrackSelectorWidget/components/dialogs/ToggleConnectionsDialog.js.map +1 -1
  33. package/dist/HierarchicalTrackSelectorWidget/components/faceted/FacetFilters.d.ts +2 -1
  34. package/dist/HierarchicalTrackSelectorWidget/components/faceted/FacetedDialog.d.ts +2 -1
  35. package/dist/HierarchicalTrackSelectorWidget/components/faceted/FacetedHeader.d.ts +2 -1
  36. package/dist/HierarchicalTrackSelectorWidget/components/faceted/FacetedSelector.d.ts +2 -1
  37. package/dist/HierarchicalTrackSelectorWidget/components/faceted/FacetedSelector.js +32 -31
  38. package/dist/HierarchicalTrackSelectorWidget/components/faceted/FacetedSelector.js.map +1 -1
  39. package/dist/HierarchicalTrackSelectorWidget/components/tree/HamburgerMenu.d.ts +3 -3
  40. package/dist/HierarchicalTrackSelectorWidget/components/tree/HamburgerMenu.js +36 -41
  41. package/dist/HierarchicalTrackSelectorWidget/components/tree/HamburgerMenu.js.map +1 -1
  42. package/dist/HierarchicalTrackSelectorWidget/components/tree/HierarchicalHeader.d.ts +3 -3
  43. package/dist/HierarchicalTrackSelectorWidget/components/tree/HierarchicalHeader.js +2 -2
  44. package/dist/HierarchicalTrackSelectorWidget/components/tree/HierarchicalHeader.js.map +1 -1
  45. package/dist/HierarchicalTrackSelectorWidget/components/tree/HierarchicalTree.d.ts +2 -1
  46. package/dist/HierarchicalTrackSelectorWidget/components/tree/TrackCategory.d.ts +2 -1
  47. package/dist/HierarchicalTrackSelectorWidget/components/tree/TrackLabel.d.ts +2 -1
  48. package/dist/HierarchicalTrackSelectorWidget/components/tree/TrackListNode.d.ts +2 -1
  49. package/dist/HierarchicalTrackSelectorWidget/model.d.ts +69 -5
  50. package/dist/HierarchicalTrackSelectorWidget/model.js +100 -53
  51. package/dist/HierarchicalTrackSelectorWidget/model.js.map +1 -1
  52. package/dist/PluginStoreWidget/components/CustomPluginForm.d.ts +2 -1
  53. package/dist/PluginStoreWidget/components/InstalledPlugin.d.ts +2 -1
  54. package/dist/PluginStoreWidget/components/InstalledPluginsList.d.ts +2 -1
  55. package/dist/PluginStoreWidget/components/PluginCard.d.ts +2 -1
  56. package/dist/PluginStoreWidget/components/PluginStoreWidget.d.ts +2 -1
  57. package/dist/SetDefaultSession/SetDefaultSession.d.ts +2 -1
  58. package/dist/index.d.ts +4 -4
  59. package/dist/ucsc-trackhub/model.d.ts +12 -0
  60. package/dist/ucsc-trackhub/model.js +45 -12
  61. package/dist/ucsc-trackhub/model.js.map +1 -1
  62. package/esm/AddConnectionWidget/components/AddConnectionWidget.d.ts +2 -1
  63. package/esm/AddConnectionWidget/components/ConfigureConnection.d.ts +2 -1
  64. package/esm/AddConnectionWidget/components/ConnectionTypeSelect.d.ts +2 -1
  65. package/esm/AddTrackWidget/components/AddTrackWidget.d.ts +2 -1
  66. package/esm/AddTrackWidget/components/ConfirmTrack.d.ts +2 -1
  67. package/esm/AddTrackWidget/components/DefaultAddTrackWorkflow.d.ts +2 -1
  68. package/esm/AddTrackWidget/components/DefaultAddTrackWorkflow.js +1 -1
  69. package/esm/AddTrackWidget/components/DefaultAddTrackWorkflow.js.map +1 -1
  70. package/esm/AddTrackWidget/components/PasteConfigWorkflow.d.ts +2 -1
  71. package/esm/AddTrackWidget/components/PasteConfigWorkflow.js +1 -0
  72. package/esm/AddTrackWidget/components/PasteConfigWorkflow.js.map +1 -1
  73. package/esm/AddTrackWidget/components/TextIndexingConfig.d.ts +2 -1
  74. package/esm/AddTrackWidget/components/TrackAdapterSelector.d.ts +2 -1
  75. package/esm/AddTrackWidget/components/TrackSourceSelect.d.ts +2 -1
  76. package/esm/AddTrackWidget/components/TrackTypeSelector.d.ts +2 -1
  77. package/esm/AssemblyManager/AssemblyAddForm.d.ts +2 -1
  78. package/esm/AssemblyManager/AssemblyEditor.d.ts +2 -1
  79. package/esm/AssemblyManager/AssemblyManager.d.ts +2 -1
  80. package/esm/AssemblyManager/AssemblyTable.d.ts +2 -1
  81. package/esm/HierarchicalTrackSelectorWidget/components/HierarchicalFab.d.ts +2 -1
  82. package/esm/HierarchicalTrackSelectorWidget/components/HierarchicalTrackSelector.d.ts +2 -1
  83. package/esm/HierarchicalTrackSelectorWidget/components/HierarchicalTrackSelector.js +4 -9
  84. package/esm/HierarchicalTrackSelectorWidget/components/HierarchicalTrackSelector.js.map +1 -1
  85. package/esm/HierarchicalTrackSelectorWidget/components/ShoppingCart.d.ts +2 -1
  86. package/esm/HierarchicalTrackSelectorWidget/components/dialogs/CloseConnectionDialog.d.ts +8 -8
  87. package/esm/HierarchicalTrackSelectorWidget/components/dialogs/CloseConnectionDialog.js +7 -11
  88. package/esm/HierarchicalTrackSelectorWidget/components/dialogs/CloseConnectionDialog.js.map +1 -1
  89. package/esm/HierarchicalTrackSelectorWidget/components/dialogs/DeleteConnectionDialog.d.ts +2 -1
  90. package/esm/HierarchicalTrackSelectorWidget/components/dialogs/ManageConnectionsDialog.d.ts +2 -1
  91. package/esm/HierarchicalTrackSelectorWidget/components/dialogs/ToggleConnectionsDialog.d.ts +3 -3
  92. package/esm/HierarchicalTrackSelectorWidget/components/dialogs/ToggleConnectionsDialog.js +27 -22
  93. package/esm/HierarchicalTrackSelectorWidget/components/dialogs/ToggleConnectionsDialog.js.map +1 -1
  94. package/esm/HierarchicalTrackSelectorWidget/components/faceted/FacetFilters.d.ts +2 -1
  95. package/esm/HierarchicalTrackSelectorWidget/components/faceted/FacetedDialog.d.ts +2 -1
  96. package/esm/HierarchicalTrackSelectorWidget/components/faceted/FacetedHeader.d.ts +2 -1
  97. package/esm/HierarchicalTrackSelectorWidget/components/faceted/FacetedSelector.d.ts +2 -1
  98. package/esm/HierarchicalTrackSelectorWidget/components/faceted/FacetedSelector.js +32 -31
  99. package/esm/HierarchicalTrackSelectorWidget/components/faceted/FacetedSelector.js.map +1 -1
  100. package/esm/HierarchicalTrackSelectorWidget/components/tree/HamburgerMenu.d.ts +3 -3
  101. package/esm/HierarchicalTrackSelectorWidget/components/tree/HamburgerMenu.js +37 -42
  102. package/esm/HierarchicalTrackSelectorWidget/components/tree/HamburgerMenu.js.map +1 -1
  103. package/esm/HierarchicalTrackSelectorWidget/components/tree/HierarchicalHeader.d.ts +3 -3
  104. package/esm/HierarchicalTrackSelectorWidget/components/tree/HierarchicalHeader.js +2 -2
  105. package/esm/HierarchicalTrackSelectorWidget/components/tree/HierarchicalHeader.js.map +1 -1
  106. package/esm/HierarchicalTrackSelectorWidget/components/tree/HierarchicalTree.d.ts +2 -1
  107. package/esm/HierarchicalTrackSelectorWidget/components/tree/TrackCategory.d.ts +2 -1
  108. package/esm/HierarchicalTrackSelectorWidget/components/tree/TrackLabel.d.ts +2 -1
  109. package/esm/HierarchicalTrackSelectorWidget/components/tree/TrackListNode.d.ts +2 -1
  110. package/esm/HierarchicalTrackSelectorWidget/model.d.ts +69 -5
  111. package/esm/HierarchicalTrackSelectorWidget/model.js +101 -54
  112. package/esm/HierarchicalTrackSelectorWidget/model.js.map +1 -1
  113. package/esm/PluginStoreWidget/components/CustomPluginForm.d.ts +2 -1
  114. package/esm/PluginStoreWidget/components/InstalledPlugin.d.ts +2 -1
  115. package/esm/PluginStoreWidget/components/InstalledPluginsList.d.ts +2 -1
  116. package/esm/PluginStoreWidget/components/PluginCard.d.ts +2 -1
  117. package/esm/PluginStoreWidget/components/PluginStoreWidget.d.ts +2 -1
  118. package/esm/SetDefaultSession/SetDefaultSession.d.ts +2 -1
  119. package/esm/index.d.ts +4 -4
  120. package/esm/ucsc-trackhub/model.d.ts +12 -0
  121. package/esm/ucsc-trackhub/model.js +20 -10
  122. package/esm/ucsc-trackhub/model.js.map +1 -1
  123. package/package.json +2 -2
  124. package/src/AddConnectionWidget/components/AddConnectionWidget.test.tsx +1 -1
  125. package/src/AddTrackWidget/components/DefaultAddTrackWorkflow.tsx +1 -1
  126. package/src/AddTrackWidget/components/PasteConfigWorkflow.tsx +1 -0
  127. package/src/HierarchicalTrackSelectorWidget/components/HierarchicalTrackSelector.tsx +11 -21
  128. package/src/HierarchicalTrackSelectorWidget/components/__snapshots__/HierarchicalTrackSelector.test.tsx.snap +89 -24
  129. package/src/HierarchicalTrackSelectorWidget/components/dialogs/CloseConnectionDialog.tsx +9 -13
  130. package/src/HierarchicalTrackSelectorWidget/components/dialogs/ToggleConnectionsDialog.tsx +69 -39
  131. package/src/HierarchicalTrackSelectorWidget/components/faceted/FacetedSelector.tsx +14 -18
  132. package/src/HierarchicalTrackSelectorWidget/components/tree/HamburgerMenu.tsx +46 -51
  133. package/src/HierarchicalTrackSelectorWidget/components/tree/HierarchicalHeader.tsx +1 -3
  134. package/src/HierarchicalTrackSelectorWidget/model.ts +120 -65
  135. package/src/PluginStoreWidget/model.test.tsx +1 -1
  136. package/src/ucsc-trackhub/model.ts +28 -24
@@ -46,7 +46,7 @@ export default observer(function FacetedSelector({
46
46
  }: {
47
47
  model: HierarchicalTrackSelectorModel
48
48
  }) {
49
- const { assemblyNames, view, selection } = model
49
+ const { view, selection } = model
50
50
  const { pluginManager } = getEnv(model)
51
51
  const { ref, scrollLeft } = useResizeBar()
52
52
 
@@ -56,10 +56,9 @@ export default observer(function FacetedSelector({
56
56
  const [useShoppingCart, setUseShoppingCart] = useState(false)
57
57
  const [hideSparse, setHideSparse] = useState(true)
58
58
  const [panelWidth, setPanelWidth] = useState(400)
59
-
60
- const assemblyName = assemblyNames[0]
61
59
  const session = getSession(model)
62
60
  const filterDebounced = useDebounce(filterText, 400)
61
+ const tracks = view.tracks as AnyConfigurationModel[]
63
62
  const [filters, dispatch] = useReducer(
64
63
  (
65
64
  state: Record<string, string[]>,
@@ -73,8 +72,7 @@ export default observer(function FacetedSelector({
73
72
  const rows = useMemo(() => {
74
73
  // metadata is spread onto the object for easier access and sorting
75
74
  // by the mui data grid (it's unable to sort by nested objects)
76
- return model
77
- .trackConfigurations(assemblyName)
75
+ return model.trackConfigurations
78
76
  .filter(conf => matches(filterDebounced, conf, session))
79
77
  .map(track => {
80
78
  const metadata = readConfObject(track, 'metadata')
@@ -89,7 +87,7 @@ export default observer(function FacetedSelector({
89
87
  ...metadata,
90
88
  }
91
89
  })
92
- }, [assemblyName, model, filterDebounced, session])
90
+ }, [model, filterDebounced, session])
93
91
 
94
92
  const filteredNonMetadataKeys = useMemo(
95
93
  () =>
@@ -109,9 +107,10 @@ export default observer(function FacetedSelector({
109
107
  [hideSparse, rows],
110
108
  )
111
109
 
112
- const fields = useMemo(() => {
113
- return ['name', ...filteredNonMetadataKeys, ...filteredMetadataKeys]
114
- }, [filteredNonMetadataKeys, filteredMetadataKeys])
110
+ const fields = useMemo(
111
+ () => ['name', ...filteredNonMetadataKeys, ...filteredMetadataKeys],
112
+ [filteredNonMetadataKeys, filteredMetadataKeys],
113
+ )
115
114
 
116
115
  const [widths, setWidths] = useState({
117
116
  name:
@@ -137,7 +136,7 @@ export default observer(function FacetedSelector({
137
136
  ),
138
137
  ]),
139
138
  ),
140
- } as { [key: string]: number })
139
+ } as { [key: string]: number | undefined })
141
140
 
142
141
  const [visible, setVisible] = useState(
143
142
  Object.fromEntries(fields.map(c => [c, true])),
@@ -202,11 +201,11 @@ export default observer(function FacetedSelector({
202
201
  </>
203
202
  )
204
203
  },
205
- width: widthsDebounced.name || 100, // can be undefined before useEffect update
204
+ width: widthsDebounced.name ?? 100,
206
205
  },
207
206
  ...filteredNonMetadataKeys.map(e => ({
208
207
  field: e,
209
- width: widthsDebounced[e] || 100, // can be undefined before useEffect update
208
+ width: widthsDebounced[e] ?? 100,
210
209
  renderCell: (params: GridCellParams) => {
211
210
  const { value } = params
212
211
  return value ? <SanitizedHTML html={value as string} /> : ''
@@ -214,7 +213,7 @@ export default observer(function FacetedSelector({
214
213
  })),
215
214
  ...filteredMetadataKeys.map(e => ({
216
215
  field: e,
217
- width: widthsDebounced[e] || 100, // can be undefined before useEffect update
216
+ width: widthsDebounced[e] ?? 100,
218
217
  renderCell: (params: GridCellParams) => {
219
218
  const { value } = params
220
219
  return value ? <SanitizedHTML html={value as string} /> : ''
@@ -222,10 +221,7 @@ export default observer(function FacetedSelector({
222
221
  })),
223
222
  ]
224
223
 
225
- const shownTrackIds = view.tracks.map(
226
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
227
- (t: any) => t.configuration.trackId,
228
- ) as string[]
224
+ const shownTrackIds = tracks.map(t => t.configuration.trackId as string)
229
225
 
230
226
  const arrFilters = Object.entries(filters).filter(f => f[1].length > 0)
231
227
  return (
@@ -271,7 +267,7 @@ export default observer(function FacetedSelector({
271
267
  >
272
268
  <ResizeBar
273
269
  checkbox
274
- widths={Object.values(widths)}
270
+ widths={Object.values(widths).map(f => f ?? 100)}
275
271
  setWidths={newWidths =>
276
272
  setWidths(
277
273
  Object.fromEntries(
@@ -5,8 +5,10 @@ import { observer } from 'mobx-react'
5
5
  import JBrowseMenu from '@jbrowse/core/ui/Menu'
6
6
  import {
7
7
  getSession,
8
- isSessionModelWithWidgets,
8
+ isSessionModelWithConnectionEditing,
9
9
  isSessionModelWithConnections,
10
+ isSessionModelWithWidgets,
11
+ isSessionWithAddTracks,
10
12
  } from '@jbrowse/core/util'
11
13
  import {
12
14
  AnyConfigurationModel,
@@ -42,7 +44,7 @@ const useStyles = makeStyles()(theme => ({
42
44
 
43
45
  interface ModalArgs {
44
46
  connectionConf: AnyConfigurationModel
45
- safelyBreakConnection: Function
47
+ safelyBreakConnection: () => void
46
48
  dereferenceTypeCount: { [key: string]: number }
47
49
  name: string
48
50
  }
@@ -54,10 +56,8 @@ interface DialogDetails {
54
56
 
55
57
  export default observer(function HamburgerMenu({
56
58
  model,
57
- setAssemblyIdx,
58
59
  }: {
59
60
  model: HierarchicalTrackSelectorModel
60
- setAssemblyIdx: Function
61
61
  }) {
62
62
  const session = getSession(model)
63
63
  const [menuEl, setMenuEl] = useState<HTMLButtonElement>()
@@ -66,7 +66,6 @@ export default observer(function HamburgerMenu({
66
66
  const [connectionToggleOpen, setConnectionToggleOpen] = useState(false)
67
67
  const [connectionManagerOpen, setConnectionManagerOpen] = useState(false)
68
68
  const { classes } = useStyles()
69
- const { assemblyNames } = model
70
69
 
71
70
  function breakConnection(
72
71
  connectionConf: AnyConfigurationModel,
@@ -92,30 +91,6 @@ export default observer(function HamburgerMenu({
92
91
  }
93
92
  }
94
93
 
95
- const connectionMenuItems = [
96
- {
97
- label: 'Turn on/off connections...',
98
- onClick: () => setConnectionToggleOpen(true),
99
- },
100
- ]
101
-
102
- if (isSessionModelWithConnections(session)) {
103
- connectionMenuItems.unshift({
104
- label: 'Add connection...',
105
- onClick: () => {
106
- if (isSessionModelWithWidgets(session)) {
107
- session.showWidget(
108
- session.addWidget('AddConnectionWidget', 'addConnectionWidget'),
109
- )
110
- }
111
- },
112
- })
113
-
114
- connectionMenuItems.push({
115
- label: 'Delete connections...',
116
- onClick: () => setConnectionManagerOpen(true),
117
- })
118
- }
119
94
  return (
120
95
  <>
121
96
  <IconButton
@@ -134,38 +109,58 @@ export default observer(function HamburgerMenu({
134
109
  }}
135
110
  onClose={() => setMenuEl(undefined)}
136
111
  menuItems={[
137
- {
138
- label: 'Add track...',
139
- onClick: () => {
140
- if (isSessionModelWithWidgets(session)) {
141
- session.showWidget(
142
- session.addWidget('AddTrackWidget', 'addTrackWidget', {
143
- view: model.view.id,
144
- }),
145
- )
146
- }
147
- },
148
- },
149
- ...(session.makeConnection ? connectionMenuItems : []),
150
-
151
- ...(assemblyNames.length > 1
112
+ ...(isSessionWithAddTracks(session)
113
+ ? [
114
+ {
115
+ label: 'Add track...',
116
+ onClick: () => {
117
+ if (isSessionModelWithWidgets(session)) {
118
+ session.showWidget(
119
+ session.addWidget('AddTrackWidget', 'addTrackWidget', {
120
+ view: model.view.id,
121
+ }),
122
+ )
123
+ }
124
+ },
125
+ },
126
+ ]
127
+ : []),
128
+ ...(isSessionModelWithConnections(session)
152
129
  ? [
153
130
  {
154
- label: 'Select assembly...',
155
- subMenu: assemblyNames.map((name, idx) => ({
156
- label: name,
157
- onClick: () => setAssemblyIdx(idx),
158
- })),
131
+ label: 'Turn on/off connections...',
132
+ onClick: () => setConnectionToggleOpen(true),
133
+ },
134
+ ]
135
+ : []),
136
+ ...(isSessionModelWithConnectionEditing(session)
137
+ ? [
138
+ {
139
+ label: 'Add connection...',
140
+ onClick: () => {
141
+ if (isSessionModelWithWidgets(session)) {
142
+ session.showWidget(
143
+ session.addWidget(
144
+ 'AddConnectionWidget',
145
+ 'addConnectionWidget',
146
+ ),
147
+ )
148
+ }
149
+ },
150
+ },
151
+ {
152
+ label: 'Delete connections...',
153
+ onClick: () => setConnectionManagerOpen(true),
159
154
  },
160
155
  ]
161
156
  : []),
162
157
  ]}
163
158
  />
164
- <Suspense fallback={<div />}>
159
+ <Suspense fallback={<React.Fragment />}>
165
160
  {modalInfo ? (
166
161
  <CloseConnectionDlg
167
162
  modalInfo={modalInfo}
168
- setModalInfo={setModalInfo}
163
+ onClose={() => setModalInfo(undefined)}
169
164
  />
170
165
  ) : null}
171
166
  {deleteDlgDetails ? (
@@ -27,11 +27,9 @@ const useStyles = makeStyles()(theme => ({
27
27
  function HierarchicalTrackSelectorHeader({
28
28
  model,
29
29
  setHeaderHeight,
30
- setAssemblyIdx,
31
30
  }: {
32
31
  model: HierarchicalTrackSelectorModel
33
32
  setHeaderHeight: (n: number) => void
34
- setAssemblyIdx: (n: number) => void
35
33
  }) {
36
34
  const { classes } = useStyles()
37
35
  const [facetedOpen, setFacetedOpen] = useState(false)
@@ -43,7 +41,7 @@ function HierarchicalTrackSelectorHeader({
43
41
  data-testid="hierarchical_track_selector"
44
42
  >
45
43
  <div style={{ display: 'flex' }}>
46
- <HamburgerMenu model={model} setAssemblyIdx={setAssemblyIdx} />
44
+ <HamburgerMenu model={model} />
47
45
  <ShoppingCart model={model} />
48
46
 
49
47
  <TextField
@@ -9,6 +9,7 @@ import {
9
9
  dedupe,
10
10
  getSession,
11
11
  getEnv,
12
+ notEmpty,
12
13
  } from '@jbrowse/core/util'
13
14
  import { getTrackName } from '@jbrowse/core/util/tracks'
14
15
  import { ElementId } from '@jbrowse/core/util/types/mst'
@@ -49,22 +50,34 @@ export type TreeNode = {
49
50
 
50
51
  function filterTracks(
51
52
  tracks: AnyConfigurationModel[],
52
- self: { view: { type: string } },
53
- assemblyName: string,
53
+ self: {
54
+ view: { type: string; trackSelectorAnyOverlap?: boolean }
55
+ assemblyNames: string[]
56
+ },
54
57
  ) {
55
58
  const { assemblyManager } = getSession(self)
56
59
  const { pluginManager } = getEnv(self)
57
- const assembly = assemblyManager.get(assemblyName)
60
+ const { view } = self
61
+ const { trackSelectorAnyOverlap } = view
62
+ const trackListAssemblies = self.assemblyNames
63
+ .map(a => assemblyManager.get(a))
64
+ .filter(notEmpty)
58
65
 
59
- if (!assembly) {
60
- return []
61
- }
62
- const { allAliases } = assembly
63
66
  return tracks
64
- .filter(c => hasAnyOverlap(allAliases, readConfObject(c, 'assemblyNames')))
65
67
  .filter(c => {
66
- const { displayTypes } = pluginManager.getViewType(self.view.type)
67
- const compatDisplays = displayTypes.map((d: { name: string }) => d.name)
68
+ const trackAssemblyNames = readConfObject(c, 'assemblyNames') as string[]
69
+ const trackAssemblies = new Set(
70
+ trackAssemblyNames
71
+ ?.map(name => assemblyManager.get(name))
72
+ .filter(notEmpty) || [],
73
+ )
74
+ return trackSelectorAnyOverlap
75
+ ? trackListAssemblies.some(a => trackAssemblies.has(a))
76
+ : trackListAssemblies.every(a => trackAssemblies.has(a))
77
+ })
78
+ .filter(c => {
79
+ const { displayTypes } = pluginManager.getViewType(view.type)
80
+ const compatDisplays = displayTypes.map(d => d.name)
68
81
  const trackDisplays = c.displays.map((d: { type: string }) => d.type)
69
82
  return hasAnyOverlap(compatDisplays, trackDisplays)
70
83
  })
@@ -132,12 +145,27 @@ export function generateHierarchy(
132
145
  return hierarchy.children
133
146
  }
134
147
 
148
+ /**
149
+ * #stateModel HierarchicalTrackSelectorWidget
150
+ */
135
151
  export default function stateTreeFactory(pluginManager: PluginManager) {
136
152
  return types
137
153
  .model('HierarchicalTrackSelectorWidget', {
154
+ /**
155
+ * #property
156
+ */
138
157
  id: ElementId,
158
+ /**
159
+ * #property
160
+ */
139
161
  type: types.literal('HierarchicalTrackSelectorWidget'),
162
+ /**
163
+ * #property
164
+ */
140
165
  collapsed: types.map(types.boolean),
166
+ /**
167
+ * #property
168
+ */
141
169
  view: types.safeReference(
142
170
  pluginManager.pluggableMstType('view', 'stateModel'),
143
171
  ),
@@ -147,33 +175,62 @@ export default function stateTreeFactory(pluginManager: PluginManager) {
147
175
  filterText: '',
148
176
  }))
149
177
  .actions(self => ({
178
+ /**
179
+ * #action
180
+ */
150
181
  setSelection(elt: AnyConfigurationModel[]) {
151
182
  self.selection = elt
152
183
  },
184
+ /**
185
+ * #action
186
+ */
153
187
  addToSelection(elt: AnyConfigurationModel[]) {
154
188
  self.selection = dedupe([...self.selection, ...elt], e => e.trackId)
155
189
  },
190
+ /**
191
+ * #action
192
+ */
156
193
  removeFromSelection(elt: AnyConfigurationModel[]) {
157
194
  self.selection = self.selection.filter(f => !elt.includes(f))
158
195
  },
196
+ /**
197
+ * #action
198
+ */
159
199
  clearSelection() {
160
200
  self.selection = []
161
201
  },
202
+ /**
203
+ * #action
204
+ */
162
205
  setView(view: unknown) {
163
206
  self.view = view
164
207
  },
208
+ /**
209
+ * #action
210
+ */
165
211
  toggleCategory(pathName: string) {
166
212
  self.collapsed.set(pathName, !self.collapsed.get(pathName))
167
213
  },
214
+ /**
215
+ * #action
216
+ */
168
217
  clearFilterText() {
169
218
  self.filterText = ''
170
219
  },
220
+ /**
221
+ * #action
222
+ */
171
223
  setFilterText(newText: string) {
172
224
  self.filterText = newText
173
225
  },
174
226
  }))
175
227
  .views(self => ({
176
- getRefSeqTrackConf(assemblyName: string) {
228
+ /**
229
+ * #method
230
+ */
231
+ getRefSeqTrackConf(
232
+ assemblyName: string,
233
+ ): AnyConfigurationModel | undefined {
177
234
  const { assemblyManager } = getSession(self)
178
235
  const assembly = assemblyManager.get(assemblyName)
179
236
  const trackConf = assembly?.configuration.sequence
@@ -186,71 +243,67 @@ export default function stateTreeFactory(pluginManager: PluginManager) {
186
243
  return trackConf
187
244
  }
188
245
  }
246
+ return undefined
189
247
  },
190
248
  }))
191
249
  .views(self => ({
192
- trackConfigurations(assemblyName: string) {
193
- if (!self.view) {
194
- return []
195
- }
196
- const { tracks, assemblyManager } = getSession(self)
197
- const assembly = assemblyManager.get(assemblyName)
198
- if (!assembly) {
199
- return []
200
- }
201
- const refseq = self.getRefSeqTrackConf(assemblyName)
202
- // filter out tracks that don't match the current assembly (check all
203
- // assembly aliases) and display types
204
- return [
205
- ...(refseq ? [refseq] : []),
206
- ...filterTracks(tracks, self, assemblyName),
207
- ]
208
- },
209
-
250
+ /**
251
+ * #getter
252
+ */
210
253
  get assemblyNames(): string[] {
211
254
  return self.view?.assemblyNames || []
212
255
  },
256
+ }))
257
+ .views(self => ({
258
+ /**
259
+ * #method
260
+ * filter out tracks that don't match the current display types
261
+ */
262
+ connectionTrackConfigurations(connection: {
263
+ tracks: AnyConfigurationModel[]
264
+ }) {
265
+ return !self.view ? [] : filterTracks(connection.tracks, self)
266
+ },
213
267
 
214
- connectionTrackConfigurations(
215
- assemblyName: string,
216
- connection: { tracks: AnyConfigurationModel[] },
217
- ) {
218
- if (!self.view) {
219
- return []
220
- }
221
-
222
- // filter out tracks that don't match the current display types
223
- return filterTracks(connection.tracks, self, assemblyName)
268
+ /**
269
+ * #getter
270
+ * filter out tracks that don't match the current assembly/display types
271
+ */
272
+ get trackConfigurations(): AnyConfigurationModel[] {
273
+ return !self.view
274
+ ? ([] as AnyConfigurationModel[])
275
+ : [
276
+ ...self.assemblyNames.map(a => self.getRefSeqTrackConf(a)),
277
+ ...filterTracks(getSession(self).tracks, self),
278
+ ].filter(notEmpty)
224
279
  },
225
280
  }))
226
281
  .views(self => ({
227
- hierarchy(assemblyName: string) {
282
+ /**
283
+ * #getter
284
+ */
285
+ get hierarchy() {
228
286
  const hier = generateHierarchy(
229
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
230
- self as any,
231
- self.trackConfigurations(assemblyName),
287
+ self as HierarchicalTrackSelectorModel,
288
+ self.trackConfigurations,
232
289
  self.collapsed,
233
290
  )
234
291
 
235
292
  const session = getSession(self)
236
293
  const { connectionInstances } = session
237
294
 
238
- const { assemblyManager } = getSession(self)
239
- const assembly = assemblyManager.get(assemblyName)
240
295
  const conns =
241
- (assembly &&
242
- connectionInstances
243
- ?.map(c => ({
244
- // @ts-expect-error
245
- id: getSnapshot(c).configuration,
246
- name: getConf(c, 'name'),
247
- children: this.connectionHierarchy(assemblyName, c),
248
- state: {
249
- expanded: true,
250
- },
251
- }))
252
- .filter(f => f.children.length)) ||
253
- []
296
+ connectionInstances
297
+ ?.map(c => ({
298
+ // @ts-expect-error
299
+ id: getSnapshot(c).configuration,
300
+ name: getConf(c, 'name'),
301
+ children: this.connectionHierarchy(c),
302
+ state: {
303
+ expanded: true,
304
+ },
305
+ }))
306
+ .filter(f => f.children.length) || []
254
307
 
255
308
  return {
256
309
  name: 'Root',
@@ -262,14 +315,16 @@ export default function stateTreeFactory(pluginManager: PluginManager) {
262
315
  }
263
316
  },
264
317
 
265
- connectionHierarchy(
266
- assemblyName: string,
267
- connection: { name: string; tracks: AnyConfigurationModel[] },
268
- ) {
318
+ /**
319
+ * #method
320
+ */
321
+ connectionHierarchy(connection: {
322
+ name: string
323
+ tracks: AnyConfigurationModel[]
324
+ }) {
269
325
  return generateHierarchy(
270
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
271
- self as any,
272
- self.connectionTrackConfigurations(assemblyName, connection),
326
+ self as HierarchicalTrackSelectorModel,
327
+ self.connectionTrackConfigurations(connection),
273
328
  self.collapsed,
274
329
  connection.name,
275
330
  )
@@ -1,4 +1,4 @@
1
- import { createTestSession } from '@jbrowse/web/src/rootModel'
1
+ import { createTestSession } from '@jbrowse/web/src/rootModel/test_util'
2
2
  jest.mock('@jbrowse/web/src/makeWorkerInstance', () => () => {})
3
3
 
4
4
  describe('PluginStoreModel', () => {
@@ -10,12 +10,6 @@ import { types } from 'mobx-state-tree'
10
10
 
11
11
  // locals
12
12
  import configSchema from './configSchema'
13
- import {
14
- fetchGenomesFile,
15
- fetchHubFile,
16
- fetchTrackDbFile,
17
- generateTracks,
18
- } from './ucscTrackHub'
19
13
 
20
14
  export default function UCSCTrackHubConnection(pluginManager: PluginManager) {
21
15
  return types
@@ -30,9 +24,15 @@ export default function UCSCTrackHubConnection(pluginManager: PluginManager) {
30
24
  .actions(self => ({
31
25
  async connect() {
32
26
  const session = getSession(self)
27
+ const notLoadedAssemblies = [] as string[]
33
28
  try {
34
- const connectionName = getConf(self, 'name') // NOTE: name comes from the base configuration
35
29
  const hubFileLocation = getConf(self, 'hubTxtLocation')
30
+ const {
31
+ generateTracks,
32
+ fetchGenomesFile,
33
+ fetchTrackDbFile,
34
+ fetchHubFile,
35
+ } = await import('./ucscTrackHub')
36
36
  const hubFile = await fetchHubFile(hubFileLocation)
37
37
  const genomeFile = hubFile.get('genomesFile')
38
38
  if (!genomeFile) {
@@ -50,7 +50,7 @@ export default function UCSCTrackHubConnection(pluginManager: PluginManager) {
50
50
  locationType: 'LocalPathLocation' as const,
51
51
  }
52
52
  const genomesFile = await fetchGenomesFile(genomesFileLocation)
53
- const trackDbData = []
53
+ const map = {} as { [key: string]: number }
54
54
  for (const [genomeName, genome] of genomesFile) {
55
55
  const assemblyNames = getConf(self, 'assemblyNames')
56
56
  if (
@@ -62,16 +62,15 @@ export default function UCSCTrackHubConnection(pluginManager: PluginManager) {
62
62
 
63
63
  const conf = session.assemblyManager.get(genomeName)?.configuration
64
64
  if (!conf) {
65
- throw new Error(
66
- `Cannot find assembly for "${genomeName}" from the genomes file for connection "${connectionName}"`,
67
- )
65
+ notLoadedAssemblies.push(genomeName)
66
+ continue
68
67
  }
69
68
  const db = genome.get('trackDb')
70
69
  if (!db) {
71
70
  throw new Error('genomesFile not found on hub')
72
71
  }
73
72
  const base = new URL(genomeFile, hubUri)
74
- const trackDbLoc = hubUri
73
+ const loc = hubUri
75
74
  ? {
76
75
  uri: new URL(db, base).href,
77
76
  locationType: 'UriLocation' as const,
@@ -80,20 +79,25 @@ export default function UCSCTrackHubConnection(pluginManager: PluginManager) {
80
79
  localPath: db,
81
80
  locationType: 'LocalPathLocation' as const,
82
81
  }
83
- const trackDb = await fetchTrackDbFile(trackDbLoc)
84
- trackDbData.push([trackDbLoc, trackDb, genomeName, conf] as const)
85
- }
86
- for (const [
87
- trackDbLoc,
88
- trackDbFile,
89
- genomeName,
90
- conf,
91
- ] of trackDbData) {
82
+ const trackDb = await fetchTrackDbFile(loc)
92
83
  const seqAdapter = readConfObject(conf, ['sequence', 'adapter'])
93
- self.addTrackConfs(
94
- generateTracks(trackDbFile, trackDbLoc, genomeName, seqAdapter),
95
- )
84
+ const tracks = generateTracks(trackDb, loc, genomeName, seqAdapter)
85
+ self.addTrackConfs(tracks)
86
+ map[genomeName] = tracks.length
96
87
  }
88
+
89
+ const loadedAssemblies = Object.entries(map)
90
+ const str1 = loadedAssemblies.length
91
+ ? `Loaded data from these assemblies: ${loadedAssemblies
92
+ .map(([key, val]) => `${key} (${val} tracks)`)
93
+ .join(', ')}`
94
+ : ''
95
+ const str2 = notLoadedAssemblies.length
96
+ ? `Skipped data from these assemblies: ${notLoadedAssemblies.join(
97
+ ', ',
98
+ )}`
99
+ : ''
100
+ session.notify([str1, str2].filter(f => !!f).join('. '), 'success')
97
101
  } catch (e) {
98
102
  console.error(e)
99
103
  session.notify(