@jbrowse/plugin-data-management 2.3.3 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (200) hide show
  1. package/dist/AddConnectionWidget/components/ConnectionTypeSelect.js +1 -1
  2. package/dist/AddConnectionWidget/components/ConnectionTypeSelect.js.map +1 -1
  3. package/dist/AddTrackWidget/components/DefaultAddTrackWorkflow.js +1 -4
  4. package/dist/AddTrackWidget/components/DefaultAddTrackWorkflow.js.map +1 -1
  5. package/dist/AddTrackWidget/components/TextIndexingConfig.js +2 -2
  6. package/dist/AddTrackWidget/components/TextIndexingConfig.js.map +1 -1
  7. package/dist/AddTrackWidget/components/TrackSourceSelect.js +1 -4
  8. package/dist/AddTrackWidget/components/TrackSourceSelect.js.map +1 -1
  9. package/dist/HierarchicalTrackSelectorWidget/components/HierarchicalFab.d.ts +6 -0
  10. package/dist/HierarchicalTrackSelectorWidget/components/HierarchicalFab.js +71 -0
  11. package/dist/HierarchicalTrackSelectorWidget/components/HierarchicalFab.js.map +1 -0
  12. package/dist/HierarchicalTrackSelectorWidget/components/HierarchicalTrackSelector.js +10 -104
  13. package/dist/HierarchicalTrackSelectorWidget/components/HierarchicalTrackSelector.js.map +1 -1
  14. package/dist/HierarchicalTrackSelectorWidget/components/ShoppingCart.d.ts +6 -0
  15. package/dist/HierarchicalTrackSelectorWidget/components/ShoppingCart.js +70 -0
  16. package/dist/HierarchicalTrackSelectorWidget/components/ShoppingCart.js.map +1 -0
  17. package/dist/HierarchicalTrackSelectorWidget/components/dialogs/CloseConnectionDialog.js.map +1 -0
  18. package/dist/HierarchicalTrackSelectorWidget/components/dialogs/DeleteConnectionDialog.js.map +1 -0
  19. package/dist/HierarchicalTrackSelectorWidget/components/dialogs/ManageConnectionsDialog.js.map +1 -0
  20. package/dist/HierarchicalTrackSelectorWidget/components/dialogs/ToggleConnectionsDialog.js.map +1 -0
  21. package/dist/HierarchicalTrackSelectorWidget/components/faceted/FacetFilters.d.ts +13 -0
  22. package/dist/HierarchicalTrackSelectorWidget/components/faceted/FacetFilters.js +99 -0
  23. package/dist/HierarchicalTrackSelectorWidget/components/faceted/FacetFilters.js.map +1 -0
  24. package/dist/HierarchicalTrackSelectorWidget/components/faceted/FacetedDialog.d.ts +8 -0
  25. package/dist/HierarchicalTrackSelectorWidget/components/faceted/FacetedDialog.js +18 -0
  26. package/dist/HierarchicalTrackSelectorWidget/components/faceted/FacetedDialog.js.map +1 -0
  27. package/dist/HierarchicalTrackSelectorWidget/components/faceted/FacetedHeader.d.ts +11 -0
  28. package/dist/HierarchicalTrackSelectorWidget/components/faceted/FacetedHeader.js +71 -0
  29. package/dist/HierarchicalTrackSelectorWidget/components/faceted/FacetedHeader.js.map +1 -0
  30. package/dist/HierarchicalTrackSelectorWidget/components/faceted/FacetedSelector.d.ts +12 -0
  31. package/dist/HierarchicalTrackSelectorWidget/components/faceted/FacetedSelector.js +211 -0
  32. package/dist/HierarchicalTrackSelectorWidget/components/faceted/FacetedSelector.js.map +1 -0
  33. package/dist/HierarchicalTrackSelectorWidget/components/faceted/util.d.ts +1 -0
  34. package/dist/HierarchicalTrackSelectorWidget/components/faceted/util.js +10 -0
  35. package/dist/HierarchicalTrackSelectorWidget/components/faceted/util.js.map +1 -0
  36. package/dist/HierarchicalTrackSelectorWidget/components/tree/HamburgerMenu.d.ts +7 -0
  37. package/dist/HierarchicalTrackSelectorWidget/components/tree/HamburgerMenu.js +136 -0
  38. package/dist/HierarchicalTrackSelectorWidget/components/tree/HamburgerMenu.js.map +1 -0
  39. package/dist/HierarchicalTrackSelectorWidget/components/{Header.d.ts → tree/HierarchicalHeader.d.ts} +2 -3
  40. package/dist/HierarchicalTrackSelectorWidget/components/tree/HierarchicalHeader.js +65 -0
  41. package/dist/HierarchicalTrackSelectorWidget/components/tree/HierarchicalHeader.js.map +1 -0
  42. package/dist/HierarchicalTrackSelectorWidget/components/tree/HierarchicalTree.d.ts +8 -0
  43. package/dist/HierarchicalTrackSelectorWidget/components/tree/HierarchicalTree.js +91 -0
  44. package/dist/HierarchicalTrackSelectorWidget/components/tree/HierarchicalTree.js.map +1 -0
  45. package/dist/HierarchicalTrackSelectorWidget/components/tree/TrackCategory.d.ts +7 -0
  46. package/dist/HierarchicalTrackSelectorWidget/components/tree/TrackCategory.js +89 -0
  47. package/dist/HierarchicalTrackSelectorWidget/components/tree/TrackCategory.js.map +1 -0
  48. package/dist/HierarchicalTrackSelectorWidget/components/tree/TrackLabel.d.ts +11 -0
  49. package/dist/HierarchicalTrackSelectorWidget/components/tree/TrackLabel.js +86 -0
  50. package/dist/HierarchicalTrackSelectorWidget/components/tree/TrackLabel.js.map +1 -0
  51. package/dist/HierarchicalTrackSelectorWidget/components/tree/TrackListNode.d.ts +10 -0
  52. package/dist/HierarchicalTrackSelectorWidget/components/tree/TrackListNode.js +54 -0
  53. package/dist/HierarchicalTrackSelectorWidget/components/tree/TrackListNode.js.map +1 -0
  54. package/dist/HierarchicalTrackSelectorWidget/components/util.d.ts +17 -1
  55. package/dist/HierarchicalTrackSelectorWidget/components/util.js +16 -1
  56. package/dist/HierarchicalTrackSelectorWidget/components/util.js.map +1 -1
  57. package/dist/HierarchicalTrackSelectorWidget/model.d.ts +4 -1
  58. package/dist/HierarchicalTrackSelectorWidget/model.js +12 -8
  59. package/dist/HierarchicalTrackSelectorWidget/model.js.map +1 -1
  60. package/dist/PluginStoreWidget/components/InstalledPluginsList.js.map +1 -1
  61. package/dist/PluginStoreWidget/components/PluginCard.d.ts +2 -3
  62. package/dist/PluginStoreWidget/components/PluginCard.js +5 -6
  63. package/dist/PluginStoreWidget/components/PluginCard.js.map +1 -1
  64. package/dist/PluginStoreWidget/components/PluginStoreWidget.js +3 -3
  65. package/dist/PluginStoreWidget/components/PluginStoreWidget.js.map +1 -1
  66. package/dist/ucsc-trackhub/ucscTrackHub.js.map +1 -1
  67. package/esm/AddConnectionWidget/components/ConnectionTypeSelect.js +1 -1
  68. package/esm/AddConnectionWidget/components/ConnectionTypeSelect.js.map +1 -1
  69. package/esm/AddTrackWidget/components/DefaultAddTrackWorkflow.js +1 -4
  70. package/esm/AddTrackWidget/components/DefaultAddTrackWorkflow.js.map +1 -1
  71. package/esm/AddTrackWidget/components/TextIndexingConfig.js +2 -2
  72. package/esm/AddTrackWidget/components/TextIndexingConfig.js.map +1 -1
  73. package/esm/AddTrackWidget/components/TrackSourceSelect.js +1 -4
  74. package/esm/AddTrackWidget/components/TrackSourceSelect.js.map +1 -1
  75. package/esm/HierarchicalTrackSelectorWidget/components/HierarchicalFab.d.ts +6 -0
  76. package/esm/HierarchicalTrackSelectorWidget/components/HierarchicalFab.js +43 -0
  77. package/esm/HierarchicalTrackSelectorWidget/components/HierarchicalFab.js.map +1 -0
  78. package/esm/HierarchicalTrackSelectorWidget/components/HierarchicalTrackSelector.js +9 -103
  79. package/esm/HierarchicalTrackSelectorWidget/components/HierarchicalTrackSelector.js.map +1 -1
  80. package/esm/HierarchicalTrackSelectorWidget/components/ShoppingCart.d.ts +6 -0
  81. package/esm/HierarchicalTrackSelectorWidget/components/ShoppingCart.js +42 -0
  82. package/esm/HierarchicalTrackSelectorWidget/components/ShoppingCart.js.map +1 -0
  83. package/esm/HierarchicalTrackSelectorWidget/components/dialogs/CloseConnectionDialog.js.map +1 -0
  84. package/esm/HierarchicalTrackSelectorWidget/components/dialogs/DeleteConnectionDialog.js.map +1 -0
  85. package/esm/HierarchicalTrackSelectorWidget/components/dialogs/ManageConnectionsDialog.js.map +1 -0
  86. package/esm/HierarchicalTrackSelectorWidget/components/dialogs/ToggleConnectionsDialog.js.map +1 -0
  87. package/esm/HierarchicalTrackSelectorWidget/components/faceted/FacetFilters.d.ts +13 -0
  88. package/esm/HierarchicalTrackSelectorWidget/components/faceted/FacetFilters.js +70 -0
  89. package/esm/HierarchicalTrackSelectorWidget/components/faceted/FacetFilters.js.map +1 -0
  90. package/esm/HierarchicalTrackSelectorWidget/components/faceted/FacetedDialog.d.ts +8 -0
  91. package/esm/HierarchicalTrackSelectorWidget/components/faceted/FacetedDialog.js +13 -0
  92. package/esm/HierarchicalTrackSelectorWidget/components/faceted/FacetedDialog.js.map +1 -0
  93. package/esm/HierarchicalTrackSelectorWidget/components/faceted/FacetedHeader.d.ts +11 -0
  94. package/esm/HierarchicalTrackSelectorWidget/components/faceted/FacetedHeader.js +42 -0
  95. package/esm/HierarchicalTrackSelectorWidget/components/faceted/FacetedHeader.js.map +1 -0
  96. package/esm/HierarchicalTrackSelectorWidget/components/faceted/FacetedSelector.d.ts +12 -0
  97. package/esm/HierarchicalTrackSelectorWidget/components/faceted/FacetedSelector.js +183 -0
  98. package/esm/HierarchicalTrackSelectorWidget/components/faceted/FacetedSelector.js.map +1 -0
  99. package/esm/HierarchicalTrackSelectorWidget/components/faceted/util.d.ts +1 -0
  100. package/esm/HierarchicalTrackSelectorWidget/components/faceted/util.js +6 -0
  101. package/esm/HierarchicalTrackSelectorWidget/components/faceted/util.js.map +1 -0
  102. package/esm/HierarchicalTrackSelectorWidget/components/tree/HamburgerMenu.d.ts +7 -0
  103. package/esm/HierarchicalTrackSelectorWidget/components/tree/HamburgerMenu.js +108 -0
  104. package/esm/HierarchicalTrackSelectorWidget/components/tree/HamburgerMenu.js.map +1 -0
  105. package/esm/HierarchicalTrackSelectorWidget/components/{Header.d.ts → tree/HierarchicalHeader.d.ts} +2 -3
  106. package/esm/HierarchicalTrackSelectorWidget/components/tree/HierarchicalHeader.js +37 -0
  107. package/esm/HierarchicalTrackSelectorWidget/components/tree/HierarchicalHeader.js.map +1 -0
  108. package/esm/HierarchicalTrackSelectorWidget/components/tree/HierarchicalTree.d.ts +8 -0
  109. package/esm/HierarchicalTrackSelectorWidget/components/tree/HierarchicalTree.js +63 -0
  110. package/esm/HierarchicalTrackSelectorWidget/components/tree/HierarchicalTree.js.map +1 -0
  111. package/esm/HierarchicalTrackSelectorWidget/components/tree/TrackCategory.d.ts +7 -0
  112. package/esm/HierarchicalTrackSelectorWidget/components/tree/TrackCategory.js +60 -0
  113. package/esm/HierarchicalTrackSelectorWidget/components/tree/TrackCategory.js.map +1 -0
  114. package/esm/HierarchicalTrackSelectorWidget/components/tree/TrackLabel.d.ts +11 -0
  115. package/esm/HierarchicalTrackSelectorWidget/components/tree/TrackLabel.js +57 -0
  116. package/esm/HierarchicalTrackSelectorWidget/components/tree/TrackLabel.js.map +1 -0
  117. package/esm/HierarchicalTrackSelectorWidget/components/tree/TrackListNode.d.ts +10 -0
  118. package/esm/HierarchicalTrackSelectorWidget/components/tree/TrackListNode.js +48 -0
  119. package/esm/HierarchicalTrackSelectorWidget/components/tree/TrackListNode.js.map +1 -0
  120. package/esm/HierarchicalTrackSelectorWidget/components/util.d.ts +17 -1
  121. package/esm/HierarchicalTrackSelectorWidget/components/util.js +13 -0
  122. package/esm/HierarchicalTrackSelectorWidget/components/util.js.map +1 -1
  123. package/esm/HierarchicalTrackSelectorWidget/model.d.ts +4 -1
  124. package/esm/HierarchicalTrackSelectorWidget/model.js +10 -7
  125. package/esm/HierarchicalTrackSelectorWidget/model.js.map +1 -1
  126. package/esm/PluginStoreWidget/components/InstalledPluginsList.js.map +1 -1
  127. package/esm/PluginStoreWidget/components/PluginCard.d.ts +2 -3
  128. package/esm/PluginStoreWidget/components/PluginCard.js +5 -6
  129. package/esm/PluginStoreWidget/components/PluginCard.js.map +1 -1
  130. package/esm/PluginStoreWidget/components/PluginStoreWidget.js +3 -3
  131. package/esm/PluginStoreWidget/components/PluginStoreWidget.js.map +1 -1
  132. package/esm/ucsc-trackhub/ucscTrackHub.js.map +1 -1
  133. package/package.json +3 -2
  134. package/src/AddConnectionWidget/components/ConnectionTypeSelect.tsx +0 -1
  135. package/src/AddConnectionWidget/components/__snapshots__/AddConnectionWidget.test.tsx.snap +1 -1
  136. package/src/AddTrackWidget/components/DefaultAddTrackWorkflow.tsx +1 -4
  137. package/src/AddTrackWidget/components/TextIndexingConfig.tsx +0 -2
  138. package/src/AddTrackWidget/components/TrackSourceSelect.tsx +3 -5
  139. package/src/HierarchicalTrackSelectorWidget/components/HierarchicalFab.tsx +94 -0
  140. package/src/HierarchicalTrackSelectorWidget/components/HierarchicalTrackSelector.tsx +47 -228
  141. package/src/HierarchicalTrackSelectorWidget/components/ShoppingCart.tsx +73 -0
  142. package/src/HierarchicalTrackSelectorWidget/components/__snapshots__/HierarchicalTrackSelector.test.tsx.snap +24 -42
  143. package/src/HierarchicalTrackSelectorWidget/components/faceted/FacetFilters.tsx +138 -0
  144. package/src/HierarchicalTrackSelectorWidget/components/faceted/FacetedDialog.tsx +29 -0
  145. package/src/HierarchicalTrackSelectorWidget/components/faceted/FacetedHeader.tsx +86 -0
  146. package/src/HierarchicalTrackSelectorWidget/components/faceted/FacetedSelector.tsx +339 -0
  147. package/src/HierarchicalTrackSelectorWidget/components/faceted/util.ts +5 -0
  148. package/src/HierarchicalTrackSelectorWidget/components/tree/HamburgerMenu.tsx +197 -0
  149. package/src/HierarchicalTrackSelectorWidget/components/tree/HierarchicalHeader.tsx +85 -0
  150. package/src/HierarchicalTrackSelectorWidget/components/tree/HierarchicalTree.tsx +101 -0
  151. package/src/HierarchicalTrackSelectorWidget/components/tree/TrackCategory.tsx +92 -0
  152. package/src/HierarchicalTrackSelectorWidget/components/tree/TrackLabel.tsx +106 -0
  153. package/src/HierarchicalTrackSelectorWidget/components/tree/TrackListNode.tsx +84 -0
  154. package/src/HierarchicalTrackSelectorWidget/components/util.ts +31 -1
  155. package/src/HierarchicalTrackSelectorWidget/model.ts +12 -9
  156. package/src/PluginStoreWidget/components/InstalledPluginsList.tsx +1 -1
  157. package/src/PluginStoreWidget/components/PluginCard.tsx +6 -7
  158. package/src/PluginStoreWidget/components/PluginStoreWidget.tsx +3 -7
  159. package/src/PluginStoreWidget/components/__snapshots__/PluginStoreWidget.test.tsx.snap +1 -1
  160. package/src/ucsc-trackhub/ucscTrackHub.ts +1 -1
  161. package/dist/HierarchicalTrackSelectorWidget/components/CloseConnectionDialog.js.map +0 -1
  162. package/dist/HierarchicalTrackSelectorWidget/components/DeleteConnectionDialog.js.map +0 -1
  163. package/dist/HierarchicalTrackSelectorWidget/components/Header.js +0 -174
  164. package/dist/HierarchicalTrackSelectorWidget/components/Header.js.map +0 -1
  165. package/dist/HierarchicalTrackSelectorWidget/components/ManageConnectionsDialog.js.map +0 -1
  166. package/dist/HierarchicalTrackSelectorWidget/components/Node.d.ts +0 -29
  167. package/dist/HierarchicalTrackSelectorWidget/components/Node.js +0 -173
  168. package/dist/HierarchicalTrackSelectorWidget/components/Node.js.map +0 -1
  169. package/dist/HierarchicalTrackSelectorWidget/components/ToggleConnectionsDialog.js.map +0 -1
  170. package/esm/HierarchicalTrackSelectorWidget/components/CloseConnectionDialog.js.map +0 -1
  171. package/esm/HierarchicalTrackSelectorWidget/components/DeleteConnectionDialog.js.map +0 -1
  172. package/esm/HierarchicalTrackSelectorWidget/components/Header.js +0 -146
  173. package/esm/HierarchicalTrackSelectorWidget/components/Header.js.map +0 -1
  174. package/esm/HierarchicalTrackSelectorWidget/components/ManageConnectionsDialog.js.map +0 -1
  175. package/esm/HierarchicalTrackSelectorWidget/components/Node.d.ts +0 -29
  176. package/esm/HierarchicalTrackSelectorWidget/components/Node.js +0 -144
  177. package/esm/HierarchicalTrackSelectorWidget/components/Node.js.map +0 -1
  178. package/esm/HierarchicalTrackSelectorWidget/components/ToggleConnectionsDialog.js.map +0 -1
  179. package/src/HierarchicalTrackSelectorWidget/components/Header.tsx +0 -286
  180. package/src/HierarchicalTrackSelectorWidget/components/Node.tsx +0 -282
  181. /package/dist/HierarchicalTrackSelectorWidget/components/{CloseConnectionDialog.d.ts → dialogs/CloseConnectionDialog.d.ts} +0 -0
  182. /package/dist/HierarchicalTrackSelectorWidget/components/{CloseConnectionDialog.js → dialogs/CloseConnectionDialog.js} +0 -0
  183. /package/dist/HierarchicalTrackSelectorWidget/components/{DeleteConnectionDialog.d.ts → dialogs/DeleteConnectionDialog.d.ts} +0 -0
  184. /package/dist/HierarchicalTrackSelectorWidget/components/{DeleteConnectionDialog.js → dialogs/DeleteConnectionDialog.js} +0 -0
  185. /package/dist/HierarchicalTrackSelectorWidget/components/{ManageConnectionsDialog.d.ts → dialogs/ManageConnectionsDialog.d.ts} +0 -0
  186. /package/dist/HierarchicalTrackSelectorWidget/components/{ManageConnectionsDialog.js → dialogs/ManageConnectionsDialog.js} +0 -0
  187. /package/dist/HierarchicalTrackSelectorWidget/components/{ToggleConnectionsDialog.d.ts → dialogs/ToggleConnectionsDialog.d.ts} +0 -0
  188. /package/dist/HierarchicalTrackSelectorWidget/components/{ToggleConnectionsDialog.js → dialogs/ToggleConnectionsDialog.js} +0 -0
  189. /package/esm/HierarchicalTrackSelectorWidget/components/{CloseConnectionDialog.d.ts → dialogs/CloseConnectionDialog.d.ts} +0 -0
  190. /package/esm/HierarchicalTrackSelectorWidget/components/{CloseConnectionDialog.js → dialogs/CloseConnectionDialog.js} +0 -0
  191. /package/esm/HierarchicalTrackSelectorWidget/components/{DeleteConnectionDialog.d.ts → dialogs/DeleteConnectionDialog.d.ts} +0 -0
  192. /package/esm/HierarchicalTrackSelectorWidget/components/{DeleteConnectionDialog.js → dialogs/DeleteConnectionDialog.js} +0 -0
  193. /package/esm/HierarchicalTrackSelectorWidget/components/{ManageConnectionsDialog.d.ts → dialogs/ManageConnectionsDialog.d.ts} +0 -0
  194. /package/esm/HierarchicalTrackSelectorWidget/components/{ManageConnectionsDialog.js → dialogs/ManageConnectionsDialog.js} +0 -0
  195. /package/esm/HierarchicalTrackSelectorWidget/components/{ToggleConnectionsDialog.d.ts → dialogs/ToggleConnectionsDialog.d.ts} +0 -0
  196. /package/esm/HierarchicalTrackSelectorWidget/components/{ToggleConnectionsDialog.js → dialogs/ToggleConnectionsDialog.js} +0 -0
  197. /package/src/HierarchicalTrackSelectorWidget/components/{CloseConnectionDialog.tsx → dialogs/CloseConnectionDialog.tsx} +0 -0
  198. /package/src/HierarchicalTrackSelectorWidget/components/{DeleteConnectionDialog.tsx → dialogs/DeleteConnectionDialog.tsx} +0 -0
  199. /package/src/HierarchicalTrackSelectorWidget/components/{ManageConnectionsDialog.tsx → dialogs/ManageConnectionsDialog.tsx} +0 -0
  200. /package/src/HierarchicalTrackSelectorWidget/components/{ToggleConnectionsDialog.tsx → dialogs/ToggleConnectionsDialog.tsx} +0 -0
