@jbrowse/plugin-data-management 2.7.2 → 2.9.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 (83) hide show
  1. package/dist/AddTrackWidget/model.d.ts +81 -0
  2. package/dist/AddTrackWidget/model.js +81 -0
  3. package/dist/HierarchicalTrackSelectorWidget/components/ShoppingCart.d.ts +1 -1
  4. package/dist/HierarchicalTrackSelectorWidget/components/ShoppingCart.js +11 -53
  5. package/dist/HierarchicalTrackSelectorWidget/components/faceted/FacetFilter.d.ts +5 -7
  6. package/dist/HierarchicalTrackSelectorWidget/components/faceted/FacetFilter.js +12 -11
  7. package/dist/HierarchicalTrackSelectorWidget/components/faceted/FacetFilters.d.ts +5 -7
  8. package/dist/HierarchicalTrackSelectorWidget/components/faceted/FacetFilters.js +11 -8
  9. package/dist/HierarchicalTrackSelectorWidget/components/faceted/FacetedHeader.d.ts +1 -11
  10. package/dist/HierarchicalTrackSelectorWidget/components/faceted/FacetedHeader.js +9 -7
  11. package/dist/HierarchicalTrackSelectorWidget/components/faceted/FacetedSelector.js +40 -135
  12. package/dist/HierarchicalTrackSelectorWidget/components/tree/DropdownTrackSelector.d.ts +12 -0
  13. package/dist/HierarchicalTrackSelectorWidget/components/tree/DropdownTrackSelector.js +57 -0
  14. package/dist/HierarchicalTrackSelectorWidget/components/tree/FavoriteTracks.d.ts +6 -0
  15. package/dist/HierarchicalTrackSelectorWidget/components/tree/FavoriteTracks.js +42 -0
  16. package/dist/HierarchicalTrackSelectorWidget/components/tree/HamburgerMenu.js +71 -46
  17. package/dist/HierarchicalTrackSelectorWidget/components/tree/HierarchicalHeader.js +5 -34
  18. package/dist/HierarchicalTrackSelectorWidget/components/tree/HierarchicalTree.js +8 -3
  19. package/dist/HierarchicalTrackSelectorWidget/components/tree/RecentlyUsedTracks.d.ts +6 -0
  20. package/dist/HierarchicalTrackSelectorWidget/components/tree/RecentlyUsedTracks.js +42 -0
  21. package/dist/HierarchicalTrackSelectorWidget/components/tree/TrackCategory.js +7 -6
  22. package/dist/HierarchicalTrackSelectorWidget/components/tree/TrackLabel.js +9 -28
  23. package/dist/HierarchicalTrackSelectorWidget/components/tree/TrackLabelMenu.d.ts +12 -0
  24. package/dist/HierarchicalTrackSelectorWidget/components/tree/TrackLabelMenu.js +50 -0
  25. package/dist/HierarchicalTrackSelectorWidget/components/util.d.ts +3 -0
  26. package/dist/HierarchicalTrackSelectorWidget/components/util.js +5 -1
  27. package/dist/HierarchicalTrackSelectorWidget/facetedModel.d.ts +128 -0
  28. package/dist/HierarchicalTrackSelectorWidget/facetedModel.js +206 -0
  29. package/dist/HierarchicalTrackSelectorWidget/facetedUtil.d.ts +2 -0
  30. package/dist/HierarchicalTrackSelectorWidget/{components/faceted/util.js → facetedUtil.js} +5 -1
  31. package/dist/HierarchicalTrackSelectorWidget/generateHierarchy.d.ts +17 -5
  32. package/dist/HierarchicalTrackSelectorWidget/generateHierarchy.js +27 -21
  33. package/dist/HierarchicalTrackSelectorWidget/model.d.ts +196 -17
  34. package/dist/HierarchicalTrackSelectorWidget/model.js +178 -23
  35. package/dist/ucsc-trackhub/doConnect.d.ts +1 -0
  36. package/dist/ucsc-trackhub/doConnect.js +131 -0
  37. package/dist/ucsc-trackhub/model.d.ts +19 -2
  38. package/dist/ucsc-trackhub/model.js +16 -71
  39. package/dist/ucsc-trackhub/ucscTrackHub.d.ts +161 -4
  40. package/dist/ucsc-trackhub/ucscTrackHub.js +49 -166
  41. package/esm/AddTrackWidget/model.d.ts +81 -0
  42. package/esm/AddTrackWidget/model.js +81 -0
  43. package/esm/HierarchicalTrackSelectorWidget/components/ShoppingCart.d.ts +1 -1
  44. package/esm/HierarchicalTrackSelectorWidget/components/ShoppingCart.js +12 -31
  45. package/esm/HierarchicalTrackSelectorWidget/components/faceted/FacetFilter.d.ts +5 -7
  46. package/esm/HierarchicalTrackSelectorWidget/components/faceted/FacetFilter.js +13 -11
  47. package/esm/HierarchicalTrackSelectorWidget/components/faceted/FacetFilters.d.ts +5 -7
  48. package/esm/HierarchicalTrackSelectorWidget/components/faceted/FacetFilters.js +12 -8
  49. package/esm/HierarchicalTrackSelectorWidget/components/faceted/FacetedHeader.d.ts +1 -11
  50. package/esm/HierarchicalTrackSelectorWidget/components/faceted/FacetedHeader.js +9 -7
  51. package/esm/HierarchicalTrackSelectorWidget/components/faceted/FacetedSelector.js +41 -113
  52. package/esm/HierarchicalTrackSelectorWidget/components/tree/DropdownTrackSelector.d.ts +12 -0
  53. package/esm/HierarchicalTrackSelectorWidget/components/tree/DropdownTrackSelector.js +29 -0
  54. package/esm/HierarchicalTrackSelectorWidget/components/tree/FavoriteTracks.d.ts +6 -0
  55. package/esm/HierarchicalTrackSelectorWidget/components/tree/FavoriteTracks.js +37 -0
  56. package/esm/HierarchicalTrackSelectorWidget/components/tree/HamburgerMenu.js +71 -46
  57. package/esm/HierarchicalTrackSelectorWidget/components/tree/HierarchicalHeader.js +6 -12
  58. package/esm/HierarchicalTrackSelectorWidget/components/tree/HierarchicalTree.js +8 -3
  59. package/esm/HierarchicalTrackSelectorWidget/components/tree/RecentlyUsedTracks.d.ts +6 -0
  60. package/esm/HierarchicalTrackSelectorWidget/components/tree/RecentlyUsedTracks.js +37 -0
  61. package/esm/HierarchicalTrackSelectorWidget/components/tree/TrackCategory.js +7 -6
  62. package/esm/HierarchicalTrackSelectorWidget/components/tree/TrackLabel.js +8 -27
  63. package/esm/HierarchicalTrackSelectorWidget/components/tree/TrackLabelMenu.d.ts +12 -0
  64. package/esm/HierarchicalTrackSelectorWidget/components/tree/TrackLabelMenu.js +45 -0
  65. package/esm/HierarchicalTrackSelectorWidget/components/util.d.ts +3 -0
  66. package/esm/HierarchicalTrackSelectorWidget/components/util.js +5 -1
  67. package/esm/HierarchicalTrackSelectorWidget/facetedModel.d.ts +128 -0
  68. package/esm/HierarchicalTrackSelectorWidget/facetedModel.js +202 -0
  69. package/esm/HierarchicalTrackSelectorWidget/facetedUtil.d.ts +2 -0
  70. package/esm/HierarchicalTrackSelectorWidget/{components/faceted/util.js → facetedUtil.js} +3 -0
  71. package/esm/HierarchicalTrackSelectorWidget/generateHierarchy.d.ts +17 -5
  72. package/esm/HierarchicalTrackSelectorWidget/generateHierarchy.js +27 -21
  73. package/esm/HierarchicalTrackSelectorWidget/model.d.ts +196 -17
  74. package/esm/HierarchicalTrackSelectorWidget/model.js +180 -25
  75. package/esm/ucsc-trackhub/doConnect.d.ts +1 -0
  76. package/esm/ucsc-trackhub/doConnect.js +127 -0
  77. package/esm/ucsc-trackhub/model.d.ts +19 -2
  78. package/esm/ucsc-trackhub/model.js +17 -72
  79. package/esm/ucsc-trackhub/ucscTrackHub.d.ts +161 -4
  80. package/esm/ucsc-trackhub/ucscTrackHub.js +48 -141
  81. package/package.json +3 -3
  82. package/dist/HierarchicalTrackSelectorWidget/components/faceted/util.d.ts +0 -1
  83. package/esm/HierarchicalTrackSelectorWidget/components/faceted/util.d.ts +0 -1
