@jbrowse/plugin-data-management 2.3.3 → 2.3.4

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 (170) hide show
  1. package/dist/AddTrackWidget/components/DefaultAddTrackWorkflow.js +1 -4
  2. package/dist/AddTrackWidget/components/DefaultAddTrackWorkflow.js.map +1 -1
  3. package/dist/AddTrackWidget/components/TrackSourceSelect.js +1 -4
  4. package/dist/AddTrackWidget/components/TrackSourceSelect.js.map +1 -1
  5. package/dist/HierarchicalTrackSelectorWidget/components/HierarchicalFab.d.ts +6 -0
  6. package/dist/HierarchicalTrackSelectorWidget/components/HierarchicalFab.js +71 -0
  7. package/dist/HierarchicalTrackSelectorWidget/components/HierarchicalFab.js.map +1 -0
  8. package/dist/HierarchicalTrackSelectorWidget/components/HierarchicalTrackSelector.js +10 -104
  9. package/dist/HierarchicalTrackSelectorWidget/components/HierarchicalTrackSelector.js.map +1 -1
  10. package/dist/HierarchicalTrackSelectorWidget/components/ShoppingCart.d.ts +6 -0
  11. package/dist/HierarchicalTrackSelectorWidget/components/ShoppingCart.js +70 -0
  12. package/dist/HierarchicalTrackSelectorWidget/components/ShoppingCart.js.map +1 -0
  13. package/dist/HierarchicalTrackSelectorWidget/components/{CloseConnectionDialog.d.ts → dialogs/CloseConnectionDialog.d.ts} +0 -0
  14. package/dist/HierarchicalTrackSelectorWidget/components/{CloseConnectionDialog.js → dialogs/CloseConnectionDialog.js} +0 -0
  15. package/dist/HierarchicalTrackSelectorWidget/components/dialogs/CloseConnectionDialog.js.map +1 -0
  16. package/dist/HierarchicalTrackSelectorWidget/components/{DeleteConnectionDialog.d.ts → dialogs/DeleteConnectionDialog.d.ts} +0 -0
  17. package/dist/HierarchicalTrackSelectorWidget/components/{DeleteConnectionDialog.js → dialogs/DeleteConnectionDialog.js} +0 -0
  18. package/dist/HierarchicalTrackSelectorWidget/components/dialogs/DeleteConnectionDialog.js.map +1 -0
  19. package/dist/HierarchicalTrackSelectorWidget/components/{ManageConnectionsDialog.d.ts → dialogs/ManageConnectionsDialog.d.ts} +0 -0
  20. package/dist/HierarchicalTrackSelectorWidget/components/{ManageConnectionsDialog.js → dialogs/ManageConnectionsDialog.js} +0 -0
  21. package/dist/HierarchicalTrackSelectorWidget/components/dialogs/ManageConnectionsDialog.js.map +1 -0
  22. package/dist/HierarchicalTrackSelectorWidget/components/{ToggleConnectionsDialog.d.ts → dialogs/ToggleConnectionsDialog.d.ts} +0 -0
  23. package/dist/HierarchicalTrackSelectorWidget/components/{ToggleConnectionsDialog.js → dialogs/ToggleConnectionsDialog.js} +0 -0
  24. package/dist/HierarchicalTrackSelectorWidget/components/dialogs/ToggleConnectionsDialog.js.map +1 -0
  25. package/dist/HierarchicalTrackSelectorWidget/components/faceted/FacetFilters.d.ts +13 -0
  26. package/dist/HierarchicalTrackSelectorWidget/components/faceted/FacetFilters.js +99 -0
  27. package/dist/HierarchicalTrackSelectorWidget/components/faceted/FacetFilters.js.map +1 -0
  28. package/dist/HierarchicalTrackSelectorWidget/components/faceted/FacetedDialog.d.ts +8 -0
  29. package/dist/HierarchicalTrackSelectorWidget/components/faceted/FacetedDialog.js +18 -0
  30. package/dist/HierarchicalTrackSelectorWidget/components/faceted/FacetedDialog.js.map +1 -0
  31. package/dist/HierarchicalTrackSelectorWidget/components/faceted/FacetedHeader.d.ts +11 -0
  32. package/dist/HierarchicalTrackSelectorWidget/components/faceted/FacetedHeader.js +71 -0
  33. package/dist/HierarchicalTrackSelectorWidget/components/faceted/FacetedHeader.js.map +1 -0
  34. package/dist/HierarchicalTrackSelectorWidget/components/faceted/FacetedSelector.d.ts +12 -0
  35. package/dist/HierarchicalTrackSelectorWidget/components/faceted/FacetedSelector.js +211 -0
  36. package/dist/HierarchicalTrackSelectorWidget/components/faceted/FacetedSelector.js.map +1 -0
  37. package/dist/HierarchicalTrackSelectorWidget/components/faceted/util.d.ts +1 -0
  38. package/dist/HierarchicalTrackSelectorWidget/components/faceted/util.js +10 -0
  39. package/dist/HierarchicalTrackSelectorWidget/components/faceted/util.js.map +1 -0
  40. package/dist/HierarchicalTrackSelectorWidget/components/tree/HamburgerMenu.d.ts +7 -0
  41. package/dist/HierarchicalTrackSelectorWidget/components/tree/HamburgerMenu.js +136 -0
  42. package/dist/HierarchicalTrackSelectorWidget/components/tree/HamburgerMenu.js.map +1 -0
  43. package/dist/HierarchicalTrackSelectorWidget/components/{Header.d.ts → tree/HierarchicalHeader.d.ts} +2 -3
  44. package/dist/HierarchicalTrackSelectorWidget/components/tree/HierarchicalHeader.js +65 -0
  45. package/dist/HierarchicalTrackSelectorWidget/components/tree/HierarchicalHeader.js.map +1 -0
  46. package/dist/HierarchicalTrackSelectorWidget/components/tree/HierarchicalTree.d.ts +8 -0
  47. package/dist/HierarchicalTrackSelectorWidget/components/tree/HierarchicalTree.js +91 -0
  48. package/dist/HierarchicalTrackSelectorWidget/components/tree/HierarchicalTree.js.map +1 -0
  49. package/dist/HierarchicalTrackSelectorWidget/components/tree/TrackCategory.d.ts +7 -0
  50. package/dist/HierarchicalTrackSelectorWidget/components/tree/TrackCategory.js +89 -0
  51. package/dist/HierarchicalTrackSelectorWidget/components/tree/TrackCategory.js.map +1 -0
  52. package/dist/HierarchicalTrackSelectorWidget/components/tree/TrackLabel.d.ts +11 -0
  53. package/dist/HierarchicalTrackSelectorWidget/components/tree/TrackLabel.js +86 -0
  54. package/dist/HierarchicalTrackSelectorWidget/components/tree/TrackLabel.js.map +1 -0
  55. package/dist/HierarchicalTrackSelectorWidget/components/tree/TrackListNode.d.ts +10 -0
  56. package/dist/HierarchicalTrackSelectorWidget/components/tree/TrackListNode.js +54 -0
  57. package/dist/HierarchicalTrackSelectorWidget/components/tree/TrackListNode.js.map +1 -0
  58. package/dist/HierarchicalTrackSelectorWidget/components/util.d.ts +17 -1
  59. package/dist/HierarchicalTrackSelectorWidget/components/util.js +16 -1
  60. package/dist/HierarchicalTrackSelectorWidget/components/util.js.map +1 -1
  61. package/dist/HierarchicalTrackSelectorWidget/model.d.ts +4 -1
  62. package/dist/HierarchicalTrackSelectorWidget/model.js +12 -8
  63. package/dist/HierarchicalTrackSelectorWidget/model.js.map +1 -1
  64. package/esm/AddTrackWidget/components/DefaultAddTrackWorkflow.js +1 -4
  65. package/esm/AddTrackWidget/components/DefaultAddTrackWorkflow.js.map +1 -1
  66. package/esm/AddTrackWidget/components/TrackSourceSelect.js +1 -4
  67. package/esm/AddTrackWidget/components/TrackSourceSelect.js.map +1 -1
  68. package/esm/HierarchicalTrackSelectorWidget/components/HierarchicalFab.d.ts +6 -0
  69. package/esm/HierarchicalTrackSelectorWidget/components/HierarchicalFab.js +43 -0
  70. package/esm/HierarchicalTrackSelectorWidget/components/HierarchicalFab.js.map +1 -0
  71. package/esm/HierarchicalTrackSelectorWidget/components/HierarchicalTrackSelector.js +9 -103
  72. package/esm/HierarchicalTrackSelectorWidget/components/HierarchicalTrackSelector.js.map +1 -1
  73. package/esm/HierarchicalTrackSelectorWidget/components/ShoppingCart.d.ts +6 -0
  74. package/esm/HierarchicalTrackSelectorWidget/components/ShoppingCart.js +42 -0
  75. package/esm/HierarchicalTrackSelectorWidget/components/ShoppingCart.js.map +1 -0
  76. package/esm/HierarchicalTrackSelectorWidget/components/{CloseConnectionDialog.d.ts → dialogs/CloseConnectionDialog.d.ts} +0 -0
  77. package/esm/HierarchicalTrackSelectorWidget/components/{CloseConnectionDialog.js → dialogs/CloseConnectionDialog.js} +0 -0
  78. package/esm/HierarchicalTrackSelectorWidget/components/dialogs/CloseConnectionDialog.js.map +1 -0
  79. package/esm/HierarchicalTrackSelectorWidget/components/{DeleteConnectionDialog.d.ts → dialogs/DeleteConnectionDialog.d.ts} +0 -0
  80. package/esm/HierarchicalTrackSelectorWidget/components/{DeleteConnectionDialog.js → dialogs/DeleteConnectionDialog.js} +0 -0
  81. package/esm/HierarchicalTrackSelectorWidget/components/dialogs/DeleteConnectionDialog.js.map +1 -0
  82. package/esm/HierarchicalTrackSelectorWidget/components/{ManageConnectionsDialog.d.ts → dialogs/ManageConnectionsDialog.d.ts} +0 -0
  83. package/esm/HierarchicalTrackSelectorWidget/components/{ManageConnectionsDialog.js → dialogs/ManageConnectionsDialog.js} +0 -0
  84. package/esm/HierarchicalTrackSelectorWidget/components/dialogs/ManageConnectionsDialog.js.map +1 -0
  85. package/esm/HierarchicalTrackSelectorWidget/components/{ToggleConnectionsDialog.d.ts → dialogs/ToggleConnectionsDialog.d.ts} +0 -0
  86. package/esm/HierarchicalTrackSelectorWidget/components/{ToggleConnectionsDialog.js → dialogs/ToggleConnectionsDialog.js} +0 -0
  87. package/esm/HierarchicalTrackSelectorWidget/components/dialogs/ToggleConnectionsDialog.js.map +1 -0
  88. package/esm/HierarchicalTrackSelectorWidget/components/faceted/FacetFilters.d.ts +13 -0
  89. package/esm/HierarchicalTrackSelectorWidget/components/faceted/FacetFilters.js +70 -0
  90. package/esm/HierarchicalTrackSelectorWidget/components/faceted/FacetFilters.js.map +1 -0
  91. package/esm/HierarchicalTrackSelectorWidget/components/faceted/FacetedDialog.d.ts +8 -0
  92. package/esm/HierarchicalTrackSelectorWidget/components/faceted/FacetedDialog.js +13 -0
  93. package/esm/HierarchicalTrackSelectorWidget/components/faceted/FacetedDialog.js.map +1 -0
  94. package/esm/HierarchicalTrackSelectorWidget/components/faceted/FacetedHeader.d.ts +11 -0
  95. package/esm/HierarchicalTrackSelectorWidget/components/faceted/FacetedHeader.js +42 -0
  96. package/esm/HierarchicalTrackSelectorWidget/components/faceted/FacetedHeader.js.map +1 -0
  97. package/esm/HierarchicalTrackSelectorWidget/components/faceted/FacetedSelector.d.ts +12 -0
  98. package/esm/HierarchicalTrackSelectorWidget/components/faceted/FacetedSelector.js +183 -0
  99. package/esm/HierarchicalTrackSelectorWidget/components/faceted/FacetedSelector.js.map +1 -0
  100. package/esm/HierarchicalTrackSelectorWidget/components/faceted/util.d.ts +1 -0
  101. package/esm/HierarchicalTrackSelectorWidget/components/faceted/util.js +6 -0
  102. package/esm/HierarchicalTrackSelectorWidget/components/faceted/util.js.map +1 -0
  103. package/esm/HierarchicalTrackSelectorWidget/components/tree/HamburgerMenu.d.ts +7 -0
  104. package/esm/HierarchicalTrackSelectorWidget/components/tree/HamburgerMenu.js +108 -0
  105. package/esm/HierarchicalTrackSelectorWidget/components/tree/HamburgerMenu.js.map +1 -0
  106. package/esm/HierarchicalTrackSelectorWidget/components/{Header.d.ts → tree/HierarchicalHeader.d.ts} +2 -3
  107. package/esm/HierarchicalTrackSelectorWidget/components/tree/HierarchicalHeader.js +37 -0
  108. package/esm/HierarchicalTrackSelectorWidget/components/tree/HierarchicalHeader.js.map +1 -0
  109. package/esm/HierarchicalTrackSelectorWidget/components/tree/HierarchicalTree.d.ts +8 -0
  110. package/esm/HierarchicalTrackSelectorWidget/components/tree/HierarchicalTree.js +63 -0
  111. package/esm/HierarchicalTrackSelectorWidget/components/tree/HierarchicalTree.js.map +1 -0
  112. package/esm/HierarchicalTrackSelectorWidget/components/tree/TrackCategory.d.ts +7 -0
  113. package/esm/HierarchicalTrackSelectorWidget/components/tree/TrackCategory.js +60 -0
  114. package/esm/HierarchicalTrackSelectorWidget/components/tree/TrackCategory.js.map +1 -0
  115. package/esm/HierarchicalTrackSelectorWidget/components/tree/TrackLabel.d.ts +11 -0
  116. package/esm/HierarchicalTrackSelectorWidget/components/tree/TrackLabel.js +57 -0
  117. package/esm/HierarchicalTrackSelectorWidget/components/tree/TrackLabel.js.map +1 -0
  118. package/esm/HierarchicalTrackSelectorWidget/components/tree/TrackListNode.d.ts +10 -0
  119. package/esm/HierarchicalTrackSelectorWidget/components/tree/TrackListNode.js +48 -0
  120. package/esm/HierarchicalTrackSelectorWidget/components/tree/TrackListNode.js.map +1 -0
  121. package/esm/HierarchicalTrackSelectorWidget/components/util.d.ts +17 -1
  122. package/esm/HierarchicalTrackSelectorWidget/components/util.js +13 -0
  123. package/esm/HierarchicalTrackSelectorWidget/components/util.js.map +1 -1
  124. package/esm/HierarchicalTrackSelectorWidget/model.d.ts +4 -1
  125. package/esm/HierarchicalTrackSelectorWidget/model.js +10 -7
  126. package/esm/HierarchicalTrackSelectorWidget/model.js.map +1 -1
  127. package/package.json +3 -2
  128. package/src/AddTrackWidget/components/DefaultAddTrackWorkflow.tsx +1 -4
  129. package/src/AddTrackWidget/components/TrackSourceSelect.tsx +3 -5
  130. package/src/HierarchicalTrackSelectorWidget/components/HierarchicalFab.tsx +94 -0
  131. package/src/HierarchicalTrackSelectorWidget/components/HierarchicalTrackSelector.tsx +47 -228
  132. package/src/HierarchicalTrackSelectorWidget/components/ShoppingCart.tsx +73 -0
  133. package/src/HierarchicalTrackSelectorWidget/components/__snapshots__/HierarchicalTrackSelector.test.tsx.snap +20 -38
  134. package/src/HierarchicalTrackSelectorWidget/components/{CloseConnectionDialog.tsx → dialogs/CloseConnectionDialog.tsx} +0 -0
  135. package/src/HierarchicalTrackSelectorWidget/components/{DeleteConnectionDialog.tsx → dialogs/DeleteConnectionDialog.tsx} +0 -0
  136. package/src/HierarchicalTrackSelectorWidget/components/{ManageConnectionsDialog.tsx → dialogs/ManageConnectionsDialog.tsx} +0 -0
  137. package/src/HierarchicalTrackSelectorWidget/components/{ToggleConnectionsDialog.tsx → dialogs/ToggleConnectionsDialog.tsx} +0 -0
  138. package/src/HierarchicalTrackSelectorWidget/components/faceted/FacetFilters.tsx +138 -0
  139. package/src/HierarchicalTrackSelectorWidget/components/faceted/FacetedDialog.tsx +29 -0
  140. package/src/HierarchicalTrackSelectorWidget/components/faceted/FacetedHeader.tsx +86 -0
  141. package/src/HierarchicalTrackSelectorWidget/components/faceted/FacetedSelector.tsx +339 -0
  142. package/src/HierarchicalTrackSelectorWidget/components/faceted/util.ts +5 -0
  143. package/src/HierarchicalTrackSelectorWidget/components/tree/HamburgerMenu.tsx +197 -0
  144. package/src/HierarchicalTrackSelectorWidget/components/tree/HierarchicalHeader.tsx +88 -0
  145. package/src/HierarchicalTrackSelectorWidget/components/tree/HierarchicalTree.tsx +101 -0
  146. package/src/HierarchicalTrackSelectorWidget/components/tree/TrackCategory.tsx +92 -0
  147. package/src/HierarchicalTrackSelectorWidget/components/tree/TrackLabel.tsx +107 -0
  148. package/src/HierarchicalTrackSelectorWidget/components/tree/TrackListNode.tsx +84 -0
  149. package/src/HierarchicalTrackSelectorWidget/components/util.ts +31 -1
  150. package/src/HierarchicalTrackSelectorWidget/model.ts +12 -9
  151. package/dist/HierarchicalTrackSelectorWidget/components/CloseConnectionDialog.js.map +0 -1
  152. package/dist/HierarchicalTrackSelectorWidget/components/DeleteConnectionDialog.js.map +0 -1
  153. package/dist/HierarchicalTrackSelectorWidget/components/Header.js +0 -174
  154. package/dist/HierarchicalTrackSelectorWidget/components/Header.js.map +0 -1
  155. package/dist/HierarchicalTrackSelectorWidget/components/ManageConnectionsDialog.js.map +0 -1
  156. package/dist/HierarchicalTrackSelectorWidget/components/Node.d.ts +0 -29
  157. package/dist/HierarchicalTrackSelectorWidget/components/Node.js +0 -173
  158. package/dist/HierarchicalTrackSelectorWidget/components/Node.js.map +0 -1
  159. package/dist/HierarchicalTrackSelectorWidget/components/ToggleConnectionsDialog.js.map +0 -1
  160. package/esm/HierarchicalTrackSelectorWidget/components/CloseConnectionDialog.js.map +0 -1
  161. package/esm/HierarchicalTrackSelectorWidget/components/DeleteConnectionDialog.js.map +0 -1
  162. package/esm/HierarchicalTrackSelectorWidget/components/Header.js +0 -146
  163. package/esm/HierarchicalTrackSelectorWidget/components/Header.js.map +0 -1
  164. package/esm/HierarchicalTrackSelectorWidget/components/ManageConnectionsDialog.js.map +0 -1
  165. package/esm/HierarchicalTrackSelectorWidget/components/Node.d.ts +0 -29
  166. package/esm/HierarchicalTrackSelectorWidget/components/Node.js +0 -144
  167. package/esm/HierarchicalTrackSelectorWidget/components/Node.js.map +0 -1
  168. package/esm/HierarchicalTrackSelectorWidget/components/ToggleConnectionsDialog.js.map +0 -1
  169. package/src/HierarchicalTrackSelectorWidget/components/Header.tsx +0 -286
  170. package/src/HierarchicalTrackSelectorWidget/components/Node.tsx +0 -282
