@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
@@ -0,0 +1,88 @@
1
+ import React, { Suspense, lazy, useState } from 'react'
2
+ import { Button, IconButton, InputAdornment, TextField } from '@mui/material'
3
+ import { makeStyles } from 'tss-react/mui'
4
+ import { observer } from 'mobx-react'
5
+
6
+ // icons
7
+ import ClearIcon from '@mui/icons-material/Clear'
8
+
9
+ // locals
10
+ import { HierarchicalTrackSelectorModel } from '../../model'
11
+ import HamburgerMenu from './HamburgerMenu'
12
+ import ShoppingCart from '../ShoppingCart'
13
+
14
+ // lazies
15
+ const FacetedDialog = lazy(() => import('../faceted/FacetedDialog'))
16
+
17
+ const useStyles = makeStyles()(theme => ({
18
+ searchBox: {
19
+ margin: theme.spacing(2),
20
+ },
21
+ menuIcon: {
22
+ marginRight: theme.spacing(1),
23
+ marginBottom: 0,
24
+ },
25
+ }))
26
+
27
+ function HierarchicalTrackSelectorHeader({
28
+ model,
29
+ setHeaderHeight,
30
+ setAssemblyIdx,
31
+ }: {
32
+ model: HierarchicalTrackSelectorModel
33
+ setHeaderHeight: (n: number) => void
34
+ setAssemblyIdx: (n: number) => void
35
+ }) {
36
+ const { classes } = useStyles()
37
+ const [facetedOpen, setFacetedOpen] = useState(false)
38
+ const { filterText } = model
39
+
40
+ return (
41
+ <div
42
+ ref={ref => setHeaderHeight(ref?.getBoundingClientRect().height || 0)}
43
+ data-testid="hierarchical_track_selector"
44
+ >
45
+ <div style={{ display: 'flex' }}>
46
+ <HamburgerMenu model={model} setAssemblyIdx={setAssemblyIdx} />
47
+ <ShoppingCart model={model} />
48
+
49
+ <TextField
50
+ className={classes.searchBox}
51
+ label="Filter tracks"
52
+ value={filterText}
53
+ onChange={event => model.setFilterText(event.target.value)}
54
+ fullWidth
55
+ InputProps={{
56
+ endAdornment: (
57
+ <InputAdornment position="end">
58
+ <IconButton
59
+ color="secondary"
60
+ onClick={() => model.clearFilterText()}
61
+ >
62
+ <ClearIcon />
63
+ </IconButton>
64
+ </InputAdornment>
65
+ ),
66
+ }}
67
+ />
68
+ <Button
69
+ className={classes.menuIcon}
70
+ onClick={() => setFacetedOpen(true)}
71
+ >
72
+ Open faceted selector
73
+ </Button>
74
+ </div>
75
+
76
+ <Suspense fallback={<div />}>
77
+ {facetedOpen ? (
78
+ <FacetedDialog
79
+ handleClose={() => setFacetedOpen(false)}
80
+ model={model}
81
+ />
82
+ ) : null}
83
+ </Suspense>
84
+ </div>
85
+ )
86
+ }
87
+
88
+ export default observer(HierarchicalTrackSelectorHeader)
@@ -0,0 +1,101 @@
1
+ import React, { useCallback, useMemo, useRef, useEffect } from 'react'
2
+ import { observer } from 'mobx-react'
3
+ import { VariableSizeTree } from 'react-vtree'
4
+ import { getSession } from '@jbrowse/core/util'
5
+ // locals
6
+ import { TreeNode, HierarchicalTrackSelectorModel } from '../../model'
7
+ import Node from './TrackListNode'
8
+
9
+ function getNodeData(
10
+ node: TreeNode,
11
+ nestingLevel: number,
12
+ extra: Record<string, unknown>,
13
+ selection: Record<string, unknown>,
14
+ ) {
15
+ const isLeaf = !!node.conf
16
+ const selected = !!selection[node.id]
17
+ return {
18
+ data: {
19
+ defaultHeight: isLeaf ? 22 : 40,
20
+ isLeaf,
21
+ isOpenByDefault: true,
22
+ nestingLevel,
23
+ selected,
24
+ ...node,
25
+ ...extra,
26
+ },
27
+ nestingLevel,
28
+ node,
29
+ }
30
+ }
31
+
32
+ type NodeData = ReturnType<typeof getNodeData>
33
+
34
+ // this is the main tree component for the hierarchical track selector in note:
35
+ // in jbrowse-web the toolbar is position="sticky" which means the autosizer
36
+ // includes the height of the toolbar, so we subtract the given offsets
37
+ export default observer(function HierarchicalTree({
38
+ height,
39
+ tree,
40
+ model,
41
+ }: {
42
+ height: number
43
+ tree: TreeNode
44
+ model: HierarchicalTrackSelectorModel
45
+ }) {
46
+ const { filterText, selection, view } = model
47
+ const treeRef = useRef<NodeData>(null)
48
+ const session = getSession(model)
49
+ const { drawerPosition } = session
50
+ const obj = useMemo(
51
+ () => Object.fromEntries(selection.map(s => [s.trackId, s])),
52
+ [selection],
53
+ )
54
+
55
+ const extra = useMemo(
56
+ () => ({
57
+ onChange: (trackId: string) => view.toggleTrack(trackId),
58
+ toggleCollapse: (pathName: string) => model.toggleCategory(pathName),
59
+ tree,
60
+ model,
61
+ drawerPosition,
62
+ }),
63
+ [view, model, drawerPosition, tree],
64
+ )
65
+ const treeWalker = useCallback(
66
+ function* treeWalker() {
67
+ for (let i = 0; i < tree.children.length; i++) {
68
+ const r = tree.children[i]
69
+ yield getNodeData(r, 0, extra, obj)
70
+ }
71
+
72
+ while (true) {
73
+ // @ts-ignore
74
+ const parentMeta = yield
75
+
76
+ for (let i = 0; i < parentMeta.node.children.length; i++) {
77
+ const curr = parentMeta.node.children[i]
78
+ yield getNodeData(curr, parentMeta.nestingLevel + 1, extra, obj)
79
+ }
80
+ }
81
+ },
82
+ [tree, extra, obj],
83
+ )
84
+
85
+ useEffect(() => {
86
+ // @ts-ignore
87
+ treeRef.current.recomputeTree({
88
+ refreshNodes: true,
89
+ useDefaultHeight: true,
90
+ })
91
+ }, [tree, filterText])
92
+ return (
93
+ <>
94
+ {/* @ts-ignore */}
95
+ <VariableSizeTree ref={treeRef} treeWalker={treeWalker} height={height}>
96
+ {/* @ts-ignore */}
97
+ {Node}
98
+ </VariableSizeTree>
99
+ </>
100
+ )
101
+ })
@@ -0,0 +1,92 @@
1
+ import React, { useState } from 'react'
2
+ import { IconButton, Typography } from '@mui/material'
3
+ import { makeStyles } from 'tss-react/mui'
4
+ import JBrowseMenu from '@jbrowse/core/ui/Menu'
5
+
6
+ // icons
7
+ import ArrowDropDownIcon from '@mui/icons-material/ArrowDropDown'
8
+ import ArrowRightIcon from '@mui/icons-material/ArrowRight'
9
+ import MoreHorizIcon from '@mui/icons-material/MoreHoriz'
10
+
11
+ // locals
12
+ import { getAllChildren, treeToMap, NodeData } from '../util'
13
+
14
+ const useStyles = makeStyles()(theme => ({
15
+ contrastColor: {
16
+ color: theme.palette.secondary.contrastText,
17
+ },
18
+
19
+ // margin:auto 0 to center text vertically
20
+ accordionText: {
21
+ margin: 'auto 0',
22
+ // width 100 so you can click anywhere on the category bar
23
+ width: '100%',
24
+ },
25
+ }))
26
+
27
+ export default function Category({
28
+ isOpen,
29
+ setOpen,
30
+ data,
31
+ }: {
32
+ isOpen: boolean
33
+ setOpen: (arg: boolean) => void
34
+ data: NodeData
35
+ }) {
36
+ const { classes } = useStyles()
37
+ const [menuEl, setMenuEl] = useState<HTMLElement | null>(null)
38
+ const { name, model, id, tree, toggleCollapse } = data
39
+
40
+ return (
41
+ <div
42
+ className={classes.accordionText}
43
+ onClick={() => {
44
+ if (!menuEl) {
45
+ toggleCollapse(id)
46
+ setOpen(!isOpen)
47
+ }
48
+ }}
49
+ >
50
+ <Typography>
51
+ {isOpen ? <ArrowDropDownIcon /> : <ArrowRightIcon />}
52
+ {name}
53
+ <IconButton
54
+ onClick={event => {
55
+ setMenuEl(event.currentTarget)
56
+ event.stopPropagation()
57
+ }}
58
+ className={classes.contrastColor}
59
+ >
60
+ <MoreHorizIcon />
61
+ </IconButton>
62
+ </Typography>
63
+ {menuEl ? (
64
+ <JBrowseMenu
65
+ anchorEl={menuEl}
66
+ menuItems={[
67
+ {
68
+ label: 'Add to selection',
69
+ onClick: () => {
70
+ const r = treeToMap(tree).get(id)
71
+ model.addToSelection(getAllChildren(r))
72
+ },
73
+ },
74
+ {
75
+ label: 'Remove from selection',
76
+ onClick: () => {
77
+ const r = treeToMap(tree).get(id)
78
+ model.removeFromSelection(getAllChildren(r))
79
+ },
80
+ },
81
+ ]}
82
+ onMenuItemClick={(_event, callback) => {
83
+ callback()
84
+ setMenuEl(null)
85
+ }}
86
+ open={Boolean(menuEl)}
87
+ onClose={() => setMenuEl(null)}
88
+ />
89
+ ) : null}
90
+ </div>
91
+ )
92
+ }
@@ -0,0 +1,107 @@
1
+ import React, { useState } from 'react'
2
+ import { Checkbox, FormControlLabel, IconButton, Tooltip } from '@mui/material'
3
+ import { makeStyles } from 'tss-react/mui'
4
+ import JBrowseMenu from '@jbrowse/core/ui/Menu'
5
+ import { getSession } from '@jbrowse/core/util'
6
+ import {
7
+ AnyConfigurationModel,
8
+ readConfObject,
9
+ } from '@jbrowse/core/configuration'
10
+
11
+ // icons
12
+ import MoreHorizIcon from '@mui/icons-material/MoreHoriz'
13
+
14
+ // locals
15
+ import { isUnsupported, NodeData } from '../util'
16
+ import { SanitizedHTML } from '@jbrowse/core/ui'
17
+
18
+ const useStyles = makeStyles()({
19
+ compactCheckbox: {
20
+ padding: 0,
21
+ },
22
+
23
+ checkboxLabel: {
24
+ marginRight: 0,
25
+ '&:hover': {
26
+ backgroundColor: '#eee',
27
+ },
28
+ },
29
+ })
30
+
31
+ export interface InfoArgs {
32
+ target: HTMLElement
33
+ id: string
34
+ conf: AnyConfigurationModel
35
+ }
36
+
37
+ export default function TrackLabel({ data }: { data: NodeData }) {
38
+ const { classes } = useStyles()
39
+ const { checked, conf, model, drawerPosition, id, name, onChange, selected } =
40
+ data
41
+ const [info, setInfo] = useState<InfoArgs>()
42
+ const description = (conf && readConfObject(conf, ['description'])) || ''
43
+ return (
44
+ <>
45
+ <Tooltip
46
+ title={description + (selected ? ' (in selection)' : '')}
47
+ placement={drawerPosition === 'left' ? 'right' : 'left'}
48
+ >
49
+ <FormControlLabel
50
+ className={classes.checkboxLabel}
51
+ control={
52
+ <Checkbox
53
+ className={classes.compactCheckbox}
54
+ checked={checked}
55
+ onChange={() => onChange(id)}
56
+ disabled={isUnsupported(name)}
57
+ inputProps={{
58
+ // @ts-ignore
59
+ 'data-testid': `htsTrackEntry-${id}`,
60
+ }}
61
+ />
62
+ }
63
+ label={
64
+ <div style={{ background: selected ? '#cccc' : undefined }}>
65
+ <SanitizedHTML html={name} />
66
+ </div>
67
+ }
68
+ />
69
+ </Tooltip>
70
+ <IconButton
71
+ onClick={e => setInfo({ target: e.currentTarget, id, conf })}
72
+ style={{ padding: 0 }}
73
+ color="secondary"
74
+ data-testid={`htsTrackEntryMenu-${id}`}
75
+ >
76
+ <MoreHorizIcon />
77
+ </IconButton>
78
+
79
+ {info ? (
80
+ <JBrowseMenu
81
+ anchorEl={info?.target}
82
+ menuItems={[
83
+ ...(getSession(model).getTrackActionMenuItems?.(info.conf) || []),
84
+ {
85
+ label: 'Add to selection',
86
+ onClick: () => model.addToSelection([info.conf]),
87
+ },
88
+ ...(selected
89
+ ? [
90
+ {
91
+ label: 'Remove from selection',
92
+ onClick: () => model.removeFromSelection([info.conf]),
93
+ },
94
+ ]
95
+ : []),
96
+ ]}
97
+ onMenuItemClick={(_event, callback) => {
98
+ callback()
99
+ setInfo(undefined)
100
+ }}
101
+ open={Boolean(info)}
102
+ onClose={() => setInfo(undefined)}
103
+ />
104
+ ) : null}
105
+ </>
106
+ )
107
+ }
@@ -0,0 +1,84 @@
1
+ import React from 'react'
2
+ import { makeStyles } from 'tss-react/mui'
3
+
4
+ // locals
5
+ import Category from './TrackCategory'
6
+ import TrackLabel from './TrackLabel'
7
+ import { NodeData } from '../util'
8
+
9
+ const useStyles = makeStyles()(theme => ({
10
+ // this accordionBase element's small padding is used to give a margin to
11
+ // accordionColor it a "margin" because the virtualized elements can't really
12
+ // use margin in a conventional way (it doesn't affect layout)
13
+ accordionBase: {
14
+ display: 'flex',
15
+ },
16
+
17
+ accordionCard: {
18
+ padding: 3,
19
+ cursor: 'pointer',
20
+ display: 'flex',
21
+ },
22
+
23
+ nestingLevelMarker: {
24
+ position: 'absolute',
25
+ borderLeft: '1.5px solid #555',
26
+ },
27
+ // accordionColor set's display:flex so that the child accordionText use
28
+ // vertically centered text
29
+ accordionColor: {
30
+ background: theme.palette.tertiary.main,
31
+ color: theme.palette.tertiary.contrastText,
32
+ width: '100%',
33
+ display: 'flex',
34
+ paddingLeft: 5,
35
+ },
36
+ }))
37
+
38
+ // An individual node in the track selector. Note: manually sets cursor:
39
+ // pointer improves usability for what can be clicked
40
+ export default function Node({
41
+ data,
42
+ isOpen,
43
+ style,
44
+ setOpen,
45
+ }: {
46
+ data: NodeData
47
+ isOpen: boolean
48
+ style?: { height: number }
49
+ setOpen: (arg: boolean) => void
50
+ }) {
51
+ const { isLeaf, nestingLevel } = data
52
+
53
+ const { classes } = useStyles()
54
+ const width = 10
55
+ const marginLeft = nestingLevel * width + (isLeaf ? width : 0)
56
+
57
+ return (
58
+ <div style={style} className={!isLeaf ? classes.accordionBase : undefined}>
59
+ {new Array(nestingLevel).fill(0).map((_, idx) => (
60
+ <div
61
+ key={`mark-${idx}`}
62
+ style={{ left: idx * width + 4, height: style?.height }}
63
+ className={classes.nestingLevelMarker}
64
+ />
65
+ ))}
66
+ <div
67
+ className={!isLeaf ? classes.accordionCard : undefined}
68
+ style={{
69
+ marginLeft,
70
+ whiteSpace: 'nowrap',
71
+ width: '100%',
72
+ }}
73
+ >
74
+ <div className={!isLeaf ? classes.accordionColor : undefined}>
75
+ {!isLeaf ? (
76
+ <Category isOpen={isOpen} data={data} setOpen={setOpen} />
77
+ ) : (
78
+ <TrackLabel data={data} />
79
+ )}
80
+ </div>
81
+ </div>
82
+ </div>
83
+ )
84
+ }
@@ -1,5 +1,20 @@
1
1
  import { AnyConfigurationModel } from '@jbrowse/core/configuration'