@@ -5,6 +5,8 @@ import { readConfObject, } from '@jbrowse/core/configuration';
5
5
  import CascadingMenuButton from '@jbrowse/core/ui/CascadingMenuButton';
6
6
  // icons
7
7
  import MenuIcon from '@mui/icons-material/Menu';
8
+ // lazies
9
+ const FacetedDialog = lazy(() => import('../faceted/FacetedDialog'));
8
10
  // lazy components
9
11
  const CloseConnectionDlg = lazy(() => import('../dialogs/CloseConnectionDialog'));
10
12
  const DeleteConnectionDlg = lazy(() => import('../dialogs/DeleteConnectionDialog'));
@@ -16,6 +18,7 @@ const HamburgerMenu = observer(function ({ model, }) {
16
18
  const [deleteDlgDetails, setDeleteDlgDetails] = useState();
17
19
  const [connectionToggleOpen, setConnectionToggleOpen] = useState(false);
18
20
  const [connectionManagerOpen, setConnectionManagerOpen] = useState(false);
21
+ const [facetedOpen, setFacetedOpen] = useState(false);
19
22
  function breakConnection(connectionConf, deletingConnection) {
20
23
  var _a;
21
24
  const name = readConfObject(connectionConf, 'name');
@@ -40,6 +43,12 @@ const HamburgerMenu = observer(function ({ model, }) {
40
43
  }
41
44
  return (React.createElement(React.Fragment, null,
42
45
  React.createElement(CascadingMenuButton, { menuItems: [
46
+ {
47
+ label: 'Open faceted track selector',
48
+ onClick: () => {
49
+ setFacetedOpen(true);
50
+ },
51
+ },
43
52
  ...(isSessionWithAddTracks(session)
44
53
  ? [
45
54
  {
@@ -54,59 +63,74 @@ const HamburgerMenu = observer(function ({ model, }) {
54
63
  },
55
64
  ]
56
65
  : []),
57
- ...(isSessionModelWithConnections(session)
58
- ? [
66
+ {
67
+ label: 'Connections...',
68
+ subMenu: [
69
+ ...(isSessionModelWithConnections(session)
70
+ ? [
71
+ {
72
+ label: 'Turn on/off connections...',
73
+ onClick: () => setConnectionToggleOpen(true),
74
+ },
75
+ ]
76
+ : []),
77
+ ...(isSessionModelWithConnectionEditing(session)
78
+ ? [
79
+ {
80
+ label: 'Add connection...',
81
+ onClick: () => {
82
+ if (isSessionModelWithWidgets(session)) {
83
+ session.showWidget(session.addWidget('AddConnectionWidget', 'addConnectionWidget'));
84
+ }
85
+ },
86
+ },
87
+ {
88
+ label: 'Delete connections...',
89
+ onClick: () => setConnectionManagerOpen(true),
90
+ },
91
+ ]
92
+ : []),
93
+ ],
94
+ },
95
+ {
96
+ label: 'Sort...',
97
+ type: 'subMenu',
98
+ subMenu: [
59
99
  {
60
- label: 'Turn on/off connections...',
61
- onClick: () => setConnectionToggleOpen(true),
100
+ label: 'Sort tracks by name',
101
+ type: 'checkbox',
102
+ checked: model.activeSortTrackNames,
103
+ onClick: () => model.setSortTrackNames(!model.activeSortTrackNames),
62
104
  },
63
- ]
64
- : []),
65
- ...(isSessionModelWithConnectionEditing(session)
66
- ? [
67
105
  {
68
- label: 'Add connection...',
69
- onClick: () => {
70
- if (isSessionModelWithWidgets(session)) {
71
- session.showWidget(session.addWidget('AddConnectionWidget', 'addConnectionWidget'));
72
- }
73
- },
106
+ label: 'Sort categories by name',
107
+ type: 'checkbox',
108
+ checked: model.activeSortCategories,
109
+ onClick: () => model.setSortCategories(!model.activeSortCategories),
74
110
  },
75
- {
76
- label: 'Delete connections...',
77
- onClick: () => setConnectionManagerOpen(true),
78
- },
79
- ]
80
- : []),
81
- { type: 'divider' },
82
- {
83
- label: 'Sort tracks by name',
84
- type: 'checkbox',
85
- checked: model.activeSortTrackNames,
86
- onClick: () => model.setSortTrackNames(!model.activeSortTrackNames),
111
+ ],
87
112
  },
88
113
  {
89
- label: 'Sort categories by name',
90
- type: 'checkbox',
91
- checked: model.activeSortCategories,
92
- onClick: () => model.setSortCategories(!model.activeSortCategories),
93
- },
94
- { type: 'divider' },
95
- ...(model.hasAnySubcategories
96
- ? [
114
+ label: 'Collapse...',
115
+ type: 'subMenu',
116
+ subMenu: [
117
+ ...(model.hasAnySubcategories
118
+ ? [
119
+ {
120
+ label: 'Collapse subcategories',
121
+ onClick: () => model.collapseSubCategories(),
122
+ },
123
+ ]
124
+ : []),
97
125
  {
98
- label: 'Collapse subcategories',
99
- onClick: () => model.collapseSubCategories(),
126
+ label: 'Collapse top-level categories',
127
+ onClick: () => model.collapseTopLevelCategories(),
100
128
  },
101
- ]
102
- : []),
103
- {
104
- label: 'Collapse top-level categories',
105
- onClick: () => model.collapseTopLevelCategories(),
106
- },
107
- {
108
- label: 'Expand all categories',
109
- onClick: () => model.expandAllCategories(),
129
+ {
130
+ label: 'Expand all categories',
131
+ onClick: () => model.expandAllCategories(),
132
+ },
133
+ ],
110
134
  },
111
135
  ] },
112
136
  React.createElement(MenuIcon, null)),
@@ -114,6 +138,7 @@ const HamburgerMenu = observer(function ({ model, }) {
114
138
  modalInfo ? (React.createElement(CloseConnectionDlg, { modalInfo: modalInfo, onClose: () => setModalInfo(undefined) })) : null,
115
139
  deleteDlgDetails ? (React.createElement(DeleteConnectionDlg, { handleClose: () => setDeleteDlgDetails(undefined), deleteDialogDetails: deleteDlgDetails, session: session })) : null,
116
140
  connectionManagerOpen ? (React.createElement(ManageConnectionsDlg, { handleClose: () => setConnectionManagerOpen(false), breakConnection: breakConnection, session: session })) : null,
117
- connectionToggleOpen ? (React.createElement(ToggleConnectionsDlg, { handleClose: () => setConnectionToggleOpen(false), session: session, breakConnection: breakConnection })) : null)));
141
+ connectionToggleOpen ? (React.createElement(ToggleConnectionsDlg, { handleClose: () => setConnectionToggleOpen(false), session: session, breakConnection: breakConnection })) : null,
142
+ facetedOpen ? (React.createElement(FacetedDialog, { handleClose: () => setFacetedOpen(false), model: model })) : null)));
118
143
  });
119
144
  export default HamburgerMenu;
@@ -1,21 +1,17 @@
1
- import React, { Suspense, lazy, useState } from 'react';
2
- import { Button, IconButton, InputAdornment, TextField } from '@mui/material';
1
+ import React from 'react';
2
+ import { IconButton, InputAdornment, TextField } from '@mui/material';
3
3
  import { makeStyles } from 'tss-react/mui';
4
4
  import { observer } from 'mobx-react';
5
5
  // icons
6
6
  import ClearIcon from '@mui/icons-material/Clear';
7
7
  import HamburgerMenu from './HamburgerMenu';
8
8
  import ShoppingCart from '../ShoppingCart';
9
- // lazies
10
- const FacetedDialog = lazy(() => import('../faceted/FacetedDialog'));
9
+ import FavoriteTracks from './FavoriteTracks';
10
+ import RecentlyUsedTracks from './RecentlyUsedTracks';
11
11
  const useStyles = makeStyles()(theme => ({
12
12
  searchBox: {
13
13
  margin: theme.spacing(2),
14
14
  },
15
- menuIcon: {
16
- marginRight: theme.spacing(1),
17
- marginBottom: 0,
18
- },
19
15
  }));
20
16
  const SearchTracksTextField = observer(function ({ model, }) {
21
17
  const { filterText } = model;
@@ -27,14 +23,12 @@ const SearchTracksTextField = observer(function ({ model, }) {
27
23
  } }));
28
24
  });
29
25
  const HierarchicalTrackSelectorHeader = observer(function ({ model, setHeaderHeight, }) {
30
- const { classes } = useStyles();
31
- const [facetedOpen, setFacetedOpen] = useState(false);
32
26
  return (React.createElement("div", { ref: ref => setHeaderHeight((ref === null || ref === void 0 ? void 0 : ref.getBoundingClientRect().height) || 0), "data-testid": "hierarchical_track_selector" },
33
27
  React.createElement("div", { style: { display: 'flex' } },
34
28
  React.createElement(HamburgerMenu, { model: model }),
35
29
  React.createElement(ShoppingCart, { model: model }),
36
30
  React.createElement(SearchTracksTextField, { model: model }),
37
- React.createElement(Button, { className: classes.menuIcon, onClick: () => setFacetedOpen(true) }, "Open faceted selector")),
38
- React.createElement(Suspense, { fallback: React.createElement("div", null) }, facetedOpen ? (React.createElement(FacetedDialog, { handleClose: () => setFacetedOpen(false), model: model })) : null)));
31
+ React.createElement(RecentlyUsedTracks, { model: model }),
32
+ React.createElement(FavoriteTracks, { model: model }))));
39
33
  });