@@ -1,127 +1,12 @@
1
- import React, { useCallback, useMemo, useState, useRef, useEffect } from 'react'
2
- import { Fab, Menu, MenuItem } from '@mui/material'
3
- import { makeStyles } from 'tss-react/mui'
4
- import {
5
- getSession,
6
- isSessionModelWithWidgets,
7
- isSessionModelWithConnections,
8
- isSessionWithAddTracks,
9
- } from '@jbrowse/core/util'
1
+ import React, { useState } from 'react'
10
2
  import { observer } from 'mobx-react'
11
- import { VariableSizeTree } from 'react-vtree'
12
3
  import AutoSizer from 'react-virtualized-auto-sizer'
13
4
 
14
- // icons
15
- import AddIcon from '@mui/icons-material/Add'
16
-
17
5
  // locals
18
6
  import { TreeNode, HierarchicalTrackSelectorModel } from '../model'
19
- import Header from './Header'
20
- import Node from './Node'
21
-
22
- const useStyles = makeStyles()(theme => ({
23
- fab: {
24
- position: 'absolute',
25
- bottom: theme.spacing(6),
26
- right: theme.spacing(6),
27
- },
28
- }))
29
-
30
- function getNodeData(
31
- node: TreeNode,
32
- nestingLevel: number,
33
- extra: Record<string, unknown>,
34
- selection: Record<string, unknown>,
35
- ) {
36
- const isLeaf = !!node.conf
37
- const selected = !!selection[node.id]
38
- return {
39
- data: {
40
- defaultHeight: isLeaf ? 22 : 40,
41
- isLeaf,
42
- isOpenByDefault: true,
43
- nestingLevel,
44
- selected,
45
- ...node,
46
- ...extra,
47
- },
48
- nestingLevel,
49
- node,
50
- }
51
- }
52
-
53
- type NodeData = ReturnType<typeof getNodeData>
54
-
55
- // this is the main tree component for the hierarchical track selector in note:
56
- // in jbrowse-web the toolbar is position="sticky" which means the autosizer
57
- // includes the height of the toolbar, so we subtract the given offsets
58
- const HierarchicalTree = observer(
59
- ({
60
- height,
61
- tree,
62
- model,
63
- }: {
64
- height: number
65
- tree: TreeNode
66
- model: HierarchicalTrackSelectorModel
67
- }) => {
68
- const { filterText, selection, view } = model
69
- const treeRef = useRef<NodeData>(null)
70
- const session = getSession(model)
71
- const { drawerPosition } = session
72
- const obj = useMemo(
73
- () => Object.fromEntries(selection.map(s => [s.trackId, s])),
74
- [selection],
75
- )
76
-
77
- const extra = useMemo(
78
- () => ({
79
- onChange: (trackId: string) => view.toggleTrack(trackId),
80
- toggleCollapse: (pathName: string) => model.toggleCategory(pathName),
81
- tree,
82
- model,
83
- drawerPosition,
84
- }),
85
- [view, model, drawerPosition, tree],
86
- )
87
- const treeWalker = useCallback(
88
- function* treeWalker() {
89
- for (let i = 0; i < tree.children.length; i++) {
90
- const r = tree.children[i]
91
- yield getNodeData(r, 0, extra, obj)
92
- }
93
-
94
- while (true) {
95
- // @ts-ignore
96
- const parentMeta = yield
97
-
98
- for (let i = 0; i < parentMeta.node.children.length; i++) {
99
- const curr = parentMeta.node.children[i]
100
- yield getNodeData(curr, parentMeta.nestingLevel + 1, extra, obj)
101
- }
102
- }
103
- },
104
- [tree, extra, obj],
105
- )
106
-
107
- useEffect(() => {
108
- // @ts-ignore
109
- treeRef.current.recomputeTree({
110
- refreshNodes: true,
111
- useDefaultHeight: true,
112
- })
113
- }, [tree, filterText])
114
- return (
115
- <>
116
- {/* @ts-ignore */}
117
- <VariableSizeTree ref={treeRef} treeWalker={treeWalker} height={height}>
118
- {/* @ts-ignore */}
119
- {Node}
120
- </VariableSizeTree>
121
- </>
122
- )
123
- },
124
- )
7
+ import HierarchicalFab from './HierarchicalFab'
8
+ import HierarchicalTree from './tree/HierarchicalTree'
9
+ import HierarchicalHeader from './tree/HierarchicalHeader'
125
10
 