@@ -0,0 +1,197 @@
1
+ import React, { Suspense, lazy, useState } from 'react'
2
+ import { IconButton } from '@mui/material'
3
+ import { makeStyles } from 'tss-react/mui'
4
+ import { observer } from 'mobx-react'
5
+ import JBrowseMenu from '@jbrowse/core/ui/Menu'
6
+ import {
7
+ getSession,
8
+ isSessionModelWithWidgets,
9
+ isSessionModelWithConnections,
10
+ } from '@jbrowse/core/util'
11
+ import {
12
+ AnyConfigurationModel,
13
+ readConfObject,
14
+ } from '@jbrowse/core/configuration'
15
+
16
+ // icons
17
+ import MenuIcon from '@mui/icons-material/Menu'
18
+
19
+ // locals
20
+ import { HierarchicalTrackSelectorModel } from '../../model'
21
+
22
+ // lazy components
23
+ const CloseConnectionDlg = lazy(
24
+ () => import('../dialogs/CloseConnectionDialog'),
25
+ )
26
+ const DeleteConnectionDlg = lazy(
27
+ () => import('../dialogs/DeleteConnectionDialog'),
28
+ )
29
+ const ManageConnectionsDlg = lazy(
30
+ () => import('../dialogs/ManageConnectionsDialog'),
31
+ )
32
+ const ToggleConnectionsDlg = lazy(
33
+ () => import('../dialogs/ToggleConnectionsDialog'),
34
+ )
35
+
36
+ const useStyles = makeStyles()(theme => ({
37
+ menuIcon: {
38
+ marginRight: theme.spacing(1),
39
+ marginBottom: 0,
40
+ },
41
+ }))
42
+
43
+ interface ModalArgs {
44
+ connectionConf: AnyConfigurationModel
45
+ safelyBreakConnection: Function
46
+ dereferenceTypeCount: { [key: string]: number }
47
+ name: string
48
+ }
49
+
50
+ interface DialogDetails {
51
+ name: string
52
+ connectionConf: AnyConfigurationModel
53
+ }
54
+
55
+ export default observer(function HamburgerMenu({
56
+ model,
57
+ setAssemblyIdx,
58
+ }: {
59
+ model: HierarchicalTrackSelectorModel
60
+ setAssemblyIdx: Function
61
+ }) {
62
+ const session = getSession(model)
63
+ const [menuEl, setMenuEl] = useState<HTMLButtonElement>()
64
+ const [modalInfo, setModalInfo] = useState<ModalArgs>()
65
+ const [deleteDlgDetails, setDeleteDlgDetails] = useState<DialogDetails>()
66
+ const [connectionToggleOpen, setConnectionToggleOpen] = useState(false)
67
+ const [connectionManagerOpen, setConnectionManagerOpen] = useState(false)
68
+ const { classes } = useStyles()
69
+ const { assemblyNames } = model
70
+
71
+ function breakConnection(
72
+ connectionConf: AnyConfigurationModel,
73
+ deletingConnection?: boolean,
74
+ ) {
75
+ const name = readConfObject(connectionConf, 'name')
76
+
77
+ // @ts-ignore
78
+ const result = session.prepareToBreakConnection(connectionConf)
79
+ if (result) {
80
+ const [safelyBreakConnection, dereferenceTypeCount] = result
81
+ if (Object.keys(dereferenceTypeCount).length > 0) {
82
+ setModalInfo({
83
+ connectionConf,
84
+ safelyBreakConnection,
85
+ dereferenceTypeCount,
86
+ name,
87
+ })
88
+ } else {
89
+ safelyBreakConnection()
90
+ }
91
+ }
92
+ if (deletingConnection) {
93
+ setDeleteDlgDetails({ name, connectionConf })
94
+ }
95
+ }
96
+
97
+ const connectionMenuItems = [
98
+ {
99
+ label: 'Turn on/off connections...',
100
+ onClick: () => setConnectionToggleOpen(true),
101
+ },
102
+ ]
103
+
104
+ if (isSessionModelWithConnections(session)) {
105
+ connectionMenuItems.unshift({
106
+ label: 'Add connection...',
107
+ onClick: () => {
108
+ if (isSessionModelWithWidgets(session)) {
109
+ session.showWidget(
110
+ session.addWidget('AddConnectionWidget', 'addConnectionWidget'),
111
+ )
112
+ }
113
+ },
114
+ })
115
+
116
+ connectionMenuItems.push({
117
+ label: 'Delete connections...',
118
+ onClick: () => setConnectionManagerOpen(true),
119
+ })
120
+ }
121
+ return (
122
+ <>
123
+ <IconButton
124
+ className={classes.menuIcon}
125
+ onClick={event => setMenuEl(event.currentTarget)}
126
+ >
127
+ <MenuIcon />
128
+ </IconButton>
129
+
130
+ <JBrowseMenu
131
+ anchorEl={menuEl}
132
+ open={Boolean(menuEl)}
133
+ onMenuItemClick={(_, callback) => {
134
+ callback()
135
+ setMenuEl(undefined)
136
+ }}
137
+ onClose={() => setMenuEl(undefined)}
138
+ menuItems={[
139
+ {
140
+ label: 'Add track...',
141
+ onClick: () => {
142
+ if (isSessionModelWithWidgets(session)) {
143
+ session.showWidget(
144
+ session.addWidget('AddTrackWidget', 'addTrackWidget', {
145
+ view: model.view.id,
146
+ }),
147
+ )
148
+ }
149
+ },
150
+ },
151
+ ...(session.makeConnection ? connectionMenuItems : []),
152
+
153
+ ...(assemblyNames.length > 1
154
+ ? [
155
+ {
156
+ label: 'Select assembly...',
157
+ subMenu: assemblyNames.map((name, idx) => ({
158
+ label: name,
159
+ onClick: () => setAssemblyIdx(idx),
160
+ })),
161
+ },
162
+ ]
163
+ : []),
164
+ ]}
165
+ />
166
+ <Suspense fallback={<div />}>
167
+ {modalInfo ? (
168
+ <CloseConnectionDlg
169
+ modalInfo={modalInfo}
170
+ setModalInfo={setModalInfo}
171
+ />
172
+ ) : null}
173
+ {deleteDlgDetails ? (
174
+ <DeleteConnectionDlg
175
+ handleClose={() => setDeleteDlgDetails(undefined)}
176
+ deleteDialogDetails={deleteDlgDetails}
177
+ session={session}
178
+ />
179
+ ) : null}
180
+ {connectionManagerOpen ? (
181
+ <ManageConnectionsDlg
182
+ handleClose={() => setConnectionManagerOpen(false)}
183
+ breakConnection={breakConnection}
184
+ session={session}
185
+ />
186
+ ) : null}
187
+ {connectionToggleOpen ? (
188
+ <ToggleConnectionsDlg
189
+ handleClose={() => setConnectionToggleOpen(false)}
190
+ session={session}
191
+ breakConnection={breakConnection}
192
+ />
193
+ ) : null}
194
+ </Suspense>
195
+ </>
196
+ )
197
+ })
@@ -0,0 +1,85 @@
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 onClick={() => model.clearFilterText()}>
59
+ <ClearIcon />
60
+ </IconButton>
61
+ </InputAdornment>
62
+ ),
63
+ }}
64
+ />
65
+ <Button
66
+ className={classes.menuIcon}
67
+ onClick={() => setFacetedOpen(true)}
68
+ >
69
+ Open faceted selector
70
+ </Button>
71
+ </div>
72
+
73
+ <Suspense fallback={<div />}>
74
+ {facetedOpen ? (
75
+ <FacetedDialog
76
+ handleClose={() => setFacetedOpen(false)}
77
+ model={model}
78
+ />
79
+ ) : null}
80
+ </Suspense>
81
+ </div>
82
+ )
83
+ }
84
+
85
+ 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.tertiary.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,106 @@
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()(theme => ({
19
+ compactCheckbox: {
20
+ padding: 0,
21
+ },
22
+
23
+ checkboxLabel: {
24
+ marginRight: 0,
25
+ '&:hover': {
26
+ backgroundColor: theme.palette.action.selected,
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
+ data-testid={`htsTrackEntryMenu-${id}`}
74
+ >
75
+ <MoreHorizIcon />
76
+ </IconButton>
77
+
78
+ {info ? (
79
+ <JBrowseMenu
80
+ anchorEl={info?.target}
81
+ menuItems={[
82
+ ...(getSession(model).getTrackActionMenuItems?.(info.conf) || []),
83
+ {
84
+ label: 'Add to selection',
85
+ onClick: () => model.addToSelection([info.conf]),
86
+ },
87
+ ...(selected
88
+ ? [
89
+ {
90
+ label: 'Remove from selection',
91
+ onClick: () => model.removeFromSelection([info.conf]),
92
+ },
93
+ ]
94
+ : []),
95
+ ]}
96
+ onMenuItemClick={(_event, callback) => {
97
+ callback()
98
+ setInfo(undefined)
99
+ }}
100
+ open={Boolean(info)}
101
+ onClose={() => setInfo(undefined)}
102
+ />
103
+ ) : null}
104
+ </>
105
+ )
106
+ }
@@ -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
+ }