2
- import { TreeNode } from '../model'
2
+ import { HierarchicalTrackSelectorModel, TreeNode } from '../model'
3
+
4
+ export interface NodeData {
5
+ nestingLevel: number
6
+ checked: boolean
7
+ conf: AnyConfigurationModel
8
+ drawerPosition: unknown
9
+ id: string
10
+ isLeaf: boolean
11
+ name: string
12
+ onChange: Function
13
+ toggleCollapse: (arg: string) => void
14
+ tree: TreeNode
15
+ selected: boolean
16
+ model: HierarchicalTrackSelectorModel
17
+ }
3
18
 
4
19
  export function getAllChildren(subtree?: TreeNode): AnyConfigurationModel[] {
5
20
  // @ts-ignore
@@ -9,3 +24,18 @@ export function getAllChildren(subtree?: TreeNode): AnyConfigurationModel[] {
9
24
  ) || []
10
25
  ).flat(Infinity)
11
26
  }
27
+
28
+ export function treeToMap(tree: TreeNode, map = new Map<string, TreeNode>()) {
29
+ if (tree.id && tree.children.length) {
30
+ map.set(tree.id, tree)
31
+ }
32
+ for (let i = 0; i < tree.children.length; i++) {
33
+ const node = tree.children[i]
34
+ treeToMap(node, map)
35
+ }
36
+ return map
37
+ }
38
+
39
+ export function isUnsupported(name = '') {
40
+ return name.endsWith('(Unsupported)') || name.endsWith('(Unknown)')
41
+ }
@@ -18,16 +18,16 @@ function hasAnyOverlap<T>(a1: T[] = [], a2: T[] = []) {
18
18
  return !!a1.find(value => a2.includes(value))
19
19
  }