126
11
  // Don't use autosizer in jest and instead hardcode a height, otherwise fails
127
12
  // jest tests
@@ -164,115 +49,49 @@ const Wrapper = ({
164
49
  <>{children}</>
165
50
  )
166
51
  }
167
- const HierarchicalTrackSelectorContainer = observer(
168
- ({
169
- model,
170
- toolbarHeight,
171
- overrideDimensions,
172
- }: {
173
- model: HierarchicalTrackSelectorModel
174
- toolbarHeight: number
175
- overrideDimensions?: { width: number; height: number }
176
- }) => {
177
- const { classes } = useStyles()
178
- const session = getSession(model)
179
- const [anchorEl, setAnchorEl] = useState<HTMLButtonElement | null>(null)
180
-
181
- function handleFabClose() {
182
- setAnchorEl(null)
183
- }
184
- const hasConnections = isSessionModelWithConnections(session)
185
- const hasAddTrack = isSessionWithAddTracks(session)
186
- return (
187
- <Wrapper overrideDimensions={overrideDimensions}>
188
- <HierarchicalTrackSelector
189
- model={model}
190
- toolbarHeight={toolbarHeight}
191
- />
192
- {hasAddTrack || hasConnections ? (
193
- <>
194
- <Fab
195
- color="secondary"
196
- className={classes.fab}
197
- onClick={event => setAnchorEl(event.currentTarget)}
198
- >
199
- <AddIcon />
200
- </Fab>
201
- <Menu
202
- anchorEl={anchorEl}
203
- open={Boolean(anchorEl)}
204
- onClose={() => setAnchorEl(null)}
205
- >
206
- {hasConnections ? (
207
- <MenuItem
208
- onClick={() => {
209
- handleFabClose()
210
- if (isSessionModelWithWidgets(session)) {
211
- session.showWidget(
212
- session.addWidget(
213
- 'AddConnectionWidget',
214
- 'addConnectionWidget',
215
- ),
216
- )
217
- }
218
- }}
219
- >
220
- Add connection
221
- </MenuItem>
222
- ) : null}
223
- {hasAddTrack ? (
224
- <MenuItem
225
- onClick={() => {
226
- handleFabClose()
227
- if (isSessionModelWithWidgets(session)) {
228
- session.showWidget(
229
- session.addWidget('AddTrackWidget', 'addTrackWidget', {
230
- view: model.view.id,
231
- }),
232
- )
233
- }
234
- }}
235
- >
236
- Add track
237
- </MenuItem>
238
- ) : null}
239
- </Menu>
240
- </>
241
- ) : null}
242
- </Wrapper>
243
- )
244
- },
245
- )
246
-
247
- const HierarchicalTrackSelector = observer(
248
- ({
249
- model,
250
- toolbarHeight = 0,
251
- }: {
252
- model: HierarchicalTrackSelectorModel
253
- toolbarHeight?: number
254
- }) => {
255
- const [assemblyIdx, setAssemblyIdx] = useState(0)
256
- const [headerHeight, setHeaderHeight] = useState(0)
52
+ const HierarchicalTrackSelectorContainer = observer(function ({
53
+ model,
54
+ toolbarHeight,
55
+ overrideDimensions,
56
+ }: {
57
+ model: HierarchicalTrackSelectorModel
58
+ toolbarHeight: number
59
+ overrideDimensions?: { width: number; height: number }
60
+ }) {
61
+ return (
62
+ <Wrapper overrideDimensions={overrideDimensions}>
63
+ <HierarchicalTrackSelector model={model} toolbarHeight={toolbarHeight} />
64
+ <HierarchicalFab model={model} />
65
+ </Wrapper>
66
+ )
67
+ })
257
68
 
258
- const { assemblyNames } = model
259
- const assemblyName = assemblyNames.length ? assemblyNames[assemblyIdx] : ''
260
- return assemblyName ? (
261
- <>
262
- <Header
263
- model={model}
264
- setHeaderHeight={setHeaderHeight}
265
- setAssemblyIdx={setAssemblyIdx}
266
- assemblyIdx={assemblyIdx}
267
- />
268
- <AutoSizedHierarchicalTree
269
- tree={model.hierarchy(assemblyName)}
270
- model={model}
271
- offset={toolbarHeight + headerHeight}
272
- />
273
- </>
274
- ) : null
275
- },
276
- )
69
+ const HierarchicalTrackSelector = observer(function ({
70
+ model,
71
+ toolbarHeight = 0,
72
+ }: {
73
+ model: HierarchicalTrackSelectorModel
74
+ toolbarHeight?: number
75
+ }) {
76
+ const [assemblyIdx, setAssemblyIdx] = useState(0)
77
+ const [headerHeight, setHeaderHeight] = useState(0)
78
+
79
+ const { assemblyNames } = model
80
+ const assemblyName = assemblyNames[assemblyIdx]
81
+ return assemblyName ? (
82
+ <>
83
+ <HierarchicalHeader
84
+ model={model}
85
+ setHeaderHeight={setHeaderHeight}
86
+ setAssemblyIdx={setAssemblyIdx}
87
+ />
88
+ <AutoSizedHierarchicalTree
89
+ tree={model.hierarchy(assemblyName)}
90
+ model={model}
91
+ offset={toolbarHeight + headerHeight}
92
+ />
93
+ </>
94
+ ) : null
95
+ })
277
96
 