40
34
  export default HierarchicalTrackSelectorHeader;
@@ -4,8 +4,8 @@ import { VariableSizeTree } from 'react-vtree';
4
4
  import { getSession } from '@jbrowse/core/util';
5
5
  import Node from './TrackListNode';
6
6
  function getNodeData(node, nestingLevel, extra, selection) {
7
- const isLeaf = !!node.conf;
8
- const selected = !!selection[node.id];
7
+ const isLeaf = node.type === 'track';
8
+ const selected = isLeaf ? selection[node.trackId] : false;
9
9
  return {
10
10
  data: {
11
11
  defaultHeight: isLeaf ? 22 : 40,
@@ -30,7 +30,12 @@ const HierarchicalTree = observer(function HierarchicalTree({ height, tree, mode
30
30
  const { drawerPosition } = session;
31
31
  const obj = useMemo(() => Object.fromEntries(selection.map(s => [s.trackId, s])), [selection]);
32
32
  const extra = useMemo(() => ({
33
- onChange: (trackId) => view.toggleTrack(trackId),
33
+ onChange: (trackId) => {
34
+ const trackTurnedOn = view.toggleTrack(trackId);
35
+ if (trackTurnedOn) {
36
+ model.addToRecentlyUsed(trackId);
37
+ }
38
+ },
34
39
  toggleCollapse: (pathName) => model.toggleCategory(pathName),
35
40
  tree,
36
41
  model,
@@ -0,0 +1,6 @@
1
+ import React from 'react';
2
+ import { HierarchicalTrackSelectorModel } from '../../model';
3
+ declare const RecentlyUsedTracks: ({ model, }: {
4
+ model: HierarchicalTrackSelectorModel;
5
+ }) => React.JSX.Element | null;
6
+ export default RecentlyUsedTracks;
@@ -0,0 +1,37 @@
1
+ import React from 'react';
2
+ import { Badge, Tooltip } from '@mui/material';
3
+ import { observer } from 'mobx-react';
4
+ // icons
5
+ import HistoryIcon from '@mui/icons-material/History';
6
+ import DropdownTrackSelector from './DropdownTrackSelector';
7
+ import { makeStyles } from 'tss-react/mui';
8
+ const useStyles = makeStyles()({
9
+ smallBadge: {
10
+ height: 14,
11
+ },
12
+ });
13
+ const RecentlyUsedTracks = observer(function ({ model, }) {
14
+ const { classes } = useStyles();
15
+ const { view, recentlyUsedCounter, recentlyUsedTracks } = model;
16
+ return view ? (React.createElement(DropdownTrackSelector, { onClick: () => model.setRecentlyUsedCounter(0), model: model, tracks: recentlyUsedTracks, extraMenuItems: recentlyUsedTracks.length
17
+ ? [
18
+ { type: 'divider' },
19
+ {
20
+ label: 'Clear recently used',
21
+ onClick: () => model.clearRecentlyUsed(),
22
+ },
23
+ ]
24
+ : [
25
+ {
26
+ label: 'No recently used',
27
+ onClick: () => { },
28
+ },
29
+ ] },
30
+ React.createElement(Tooltip, { title: "Recently used tracks" },
31
+ React.createElement(Badge, { classes: { badge: classes.smallBadge }, anchorOrigin: {
32
+ vertical: 'bottom',
33
+ horizontal: 'right',
34
+ }, color: "secondary", badgeContent: recentlyUsedCounter },
35
+ React.createElement(HistoryIcon, null))))) : null;
36
+ });
37
+ export default RecentlyUsedTracks;
@@ -22,10 +22,10 @@ const useStyles = makeStyles()(theme => ({
22
22
  export default function Category({ isOpen, setOpen, data, }) {
23
23
  const { classes } = useStyles();
24
24
  const [menuEl, setMenuEl] = useState(null);
25
- const { name, model, id, tree, toggleCollapse } = data;
25
+ const { menuItems = [], name, model, id, tree } = data;
26
26
  return (React.createElement("div", { className: classes.accordionText, onClick: () => {
27
27
  if (!menuEl) {
28
- toggleCollapse(id);
28
+ data.toggleCollapse(id);
29
29
  setOpen(!isOpen);
30
30
  }
31
31
  } },
@@ -57,8 +57,8 @@ export default function Category({ isOpen, setOpen, data, }) {
57
57
  onClick: () => {
58
58
  var _a;
59
59
  for (const entry of ((_a = treeToMap(tree).get(id)) === null || _a === void 0 ? void 0 : _a.children) || []) {
60
- if (!entry.children.length) {
61
- model.view.showTrack(entry.id);
60
+ if (entry.type === 'track') {
61
+ model.view.showTrack(entry.trackId);
62
62
  }
63
63
  }
64
64
  },
@@ -68,12 +68,13 @@ export default function Category({ isOpen, setOpen, data, }) {
68
68
  onClick: () => {
69
69
  var _a;
70
70
  for (const entry of ((_a = treeToMap(tree).get(id)) === null || _a === void 0 ? void 0 : _a.children) || []) {
71
- if (!entry.children.length) {
72
- model.view.hideTrack(entry.id);
71
+ if (entry.type === 'track') {
72
+ model.view.hideTrack(entry.trackId);
73
73
  }
74
74
  }
75
75
  },
76
76
  },
77
+ ...menuItems,
77
78
  ], onMenuItemClick: (_event, callback) => {
78
79
  callback();
79
80
  setMenuEl(null);
@@ -1,14 +1,11 @@
1
1
  import React from 'react';
2
2
  import { Checkbox, FormControlLabel, Tooltip } from '@mui/material';
3
3
  import { makeStyles } from 'tss-react/mui';
4
- import { getSession } from '@jbrowse/core/util';
5
4
  import SanitizedHTML from '@jbrowse/core/ui/SanitizedHTML';
6
5
  import { readConfObject, } from '@jbrowse/core/configuration';
7
- // icons
8
- import MoreHorizIcon from '@mui/icons-material/MoreHoriz';
9
6
  // locals
10
7
  import { isUnsupported } from '../util';
11
- import CascadingMenuButton from '@jbrowse/core/ui/CascadingMenuButton';
8
+ import TrackLabelMenu from './TrackLabelMenu';
12
9
  const useStyles = makeStyles()(theme => ({
13
10
  compactCheckbox: {
14
11
  padding: 0,
@@ -19,36 +16,20 @@ const useStyles = makeStyles()(theme => ({
19
16
  backgroundColor: theme.palette.action.selected,
20
17
  },
21
18
  },
19
+ selected: {
20
+ background: '#cccc',
21
+ },
22
22
  }));
23
23
  export default function TrackLabel({ data }) {
24
24
  const { classes } = useStyles();
25
- const { checked, conf, model, drawerPosition, id, name, onChange, selected } = data;
26
- const description = (conf && readConfObject(conf, ['description'])) || '';
25
+ const { checked, conf, model, drawerPosition, id, trackId, name, onChange, selected, } = data;
26
+ const description = (conf && readConfObject(conf, 'description')) || '';
27
27
  return (React.createElement(React.Fragment, null,
28
28
  React.createElement(Tooltip, { title: description + (selected ? ' (in selection)' : ''), placement: drawerPosition === 'left' ? 'right' : 'left' },
29
- React.createElement(FormControlLabel, { className: classes.checkboxLabel, control: React.createElement(Checkbox, { className: classes.compactCheckbox, checked: checked, onChange: () => onChange(id), disabled: isUnsupported(name), inputProps: {
29
+ React.createElement(FormControlLabel, { className: classes.checkboxLabel, control: React.createElement(Checkbox, { className: classes.compactCheckbox, checked: checked, onChange: () => onChange(trackId), disabled: isUnsupported(name), inputProps: {
30
30
  // @ts-expect-error
31
31
  'data-testid': `htsTrackEntry-${id}`,
32
32
  } }), label: React.createElement("div", { "data-testid": `htsTrackLabel-${id}`, style: { background: selected ? '#cccc' : undefined } },
33
33
  React.createElement(SanitizedHTML, { html: name })) })),
34
- React.createElement(TrackMenuButton, { model: model, selected: selected, id: id, conf: conf })));
35
- }
36
- function TrackMenuButton({ id, model, selected, conf, }) {
37
- var _a, _b;
38
- return (React.createElement(CascadingMenuButton, { style: { padding: 0 }, "data-testid": `htsTrackEntryMenu-${id}`, menuItems: [
39
- ...(((_b = (_a = getSession(model)).getTrackActionMenuItems) === null || _b === void 0 ? void 0 : _b.call(_a, conf)) || []),
40
- {
41
- label: 'Add to selection',
42
- onClick: () => model.addToSelection([conf]),
43
- },
44
- ...(selected
45
- ? [
46
- {
47
- label: 'Remove from selection',
48
- onClick: () => model.removeFromSelection([conf]),
49
- },
50
- ]
51
- : []),
52
- ] },
53
- React.createElement(MoreHorizIcon, null)));
34
+ React.createElement(TrackLabelMenu, { model: model, trackId: trackId, id: id, conf: conf })));
54
35
  }
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+ import { AnyConfigurationModel } from '@jbrowse/core/configuration';
3
+ import { HierarchicalTrackSelectorModel } from '../../model';
4
+ declare const TrackLabelMenu: ({ id, trackId, stopPropagation, model, setOpen, conf, }: {
5
+ id: string;
6
+ trackId: string;
7
+ stopPropagation?: boolean | undefined;
8
+ conf: AnyConfigurationModel;
9
+ setOpen?: ((arg: boolean) => void) | undefined;
10
+ model: HierarchicalTrackSelectorModel;
11
+ }) => React.JSX.Element;
12
+ export default TrackLabelMenu;
@@ -0,0 +1,45 @@
1
+ import React from 'react';
2
+ import { makeStyles } from 'tss-react/mui';
3
+ import { getSession } from '@jbrowse/core/util';
4
+ import CascadingMenuButton from '@jbrowse/core/ui/CascadingMenuButton';
5
+ // icons
6
+ import MoreHorizIcon from '@mui/icons-material/MoreHoriz';
7
+ import StarIcon from '@mui/icons-material/StarBorderOutlined';
8
+ import FilledStarIcon from '@mui/icons-material/Star';
9
+ const useStyles = makeStyles()({
10
+ cascadingStyle: {
11
+ padding: 0,
12
+ },
13
+ });
14
+ const TrackLabelMenu = function ({ id, trackId, stopPropagation, model, setOpen, conf, }) {
15
+ var _a, _b;
16
+ const { classes } = useStyles();
17
+ return (React.createElement(CascadingMenuButton, { className: classes.cascadingStyle, stopPropagation: stopPropagation, setOpen: setOpen, "data-testid": `htsTrackEntryMenu-${id}`, menuItems: [
18
+ ...(((_b = (_a = getSession(model)).getTrackActionMenuItems) === null || _b === void 0 ? void 0 : _b.call(_a, conf)) || []),
19
+ model.isFavorite(trackId)
20
+ ? {
21
+ label: 'Remove from favorites',
22
+ onClick: () => model.removeFromFavorites(trackId),
23
+ icon: StarIcon,
24
+ }
25
+ : {
26
+ label: 'Add to favorites',
27
+ onClick: () => model.addToFavorites(trackId),
28
+ icon: FilledStarIcon,
29
+ },
30
+ {
31
+ label: 'Add to selection',
32
+ onClick: () => model.addToSelection([conf]),
33
+ },
34
+ ...(model.isSelected(conf)
35
+ ? [
36
+ {
37
+ label: 'Remove from selection',
38
+ onClick: () => model.removeFromSelection([conf]),
39
+ },
40
+ ]
41
+ : []),
42
+ ] },
43
+ React.createElement(MoreHorizIcon, null)));
44
+ };
45
+ export default TrackLabelMenu;
@@ -1,18 +1,21 @@
1
1
  import { AnyConfigurationModel } from '@jbrowse/core/configuration';
2
2
  import { HierarchicalTrackSelectorModel } from '../model';
3
3
  import { TreeNode } from '../generateHierarchy';
4
+ import { MenuItem } from '@jbrowse/core/ui';
4
5
  export interface NodeData {
5
6
  nestingLevel: number;
6
7
  checked: boolean;
7
8
  conf: AnyConfigurationModel;
8
9
  drawerPosition: unknown;
9
10
  id: string;
11
+ trackId: string;
10
12
  isLeaf: boolean;
11
13
  name: string;
12
14
  onChange: Function;
13
15
  toggleCollapse: (arg: string) => void;
14
16
  tree: TreeNode;
15
17
  selected: boolean;
18
+ menuItems?: MenuItem[];
16
19
  model: HierarchicalTrackSelectorModel;
17
20
  }
18
21
  export declare function getAllChildren(subtree?: TreeNode): AnyConfigurationModel[];
@@ -1,6 +1,10 @@
1
1
  export function getAllChildren(subtree) {
2
2
  // @ts-expect-error
3
- return ((subtree === null || subtree === void 0 ? void 0 : subtree.children.map(t => t.children.length ? getAllChildren(t) : t.conf)) || []).flat(Infinity);
3
+ return (subtree === null || subtree === void 0 ? void 0 : subtree.type) === 'category'
4
+ ? subtree.children
5
+ .map(t => (t.type === 'category' ? getAllChildren(t) : t.conf))
6
+ .flat(Infinity)
7
+ : [];
4
8
  }
5
9
  export function treeToMap(tree, map = new Map()) {
6
10
  if (tree.id && tree.children.length) {
@@ -0,0 +1,128 @@
1
+ import { Instance } from 'mobx-state-tree';
2
+ /**
3
+ * #stateModel FacetedModel
4
+ */
5
+ export declare function facetedStateTreeF(): import("mobx-state-tree").IModelType<{
6
+ /**
7
+ * #property
8
+ */
9
+ filterText: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<string>, [undefined]>;
10
+ /**
11
+ * #property
12
+ */
13
+ showSparse: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<boolean>, [undefined]>;
14
+ /**
15
+ * #property
16
+ */
17
+ showFilters: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<boolean>, [undefined]>;
18
+ /**
19
+ * #property
20
+ */
21
+ showOptions: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<boolean>, [undefined]>;
22
+ /**
23
+ * #property
24
+ */
25
+ panelWidth: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<number>, [undefined]>;
26
+ }, {
27
+ visible: Record<string, boolean>;
28
+ widths: Record<string, number | undefined>;
29
+ useShoppingCart: boolean;
30
+ filters: import("mobx").ObservableMap<string, string[]>;
31
+ } & {
32
+ /**
33
+ * #action
34
+ */
35
+ setFilter(key: string, value: string[]): void;
36
+ /**
37
+ * #action
38
+ */
39
+ setPanelWidth(width: number): void;
40
+ /**
41
+ * #action
42
+ */
43
+ setUseShoppingCart(f: boolean): void;
44
+ /**
45
+ * #action
46
+ */
47
+ setFilterText(str: string): void;
48
+ /**
49
+ * #action
50
+ */
51
+ setShowSparse(f: boolean): void;
52
+ /**
53
+ * #action
54
+ */
55
+ setShowOptions(f: boolean): void;
56
+ /**
57
+ * #action
58
+ */
59
+ setShowFilters(f: boolean): void;
60
+ } & {
61
+ /**
62
+ * #getter
63
+ */
64
+ readonly allTrackConfigurations: ({
65
+ [x: string]: any;
66
+ } & import("mobx-state-tree/dist/internal").NonEmptyObject & {
67
+ setSubschema(slotName: string, data: unknown): any;
68
+ } & import("mobx-state-tree").IStateTreeNode<import("@jbrowse/core/configuration").AnyConfigurationSchemaType>)[];
69
+ } & {
70
+ /**
71
+ * #getter
72
+ */
73
+ readonly rows: {
74
+ readonly id: string;
75
+ readonly conf: {
76
+ [x: string]: any;
77
+ } & import("mobx-state-tree/dist/internal").NonEmptyObject & {
78
+ setSubschema(slotName: string, data: unknown): any;
79
+ } & import("mobx-state-tree").IStateTreeNode<import("@jbrowse/core/configuration").AnyConfigurationSchemaType>;
80
+ readonly name: string;
81
+ readonly category: string;
82
+ readonly adapter: string;
83
+ readonly description: string;
84
+ readonly metadata: any;
85
+ }[];
86
+ } & {
87
+ /**
88
+ * #getter
89
+ */
90
+ readonly filteredNonMetadataKeys: string[] | readonly ["category", "adapter", "description"];
91
+ /**
92
+ * #getter
93
+ */
94
+ readonly metadataKeys: string[];
95
+ readonly filteredMetadataKeys: string[];
96
+ /**
97
+ * #getter
98
+ */
99
+ readonly fields: string[];
100
+ /**
101
+ * #getter
102
+ */
103
+ readonly filteredRows: {
104
+ readonly id: string;
105
+ readonly conf: {
106
+ [x: string]: any;
107
+ } & import("mobx-state-tree/dist/internal").NonEmptyObject & {
108
+ setSubschema(slotName: string, data: unknown): any;
109
+ } & import("mobx-state-tree").IStateTreeNode<import("@jbrowse/core/configuration").AnyConfigurationSchemaType>;
110
+ readonly name: string;
111
+ readonly category: string;
112
+ readonly adapter: string;
113
+ readonly description: string;
114
+ readonly metadata: any;
115
+ }[];
116
+ } & {
117
+ /**
118
+ * #action
119
+ */
120
+ setVisible(args: Record<string, boolean>): void;
121
+ /**
122
+ * #action
123
+ */
124
+ setWidths(args: Record<string, number | undefined>): void;
125
+ afterAttach(): void;
126
+ }, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>;
127
+ export type FacetedStateModel = ReturnType<typeof facetedStateTreeF>;
128
+ export type FacetedModel = Instance<FacetedStateModel>;