20
20
 
21
- function passesFilter(
22
- filter: string,
23
- config: AnyConfigurationModel,
21
+ export function matches(
22
+ query: string,
23
+ conf: AnyConfigurationModel,
24
24
  session: AbstractSessionModel,
25
25
  ) {
26
- const categories = readConfObject(config, 'category') as string[] | undefined
27
- const filterLower = filter.toLowerCase()
26
+ const categories = readConfObject(conf, 'category') as string[] | undefined
27
+ const queryLower = query.toLowerCase()
28
28
  return (
29
- getTrackName(config, session).toLowerCase().includes(filterLower) ||
30
- !!categories?.filter(c => c.toLowerCase().includes(filterLower)).length
29
+ getTrackName(conf, session).toLowerCase().includes(queryLower) ||
30
+ !!categories?.filter(c => c.toLowerCase().includes(queryLower)).length
31
31
  )
32
32
  }
33
33
 
@@ -74,7 +74,7 @@ export function generateHierarchy(
74
74
  const session = getSession(model)
75
75
 
76
76
  trackConfigurations
77
- .filter(conf => passesFilter(filterText, conf, session))
77
+ .filter(conf => matches(filterText, conf, session))
78
78
  .forEach(conf => {
79
79
  // copy the categories since this array can be mutated downstream
80
80
  const categories = [...(readConfObject(conf, 'category') || [])]
@@ -131,15 +131,18 @@ export default function stateTreeFactory(pluginManager: PluginManager) {
131
131
  id: ElementId,
132
132
  type: types.literal('HierarchicalTrackSelectorWidget'),
133
133
  collapsed: types.map(types.boolean),
134
- filterText: '',
135
134
  view: types.safeReference(
136
135
  pluginManager.pluggableMstType('view', 'stateModel'),
137
136
  ),
138
137
  })
139
138
  .volatile(() => ({
140
139
  selection: [] as AnyConfigurationModel[],
140
+ filterText: '',
141
141
  }))
142
142
  .actions(self => ({
143
+ setSelection(elt: AnyConfigurationModel[]) {
144
+ self.selection = elt
145
+ },
143
146
  addToSelection(elt: AnyConfigurationModel[]) {
144
147
  self.selection = dedupe([...self.selection, ...elt], e => e.trackId)
145
148
  },
@@ -1 +0,0 @@
1
- {"version":3,"file":"CloseConnectionDialog.js","sourceRoot":"","sources":["../../../src/HierarchicalTrackSelectorWidget/components/CloseConnectionDialog.tsx"],"names":[],"mappings":";;;;;AAAA,kDAAyB;AACzB,4CASsB;AACtB,2CAAqC;AAErC,SAAS,qBAAqB,CAAC,EAC7B,SAAS,GAAG,EAAE,EACd,YAAY,GAQb;IACC,MAAM,EAAE,IAAI,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,GAAG,SAAS,CAAA;IACvE,OAAO,CACL,8BAAC,iBAAM,IAAC,IAAI;QACV,8BAAC,sBAAW;;YAAyB,IAAI;iBAAqB;QAC9D,8BAAC,wBAAa;YACX,oBAAoB,CAAC,CAAC,CAAC,CACtB;gBACE,8BAAC,4BAAiB,8CAEE;gBACpB,8BAAC,eAAI,QACF,MAAM,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAC1D,8BAAC,mBAAQ,IAAC,GAAG,EAAE,GAAG,IAAG,GAAG,KAAK,IAAI,GAAG,EAAE,CAAY,CACnD,CAAC,CACG,CACN,CACJ,CAAC,CAAC,CAAC,IAAI;YACR,8BAAC,4BAAiB,0DAEE,CACN;QAChB,8BAAC,wBAAa;YACZ,8BAAC,iBAAM,IAAC,OAAO,EAAE,GAAG,EAAE,CAAC,YAAY,EAAE,EAAE,KAAK,EAAC,SAAS,aAE7C;YACT,8BAAC,iBAAM,IACL,OAAO,EAAC,WAAW,EACnB,OAAO,EACL,SAAS;oBACP,CAAC,CAAC,GAAG,EAAE;wBACH,qBAAqB,aAArB,qBAAqB,uBAArB,qBAAqB,EAAI,CAAA;wBACzB,YAAY,EAAE,CAAA;oBAChB,CAAC;oBACH,CAAC,CAAC,GAAG,EAAE,GAAE,CAAC,EAEd,KAAK,EAAC,SAAS,SAGR,CACK,CACT,CACV,CAAA;AACH,CAAC;AAED,kBAAe,IAAA,qBAAQ,EAAC,qBAAqB,CAAC,CAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"DeleteConnectionDialog.js","sourceRoot":"","sources":["../../../src/HierarchicalTrackSelectorWidget/components/DeleteConnectionDialog.tsx"],"names":[],"mappings":";;;;;AAAA,kDAAyB;AACzB,4CAOsB;AACtB,2CAAqC;AAIrC,SAAS,sBAAsB,CAAC,EAC9B,mBAAmB,EACnB,OAAO,EACP,WAAW,GAKZ;IACC,MAAM,EAAE,cAAc,EAAE,IAAI,EAAE,GAAG,mBAAmB,CAAA;IACpD,OAAO,CACL,8BAAC,iBAAM,IAAC,IAAI;QACV,8BAAC,sBAAW;;YAA0B,IAAI;iBAAqB;QAC/D,8BAAC,wBAAa;YACZ,8BAAC,4BAAiB,2DAEE,CACN;QAChB,8BAAC,wBAAa;YACZ,8BAAC,iBAAM,IAAC,OAAO,EAAE,GAAG,EAAE,CAAC,WAAW,EAAE,EAAE,KAAK,EAAC,SAAS,aAE5C;YACT,8BAAC,iBAAM,IACL,OAAO,EAAC,WAAW,EACnB,KAAK,EAAC,SAAS,EACf,OAAO,EAAE,GAAG,EAAE;;oBACZ,IAAI,cAAc,EAAE;wBAClB,MAAA,OAAO,CAAC,gBAAgB,wDAAG,cAAc,CAAC,CAAA;qBAC3C;oBACD,WAAW,EAAE,CAAA;gBACf,CAAC,SAGM,CACK,CACT,CACV,CAAA;AACH,CAAC;AAED,kBAAe,IAAA,qBAAQ,EAAC,sBAAsB,CAAC,CAAA"}