278
97
  export default HierarchicalTrackSelectorContainer
@@ -0,0 +1,73 @@
1
+ import React, { useState } from 'react'
2
+ import { Badge, IconButton } from '@mui/material'
3
+ import { makeStyles } from 'tss-react/mui'
4
+ import { observer } from 'mobx-react'
5
+ import JBrowseMenu, { MenuItem } from '@jbrowse/core/ui/Menu'
6
+ import { getSession, getEnv } from '@jbrowse/core/util'
7
+
8
+ // icons
9
+ import ShoppingCartIcon from '@mui/icons-material/ShoppingCart'
10
+
11
+ // locals
12
+ import { HierarchicalTrackSelectorModel } from '../model'
13
+
14
+ const useStyles = makeStyles()(theme => ({
15
+ searchBox: {
16
+ margin: theme.spacing(2),
17
+ },
18
+ menuIcon: {
19
+ marginRight: theme.spacing(1),
20
+ marginBottom: 0,
21
+ },
22
+ }))
23
+
24
+ export default observer(function ShoppingCart({
25
+ model,
26
+ }: {
27
+ model: HierarchicalTrackSelectorModel
28
+ }) {
29
+ const { classes } = useStyles()
30
+ const { selection } = model
31
+ const { pluginManager } = getEnv(model)
32
+ const session = getSession(model)
33
+ const [selectionEl, setSelectionEl] = useState<HTMLButtonElement>()
34
+ const items = pluginManager.evaluateExtensionPoint(
35
+ 'TrackSelector-multiTrackMenuItems',
36
+ [],
37
+ { session },
38
+ ) as MenuItem[]
39
+
40
+ return (
41
+ <>
42
+ {selection.length ? (
43
+ <IconButton
44
+ className={classes.menuIcon}
45
+ onClick={event => setSelectionEl(event.currentTarget)}
46
+ >
47
+ <Badge badgeContent={selection.length} color="primary">
48
+ <ShoppingCartIcon />
49
+ </Badge>
50
+ </IconButton>
51
+ ) : null}
52
+
53
+ <JBrowseMenu
54
+ anchorEl={selectionEl}
55
+ open={Boolean(selectionEl)}
56
+ onMenuItemClick={(_, callback) => {
57
+ callback()
58
+ setSelectionEl(undefined)
59
+ }}
60
+ onClose={() => setSelectionEl(undefined)}
61
+ menuItems={[
62
+ { label: 'Clear', onClick: () => model.clearSelection() },
63
+ ...items.map(item => ({
64
+ ...item,
65
+ ...('onClick' in item
66
+ ? { onClick: () => item.onClick(model) }
67
+ : {}),
68
+ })),
69
+ ]}
70
+ />
71
+ </>
72
+ )
73
+ })
@@ -50,25 +50,6 @@ exports[`renders with a couple of categorized tracks 1`] = `
50
50
  class="MuiTouchRipple-root css-8je8zh-MuiTouchRipple-root"
51
51
  />
52
52
  </button>
53
- <button
54
- class="MuiButtonBase-root MuiIconButton-root MuiIconButton-sizeSmall css-1m9x3cr-MuiButtonBase-root-MuiIconButton-root-menuIcon"
55
- tabindex="0"
56
- type="button"
57
- >
58
- <svg
59
- aria-hidden="true"
60
- class="MuiSvgIcon-root MuiSvgIcon-fontSizeMedium css-havevq-MuiSvgIcon-root"
61
- focusable="false"
62
- viewBox="0 0 24 24"
63
- >
64
- <path
65
- d="M20 5V4c0-.55-.45-1-1-1h-2c-.55 0-1 .45-1 1v1h-1v4c0 .55.45 1 1 1h1v7c0 1.1-.9 2-2 2s-2-.9-2-2V7c0-2.21-1.79-4-4-4S5 4.79 5 7v7H4c-.55 0-1 .45-1 1v4h1v1c0 .55.45 1 1 1h2c.55 0 1-.45 1-1v-1h1v-4c0-.55-.45-1-1-1H7V7c0-1.1.9-2 2-2s2 .9 2 2v10c0 2.21 1.79 4 4 4s4-1.79 4-4v-7h1c.55 0 1-.45 1-1V5h-1z"
66
- />
67
- </svg>
68
- <span
69
- class="MuiTouchRipple-root css-8je8zh-MuiTouchRipple-root"
70
- />
71
- </button>
72
53
  <div
73
54
  class="MuiFormControl-root MuiFormControl-marginDense MuiFormControl-fullWidth MuiTextField-root css-rlnh8o-MuiFormControl-root-MuiTextField-root-searchBox"
74
55
  >
@@ -116,6 +97,16 @@ exports[`renders with a couple of categorized tracks 1`] = `
116
97
  </div>
117
98
  </div>
118
99
  </div>
100
+ <button
101
+ class="MuiButtonBase-root MuiButton-root MuiButton-text MuiButton-textPrimary MuiButton-sizeSmall MuiButton-textSizeSmall MuiButton-root MuiButton-text MuiButton-textPrimary MuiButton-sizeSmall MuiButton-textSizeSmall css-1c8zr45-MuiButtonBase-root-MuiButton-root-menuIcon"
102
+ tabindex="0"
103
+ type="button"
104
+ >
105
+ Open faceted selector
106
+ <span
107
+ class="MuiTouchRipple-root css-8je8zh-MuiTouchRipple-root"
108
+ />
109
+ </button>
119
110
  </div>
120
111
  </div>
121
112
  `;
@@ -147,25 +138,6 @@ exports[`renders with a couple of uncategorized tracks 1`] = `
147
138
  class="MuiTouchRipple-root css-8je8zh-MuiTouchRipple-root"
148
139
  />
149
140
  </button>
150
- <button
151
- class="MuiButtonBase-root MuiIconButton-root MuiIconButton-sizeSmall css-1m9x3cr-MuiButtonBase-root-MuiIconButton-root-menuIcon"
152
- tabindex="0"
153
- type="button"
154
- >
155
- <svg
156
- aria-hidden="true"
157
- class="MuiSvgIcon-root MuiSvgIcon-fontSizeMedium css-havevq-MuiSvgIcon-root"
158
- focusable="false"
159
- viewBox="0 0 24 24"
160
- >
161
- <path
162
- d="M20 5V4c0-.55-.45-1-1-1h-2c-.55 0-1 .45-1 1v1h-1v4c0 .55.45 1 1 1h1v7c0 1.1-.9 2-2 2s-2-.9-2-2V7c0-2.21-1.79-4-4-4S5 4.79 5 7v7H4c-.55 0-1 .45-1 1v4h1v1c0 .55.45 1 1 1h2c.55 0 1-.45 1-1v-1h1v-4c0-.55-.45-1-1-1H7V7c0-1.1.9-2 2-2s2 .9 2 2v10c0 2.21 1.79 4 4 4s4-1.79 4-4v-7h1c.55 0 1-.45 1-1V5h-1z"
163
- />
164
- </svg>
165
- <span
166
- class="MuiTouchRipple-root css-8je8zh-MuiTouchRipple-root"
167
- />
168
- </button>
169
141
  <div
170
142
  class="MuiFormControl-root MuiFormControl-marginDense MuiFormControl-fullWidth MuiTextField-root css-rlnh8o-MuiFormControl-root-MuiTextField-root-searchBox"
171
143
  >
@@ -213,6 +185,16 @@ exports[`renders with a couple of uncategorized tracks 1`] = `
213
185
  </div>
214
186
  </div>
215
187
  </div>
188
+ <button
189
+ class="MuiButtonBase-root MuiButton-root MuiButton-text MuiButton-textPrimary MuiButton-sizeSmall MuiButton-textSizeSmall MuiButton-root MuiButton-text MuiButton-textPrimary MuiButton-sizeSmall MuiButton-textSizeSmall css-1c8zr45-MuiButtonBase-root-MuiButton-root-menuIcon"
190
+ tabindex="0"
191
+ type="button"
192
+ >
193
+ Open faceted selector
194
+ <span
195
+ class="MuiTouchRipple-root css-8je8zh-MuiTouchRipple-root"
196
+ />
197
+ </button>
216
198
  </div>
217
199
  </div>
218
200
  `;
@@ -0,0 +1,138 @@
1
+ import React, { useState } from 'react'
2
+ import {
3
+ Typography,
4
+ FormControl,
5
+ Select,
6
+ IconButton,
7
+ Tooltip,
8
+ } from '@mui/material'
9
+ import { makeStyles } from 'tss-react/mui'
10
+
11
+ // icon
12
+ import ClearIcon from '@mui/icons-material/Clear'
13
+ import MinimizeIcon from '@mui/icons-material/Minimize'
14
+ import AddIcon from '@mui/icons-material/Add'
15
+
16
+ const useStyles = makeStyles()(theme => ({
17
+ facet: {
18
+ margin: 0,
19
+ marginLeft: theme.spacing(2),
20
+ },
21
+ select: {
22
+ marginBottom: theme.spacing(2),
23
+ },
24
+ }))
25
+
26
+ function FacetFilter({
27
+ column,
28
+ vals,
29
+ width,
30
+ dispatch,
31
+ filters,
32
+ }: {
33
+ column: { field: string }
34
+ vals: [string, number][]
35
+ width: number
36
+ dispatch: (arg: { key: string; val: string[] }) => void
37
+ filters: Record<string, string[]>
38
+ }) {
39
+ const { classes } = useStyles()
40
+ const [visible, setVisible] = useState(true)
41
+ return (
42
+ <FormControl key={column.field} className={classes.facet} style={{ width }}>
43
+ <div style={{ display: 'flex' }}>
44
+ <Typography>{column.field}</Typography>
45
+ <Tooltip title="Clear selection on this facet filter">
46
+ <IconButton
47
+ onClick={() => {
48
+ dispatch({ key: column.field, val: [] })
49
+ }}
50
+ size="small"
51
+ >
52
+ <ClearIcon />
53
+ </IconButton>
54
+ </Tooltip>
55
+ <Tooltip title="Minimize/expand this facet filter">
56
+ <IconButton onClick={() => setVisible(!visible)} size="small">
57
+ {visible ? <MinimizeIcon /> : <AddIcon />}
58
+ </IconButton>
59
+ </Tooltip>
60
+ </div>
61
+ {visible ? (
62
+ <Select
63
+ multiple
64
+ native
65
+ className={classes.select}
66
+ value={filters[column.field]}
67
+ onChange={event => {
68
+ // @ts-ignore
69
+ const { options } = event.target
70
+ const val: string[] = []
71
+ const len = options.length
72
+ for (let i = 0; i < len; i++) {
73
+ if (options[i].selected) {
74
+ val.push(options[i].value)
75
+ }
76
+ }
77
+ dispatch({ key: column.field, val })
78
+ }}
79
+ >
80
+ {vals
81
+ .sort((a, b) => a[0].localeCompare(b[0]))
82
+ .map(([name, count]) => (
83
+ <option key={name} value={name}>
84
+ {name} ({count})
85
+ </option>
86
+ ))}
87
+ </Select>
88
+ ) : null}
89
+ </FormControl>
90
+ )
91
+ }
92
+
93
+ export default function FacetFilters({
94
+ rows,
95
+ columns,
96
+ dispatch,
97
+ filters,
98
+ width,
99
+ }: {
100
+ rows: Record<string, unknown>[]
101
+ filters: Record<string, string[]>
102
+ columns: { field: string }[]
103
+ dispatch: (arg: { key: string; val: string[] }) => void
104
+ width: number
105
+ }) {
106
+ const facets = columns.slice(1)
107
+ const uniqs = facets.map(() => new Map<string, number>())
108
+ rows.forEach(row => {
109
+ facets.forEach((column, index) => {
110
+ const elt = uniqs[index]
111
+ const key = `${row[column.field] || ''}`
112
+ const val = elt.get(key)
113
+ // we don't allow filtering on empty yet
114
+ if (key) {
115
+ if (val !== undefined) {
116
+ elt.set(key, val + 1)
117
+ } else {
118
+ elt.set(key, 1)
119
+ }
120
+ }
121
+ })
122
+ })
123
+
124
+ return (
125
+ <div>
126
+ {facets.map((column, index) => (
127
+ <FacetFilter
128
+ key={column.field}
129
+ vals={Array.from(uniqs[index])}
130
+ column={column}
131
+ width={width}
132
+ dispatch={dispatch}
133
+ filters={filters}
134
+ />
135
+ ))}
136
+ </div>
137
+ )
138
+ }
@@ -0,0 +1,29 @@
1
+ import React from 'react'
2
+ import { DialogContent } from '@mui/material'
3
+ import { Dialog } from '@jbrowse/core/ui'
4
+ import { observer } from 'mobx-react'
5
+
6
+ // locals
7
+ import { HierarchicalTrackSelectorModel } from '../../model'
8
+ import FacetedSelector from './FacetedSelector'
9
+
10
+ function FacetedDlg(props: {
11
+ handleClose: () => void
12
+ model: HierarchicalTrackSelectorModel
13
+ }) {
14
+ const { handleClose } = props
15
+ return (
16
+ <Dialog
17
+ open
18
+ onClose={handleClose}
19
+ maxWidth="xl"
20
+ title="Faceted track selector"
21
+ >
22
+ <DialogContent>
23
+ <FacetedSelector {...props} />
24
+ </DialogContent>
25
+ </Dialog>
26
+ )
27
+ }
28
+
29
+ export default observer(FacetedDlg)