@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
@@ -1,154 +1,55 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
2
  var __importDefault = (this && this.__importDefault) || function (mod) {
26
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
27
4
  };
28
5
  Object.defineProperty(exports, "__esModule", { value: true });
29
- const react_1 = __importStar(require("react"));
30
- const material_1 = require("@mui/material");
6
+ const react_1 = __importDefault(require("react"));
31
7
  const mobx_1 = require("mobx");
32
8
  const mobx_react_1 = require("mobx-react");
33
9
  const mobx_state_tree_1 = require("mobx-state-tree");
34
10
  const x_data_grid_1 = require("@mui/x-data-grid");
35
11
  // jbrowse
36
- const tracks_1 = require("@jbrowse/core/util/tracks");
37
12
  const ui_1 = require("@jbrowse/core/ui");
38
13
  const SanitizedHTML_1 = __importDefault(require("@jbrowse/core/ui/SanitizedHTML"));
39
- const Menu_1 = __importDefault(require("@jbrowse/core/ui/Menu"));
40
14
  const ResizeBar_1 = __importDefault(require("@jbrowse/core/ui/ResizeBar"));
41
15
  const util_1 = require("@jbrowse/core/util");
42
- const configuration_1 = require("@jbrowse/core/configuration");
43
16
  const useResizeBar_1 = require("@jbrowse/core/ui/useResizeBar");
44
17
  const mui_1 = require("tss-react/mui");
45
- // icons
46
- const MoreHoriz_1 = __importDefault(require("@mui/icons-material/MoreHoriz"));
47
- const util_2 = require("../../util");
48
18
  const FacetedHeader_1 = __importDefault(require("./FacetedHeader"));
49
19
  const FacetFilters_1 = __importDefault(require("./FacetFilters"));
50
- const util_3 = require("./util");
51
- const nonMetadataKeys = ['category', 'adapter', 'description'];
20
+ const TrackLabelMenu_1 = __importDefault(require("../tree/TrackLabelMenu"));
52
21
  const useStyles = (0, mui_1.makeStyles)()({
53
22
  cell: {
54
23
  whiteSpace: 'nowrap',
55
24
  overflow: 'hidden',
56
25
  textOverflow: 'ellipsis',
57
26
  },
27
+ resizeHandle: {
28
+ marginLeft: 5,
29
+ background: 'grey',
30
+ width: 5,
31
+ },
58
32
  });
59
33
  const frac = 0.75;
60
34
  const FacetedSelector = (0, mobx_react_1.observer)(function FacetedSelector({ model, }) {
61
- var _a, _b;
35
+ var _a;
62
36
  const { classes } = useStyles();
63
- const { view, selection } = model;
37
+ const { view, selection, faceted } = model;
38
+ const { rows, panelWidth, showFilters, useShoppingCart, showOptions, filteredRows, filteredNonMetadataKeys, filteredMetadataKeys, visible, widths, } = faceted;
64
39
  const { pluginManager } = (0, util_1.getEnv)(model);
65
40
  const { ref, scrollLeft } = (0, useResizeBar_1.useResizeBar)();
66
- const [filterText, setFilterText] = (0, react_1.useState)('');
67
- const [showOptions, setShowOptions] = (0, util_1.useLocalStorage)('facet-showTableOptions', false);
68
- const [info, setInfo] = (0, react_1.useState)();
69
- const [useShoppingCart, setUseShoppingCart] = (0, react_1.useState)(false);
70
- const [showSparse, setShowSparse] = (0, util_1.useLocalStorage)('facet-showSparse', false);
71
- const [showFilters, setShowFilters] = (0, util_1.useLocalStorage)('facet-showFilters', true);
72
- const [panelWidth, setPanelWidth] = (0, util_1.useLocalStorage)('facet-panelWidth', 400);
73
- const session = (0, util_1.getSession)(model);
74
- const filterDebounced = (0, util_1.useDebounce)(filterText, 400);
75
41
  const tracks = view.tracks;
76
- const [filters, dispatch] = (0, react_1.useReducer)((state, update) => ({ ...state, [update.key]: update.val }), {});
77
- const rows = (0, react_1.useMemo)(() => {
78
- // metadata is spread onto the object for easier access and sorting
79
- // by the mui data grid (it's unable to sort by nested objects)
80
- return model.trackConfigurations
81
- .filter(conf => (0, util_2.matches)(filterDebounced, conf, session))
82
- .map(track => {
83
- var _a, _b;
84
- const metadata = (0, configuration_1.readConfObject)(track, 'metadata');
85
- return {
86
- id: track.trackId,
87
- conf: track,
88
- name: (0, tracks_1.getTrackName)(track, session),
89
- category: (_a = (0, configuration_1.readConfObject)(track, 'category')) === null || _a === void 0 ? void 0 : _a.join(', '),
90
- adapter: (_b = (0, configuration_1.readConfObject)(track, 'adapter')) === null || _b === void 0 ? void 0 : _b.type,
91
- description: (0, configuration_1.readConfObject)(track, 'description'),
92
- metadata,
93
- ...metadata,
94
- };
95
- });
96
- }, [model, filterDebounced, session]);
97
- const filteredNonMetadataKeys = (0, react_1.useMemo)(() => nonMetadataKeys.filter(f => showSparse ? true : rows.map(r => r[f]).filter(f => !!f).length > 5), [showSparse, rows]);
98
- const filteredMetadataKeys = (0, react_1.useMemo)(() => [...new Set(rows.flatMap(row => (0, util_3.getRootKeys)(row.metadata)))].filter(f => showSparse
99
- ? true
100
- : rows.map(r => r.metadata[f]).filter(f => !!f).length > 5), [showSparse, rows]);
101
- const fields = (0, react_1.useMemo)(() => ['name', ...filteredNonMetadataKeys, ...filteredMetadataKeys], [filteredNonMetadataKeys, filteredMetadataKeys]);
102
- const [widths, setWidths] = (0, react_1.useState)({
103
- name: (0, util_1.measureGridWidth)(rows.map(r => r.name), { maxWidth: 500, stripHTML: true }) + 15,
104
- ...Object.fromEntries(filteredNonMetadataKeys.map(e => [
105
- e,
106
- (0, util_1.measureGridWidth)(rows.map(r => r[e]), { maxWidth: 400, stripHTML: true }),
107
- ])),
108
- ...Object.fromEntries(filteredMetadataKeys.map(e => [
109
- e,
110
- (0, util_1.measureGridWidth)(rows.map(r => r.metadata[e]), { maxWidth: 400, stripHTML: true }),
111
- ])),
112
- });
113
- const [visible, setVisible] = (0, react_1.useState)(Object.fromEntries(fields.map(c => [c, true])));
114
- (0, react_1.useEffect)(() => {
115
- setVisible(visible => ({
116
- ...Object.fromEntries(fields.map(c => [c, true])),
117
- ...visible,
118
- }));
119
- }, [fields]);
120
- (0, react_1.useEffect)(() => {
121
- setWidths(widths => ({
122
- name: widths.name,
123
- ...Object.fromEntries(filteredNonMetadataKeys
124
- .filter(f => visible[f])
125
- .map(e => [
126
- e,
127
- (0, util_1.measureGridWidth)(rows.map(r => r[e]), { stripHTML: true, maxWidth: 400 }),
128
- ])),
129
- ...Object.fromEntries(filteredMetadataKeys
130
- .filter(f => visible[f])
131
- .map(e => [
132
- e,
133
- (0, util_1.measureGridWidth)(rows.map(r => r.metadata[e]), { stripHTML: true, maxWidth: 400 }),
134
- ])),
135
- }));
136
- }, [filteredMetadataKeys, visible, filteredNonMetadataKeys, showSparse, rows]);
137
42
  const widthsDebounced = (0, util_1.useDebounce)(widths, 200);
138
43
  const columns = [
139
44
  {
140
45
  field: 'name',
141
46
  hideable: false,
142
47
  renderCell: (params) => {
143
- const { value, id, row } = params;
48
+ const { value, row } = params;
49
+ const { id, conf } = row;
144
50
  return (react_1.default.createElement("div", { className: classes.cell },
145
51
  react_1.default.createElement(SanitizedHTML_1.default, { html: value }),
146
- react_1.default.createElement(material_1.IconButton, { onClick: e => setInfo({
147
- target: e.currentTarget,
148
- id: id,
149
- conf: row.conf,
150
- }) },
151
- react_1.default.createElement(MoreHoriz_1.default, null))));
52
+ react_1.default.createElement(TrackLabelMenu_1.default, { id: id, conf: conf, trackId: id, model: model })));
152
53
  },
153
54
  width: (_a = widthsDebounced.name) !== null && _a !== void 0 ? _a : 100,
154
55
  },
@@ -158,34 +59,30 @@ const FacetedSelector = (0, mobx_react_1.observer)(function FacetedSelector({ mo
158
59
  field: e,
159
60
  width: (_a = widthsDebounced[e]) !== null && _a !== void 0 ? _a : 100,
160
61
  renderCell: (params) => {
161
- const { value } = params;
162
- return (react_1.default.createElement("div", { className: classes.cell }, value ? react_1.default.createElement(SanitizedHTML_1.default, { html: value }) : ''));
62
+ const val = params.value;
63
+ return val ? react_1.default.createElement(SanitizedHTML_1.default, { className: classes.cell, html: val }) : '';
163
64
  },
164
65
  });
165
66
  }),
166
67
  ...filteredMetadataKeys.map(e => {
167
68
  var _a;
168
69
  return ({
169
- field: e,
170
- width: (_a = widthsDebounced[e]) !== null && _a !== void 0 ? _a : 100,
70
+ field: `metadata.${e}`,
71
+ headerName: ['name', ...filteredNonMetadataKeys].includes(e)
72
+ ? `${e} (from metadata)`
73
+ : e,
74
+ width: (_a = widthsDebounced['metadata.' + e]) !== null && _a !== void 0 ? _a : 100,
75
+ valueGetter: (params) => params.row.metadata[e],
171
76
  renderCell: (params) => {
172
- const { value } = params;
173
- return (react_1.default.createElement("div", { className: classes.cell }, value ? react_1.default.createElement(SanitizedHTML_1.default, { html: value }) : ''));
77
+ const val = params.row.metadata[e];
78
+ return val ? react_1.default.createElement(SanitizedHTML_1.default, { className: classes.cell, html: val }) : '';
174
79
  },
175
80
  });
176
81
  }),
177
82
  ];
178
83
  const shownTrackIds = new Set(tracks.map(t => t.configuration.trackId));
179
- const arrFilters = Object.entries(filters)
180
- .filter(f => f[1].length > 0)
181
- .map(([key, val]) => [key, new Set(val)]);
182
- const filteredRows = rows.filter(row => arrFilters.every(([key, val]) => val.has(row[key])));
183
84
  return (react_1.default.createElement(react_1.default.Fragment, null,
184
- info ? (react_1.default.createElement(Menu_1.default, { anchorEl: info === null || info === void 0 ? void 0 : info.target, menuItems: ((_b = session.getTrackActionMenuItems) === null || _b === void 0 ? void 0 : _b.call(session, info.conf)) || [], onMenuItemClick: (_event, callback) => {
185
- callback();
186
- setInfo(undefined);
187
- }, open: !!info, onClose: () => setInfo(undefined) })) : null,
188
- react_1.default.createElement(FacetedHeader_1.default, { setShowSparse: setShowSparse, setShowFilters: setShowFilters, setShowOptions: setShowOptions, setFilterText: setFilterText, setUseShoppingCart: setUseShoppingCart, showFilters: showFilters, showSparse: showSparse, showOptions: showOptions, filterText: filterText, useShoppingCart: useShoppingCart, model: model }),
85
+ react_1.default.createElement(FacetedHeader_1.default, { model: model }),
189
86
  react_1.default.createElement("div", { ref: ref, style: {
190
87
  display: 'flex',
191
88
  overflow: 'hidden',
@@ -196,11 +93,11 @@ const FacetedSelector = (0, mobx_react_1.observer)(function FacetedSelector({ mo
196
93
  height: window.innerHeight * frac,
197
94
  width: window.innerWidth * frac - (showFilters ? panelWidth : 0),
198
95
  } },
199
- react_1.default.createElement(ResizeBar_1.default, { checkbox: true, widths: Object.values(widths).map(f => f !== null && f !== void 0 ? f : 100), setWidths: newWidths => setWidths(Object.fromEntries(Object.entries(widths).map((entry, idx) => [
96
+ react_1.default.createElement(ResizeBar_1.default, { checkbox: true, widths: Object.values(widths).map(f => f !== null && f !== void 0 ? f : 100), setWidths: newWidths => faceted.setWidths(Object.fromEntries(Object.entries(widths).map((entry, idx) => [
200
97
  entry[0],
201
98
  newWidths[idx],
202
99
  ]))), scrollLeft: scrollLeft }),
203
- react_1.default.createElement(x_data_grid_1.DataGrid, { rows: filteredRows, columnVisibilityModel: visible, onColumnVisibilityModelChange: newModel => setVisible(newModel), columnHeaderHeight: 35, checkboxSelection: true, disableRowSelectionOnClick: true, keepNonExistentRowsSelected: true, onRowSelectionModelChange: userSelectedIds => {
100
+ react_1.default.createElement(x_data_grid_1.DataGrid, { rows: filteredRows, columnVisibilityModel: visible, onColumnVisibilityModelChange: n => faceted.setVisible(n), columnHeaderHeight: 35, checkboxSelection: true, disableRowSelectionOnClick: true, keepNonExistentRowsSelected: true, onRowSelectionModelChange: userSelectedIds => {
204
101
  if (!useShoppingCart) {
205
102
  const a1 = shownTrackIds;
206
103
  const a2 = new Set(userSelectedIds);
@@ -209,27 +106,35 @@ const FacetedSelector = (0, mobx_react_1.observer)(function FacetedSelector({ mo
209
106
  (0, mobx_1.transaction)(() => {
210
107
  ;
211
108
  [...a1].filter(x => !a2.has(x)).map(t => view.hideTrack(t));
212
- [...a2].filter(x => !a1.has(x)).map(t => view.showTrack(t));
109
+ [...a2]
110
+ .filter(x => !a1.has(x))
111
+ .map(t => {
112
+ view.showTrack(t);
113
+ model.addToRecentlyUsed(t);
114
+ });
213
115
  });
214
116
  }
215
117
  else {
216
118
  const root = (0, mobx_state_tree_1.getRoot)(model);
217
119
  const schema = pluginManager.pluggableConfigSchemaType('track');
218
- const tracks = userSelectedIds.map(id => (0, mobx_state_tree_1.resolveIdentifier)(schema, root, id));
219
- model.setSelection(tracks);
120
+ model.setSelection(userSelectedIds.map(id => (0, mobx_state_tree_1.resolveIdentifier)(schema, root, id)));
220
121
  }
221
122
  }, rowSelectionModel: useShoppingCart
222
123
  ? selection.map(s => s.trackId)
223
124
  : [...shownTrackIds], slots: { toolbar: showOptions ? x_data_grid_1.GridToolbar : null }, slotProps: {
224
- toolbar: { printOptions: { disableToolbarButton: true } },
125
+ toolbar: {
126
+ printOptions: {
127
+ disableToolbarButton: true,
128
+ },
129
+ },
225
130
  }, columns: columns, rowHeight: 25 })),
226
131
  showFilters ? (react_1.default.createElement(react_1.default.Fragment, null,
227
- react_1.default.createElement(ui_1.ResizeHandle, { vertical: true, onDrag: dist => setPanelWidth(panelWidth - dist), style: { marginLeft: 5, background: 'grey', width: 5 } }),
132
+ react_1.default.createElement(ui_1.ResizeHandle, { vertical: true, onDrag: dist => faceted.setPanelWidth(panelWidth - dist), className: classes.resizeHandle }),
228
133
  react_1.default.createElement("div", { style: {
229
134
  width: panelWidth,
230
135
  overflowY: 'auto',
231
136
  overflowX: 'hidden',
232
137
  } },
233
- react_1.default.createElement(FacetFilters_1.default, { width: panelWidth - 10, rows: rows, columns: columns, dispatch: dispatch, filters: filters })))) : null)));
138
+ react_1.default.createElement(FacetFilters_1.default, { model: model, width: panelWidth - 10, rows: rows, columns: columns })))) : null)));
234
139
  });
235
140
  exports.default = FacetedSelector;
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+ import { AnyConfigurationModel } from '@jbrowse/core/configuration';
3
+ import { MenuItem } from '@jbrowse/core/ui/Menu';
4
+ import { HierarchicalTrackSelectorModel } from '../../model';
5
+ declare const DropdownTrackSelector: ({ model, tracks, extraMenuItems, children, onClick, }: {
6
+ model: HierarchicalTrackSelectorModel;
7
+ tracks: AnyConfigurationModel[];
8
+ extraMenuItems: MenuItem[];
9
+ onClick?: (() => void) | undefined;
10
+ children: React.ReactElement;
11
+ }) => React.JSX.Element | null;
12
+ export default DropdownTrackSelector;
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ const react_1 = __importStar(require("react"));
30
+ const mobx_react_1 = require("mobx-react");
31
+ const CascadingMenuButton_1 = __importDefault(require("@jbrowse/core/ui/CascadingMenuButton"));
32
+ const SanitizedHTML_1 = __importDefault(require("@jbrowse/core/ui/SanitizedHTML"));
33
+ const tracks_1 = require("@jbrowse/core/util/tracks");
34
+ const util_1 = require("@jbrowse/core/util");
35
+ const TrackLabelMenu_1 = __importDefault(require("./TrackLabelMenu"));
36
+ const DropdownTrackSelector = (0, mobx_react_1.observer)(function ({ model, tracks, extraMenuItems, children, onClick, }) {
37
+ const { view } = model;
38
+ const [open, setOpen] = (0, react_1.useState)(false);
39
+ const session = (0, util_1.getSession)(model);
40
+ return view ? (react_1.default.createElement(CascadingMenuButton_1.default, { closeAfterItemClick: false, onClick: onClick, menuItems: [
41
+ ...tracks.map(t => ({
42
+ type: 'checkbox',
43
+ label: (react_1.default.createElement(react_1.default.Fragment, null,
44
+ react_1.default.createElement(SanitizedHTML_1.default, { html: (0, tracks_1.getTrackName)(t, session) }),
45
+ ' ',
46
+ react_1.default.createElement(TrackLabelMenu_1.default, { id: t.trackId, trackId: t.trackId, model: model, conf: t, setOpen: setOpen, stopPropagation: true }))),
47
+ checked: view.tracks.some((f) => f.configuration === t),
48
+ onClick: () => {
49
+ if (!open) {
50
+ model.view.toggleTrack(t.trackId);
51
+ }
52
+ },
53
+ })),
54
+ ...extraMenuItems,
55
+ ] }, children)) : null;
56
+ });
57
+ exports.default = DropdownTrackSelector;
@@ -0,0 +1,6 @@
1
+ import React from 'react';
2
+ import { HierarchicalTrackSelectorModel } from '../../model';
3
+ declare const FavoriteTracks: ({ model, }: {
4
+ model: HierarchicalTrackSelectorModel;
5
+ }) => React.JSX.Element | null;
6
+ export default FavoriteTracks;
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const react_1 = __importDefault(require("react"));
7
+ const material_1 = require("@mui/material");
8
+ const mobx_react_1 = require("mobx-react");
9
+ // icons
10
+ const Grade_1 = __importDefault(require("@mui/icons-material/Grade"));
11
+ const DropdownTrackSelector_1 = __importDefault(require("./DropdownTrackSelector"));
12
+ const mui_1 = require("tss-react/mui");
13
+ const useStyles = (0, mui_1.makeStyles)()({
14
+ smallBadge: {
15
+ height: 14,
16
+ },
17
+ });
18
+ const FavoriteTracks = (0, mobx_react_1.observer)(function ({ model, }) {
19
+ const { classes } = useStyles();
20
+ const { view, favoriteTracks } = model;
21
+ return view ? (react_1.default.createElement(DropdownTrackSelector_1.default, { onClick: () => model.setFavoritesCounter(0), tracks: favoriteTracks, model: model, extraMenuItems: favoriteTracks.length
22
+ ? [
23
+ { type: 'divider' },
24
+ {
25
+ label: 'Clear favorites',
26
+ onClick: () => model.clearFavorites(),
27
+ },
28
+ ]
29
+ : [
30
+ {
31
+ label: 'No favorite tracks yet',
32
+ onClick: () => { },
33
+ },
34
+ ] },
35
+ react_1.default.createElement(material_1.Tooltip, { title: "Favorite tracks" },
36
+ react_1.default.createElement(material_1.Badge, { classes: { badge: classes.smallBadge }, color: "secondary", anchorOrigin: {
37
+ vertical: 'bottom',
38
+ horizontal: 'right',
39
+ }, style: { marginRight: 10 }, badgeContent: model.favoritesCounter },
40
+ react_1.default.createElement(Grade_1.default, null))))) : null;
41
+ });
42
+ exports.default = FavoriteTracks;
@@ -33,6 +33,8 @@ const configuration_1 = require("@jbrowse/core/configuration");
33
33
  const CascadingMenuButton_1 = __importDefault(require("@jbrowse/core/ui/CascadingMenuButton"));
34
34
  // icons
35
35
  const Menu_1 = __importDefault(require("@mui/icons-material/Menu"));
36
+ // lazies
37
+ const FacetedDialog = (0, react_1.lazy)(() => Promise.resolve().then(() => __importStar(require('../faceted/FacetedDialog'))));
36
38
  // lazy components
37
39
  const CloseConnectionDlg = (0, react_1.lazy)(() => Promise.resolve().then(() => __importStar(require('../dialogs/CloseConnectionDialog'))));
38
40
  const DeleteConnectionDlg = (0, react_1.lazy)(() => Promise.resolve().then(() => __importStar(require('../dialogs/DeleteConnectionDialog'))));
@@ -44,6 +46,7 @@ const HamburgerMenu = (0, mobx_react_1.observer)(function ({ model, }) {
44
46
  const [deleteDlgDetails, setDeleteDlgDetails] = (0, react_1.useState)();
45
47
  const [connectionToggleOpen, setConnectionToggleOpen] = (0, react_1.useState)(false);
46
48
  const [connectionManagerOpen, setConnectionManagerOpen] = (0, react_1.useState)(false);
49
+ const [facetedOpen, setFacetedOpen] = (0, react_1.useState)(false);
47
50
  function breakConnection(connectionConf, deletingConnection) {
48
51
  var _a;
49
52
  const name = (0, configuration_1.readConfObject)(connectionConf, 'name');
@@ -68,6 +71,12 @@ const HamburgerMenu = (0, mobx_react_1.observer)(function ({ model, }) {
68
71
  }
69
72
  return (react_1.default.createElement(react_1.default.Fragment, null,
70
73
  react_1.default.createElement(CascadingMenuButton_1.default, { menuItems: [
74
+ {
75
+ label: 'Open faceted track selector',
76
+ onClick: () => {
77
+ setFacetedOpen(true);
78
+ },
79
+ },
71
80
  ...((0, util_1.isSessionWithAddTracks)(session)
72
81
  ? [
73
82
  {
@@ -82,59 +91,74 @@ const HamburgerMenu = (0, mobx_react_1.observer)(function ({ model, }) {
82
91
  },
83
92
  ]
84
93
  : []),
85
- ...((0, util_1.isSessionModelWithConnections)(session)
86
- ? [
94
+ {
95
+ label: 'Connections...',
96
+ subMenu: [
97
+ ...((0, util_1.isSessionModelWithConnections)(session)
98
+ ? [
99
+ {
100
+ label: 'Turn on/off connections...',
101
+ onClick: () => setConnectionToggleOpen(true),
102
+ },
103
+ ]
104
+ : []),
105
+ ...((0, util_1.isSessionModelWithConnectionEditing)(session)
106
+ ? [
107
+ {
108
+ label: 'Add connection...',
109
+ onClick: () => {
110
+ if ((0, util_1.isSessionModelWithWidgets)(session)) {
111
+ session.showWidget(session.addWidget('AddConnectionWidget', 'addConnectionWidget'));
112
+ }
113
+ },
114
+ },
115
+ {
116
+ label: 'Delete connections...',
117
+ onClick: () => setConnectionManagerOpen(true),
118
+ },
119
+ ]
120
+ : []),
121
+ ],
122
+ },
123
+ {
124
+ label: 'Sort...',
125
+ type: 'subMenu',
126
+ subMenu: [
87
127
  {
88
- label: 'Turn on/off connections...',
89
- onClick: () => setConnectionToggleOpen(true),
128
+ label: 'Sort tracks by name',
129
+ type: 'checkbox',
130
+ checked: model.activeSortTrackNames,
131
+ onClick: () => model.setSortTrackNames(!model.activeSortTrackNames),
90
132
  },
91
- ]
92
- : []),
93
- ...((0, util_1.isSessionModelWithConnectionEditing)(session)
94
- ? [
95
133
  {
96
- label: 'Add connection...',
97
- onClick: () => {
98
- if ((0, util_1.isSessionModelWithWidgets)(session)) {
99
- session.showWidget(session.addWidget('AddConnectionWidget', 'addConnectionWidget'));
100
- }
101
- },
134
+ label: 'Sort categories by name',
135
+ type: 'checkbox',
136
+ checked: model.activeSortCategories,
137
+ onClick: () => model.setSortCategories(!model.activeSortCategories),
102
138
  },
103
- {
104
- label: 'Delete connections...',
105
- onClick: () => setConnectionManagerOpen(true),
106
- },
107
- ]
108
- : []),
109
- { type: 'divider' },
110
- {
111
- label: 'Sort tracks by name',
112
- type: 'checkbox',
113
- checked: model.activeSortTrackNames,
114
- onClick: () => model.setSortTrackNames(!model.activeSortTrackNames),
139
+ ],
115
140
  },
116
141
  {
117
- label: 'Sort categories by name',
118
- type: 'checkbox',
119
- checked: model.activeSortCategories,
120
- onClick: () => model.setSortCategories(!model.activeSortCategories),
121
- },
122
- { type: 'divider' },
123
- ...(model.hasAnySubcategories
124
- ? [
142
+ label: 'Collapse...',
143
+ type: 'subMenu',
144
+ subMenu: [
145
+ ...(model.hasAnySubcategories
146
+ ? [
147
+ {
148
+ label: 'Collapse subcategories',
149
+ onClick: () => model.collapseSubCategories(),
150
+ },
151
+ ]
152
+ : []),
125
153
  {
126
- label: 'Collapse subcategories',
127
- onClick: () => model.collapseSubCategories(),
154
+ label: 'Collapse top-level categories',
155
+ onClick: () => model.collapseTopLevelCategories(),
128
156
  },
129
- ]
130
- : []),
131
- {
132
- label: 'Collapse top-level categories',
133
- onClick: () => model.collapseTopLevelCategories(),
134
- },
135
- {
136
- label: 'Expand all categories',
137
- onClick: () => model.expandAllCategories(),
157
+ {
158
+ label: 'Expand all categories',
159
+ onClick: () => model.expandAllCategories(),
160
+ },
161
+ ],
138
162
  },
139
163
  ] },
140
164
  react_1.default.createElement(Menu_1.default, null)),
@@ -142,6 +166,7 @@ const HamburgerMenu = (0, mobx_react_1.observer)(function ({ model, }) {
142
166
  modalInfo ? (react_1.default.createElement(CloseConnectionDlg, { modalInfo: modalInfo, onClose: () => setModalInfo(undefined) })) : null,
143
167
  deleteDlgDetails ? (react_1.default.createElement(DeleteConnectionDlg, { handleClose: () => setDeleteDlgDetails(undefined), deleteDialogDetails: deleteDlgDetails, session: session })) : null,
144
168
  connectionManagerOpen ? (react_1.default.createElement(ManageConnectionsDlg, { handleClose: () => setConnectionManagerOpen(false), breakConnection: breakConnection, session: session })) : null,
145
- connectionToggleOpen ? (react_1.default.createElement(ToggleConnectionsDlg, { handleClose: () => setConnectionToggleOpen(false), session: session, breakConnection: breakConnection })) : null)));
169
+ connectionToggleOpen ? (react_1.default.createElement(ToggleConnectionsDlg, { handleClose: () => setConnectionToggleOpen(false), session: session, breakConnection: breakConnection })) : null,
170
+ facetedOpen ? (react_1.default.createElement(FacetedDialog, { handleClose: () => setFacetedOpen(false), model: model })) : null)));
146
171
  });
147
172
  exports.default = HamburgerMenu;
@@ -1,32 +1,9 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
2
  var __importDefault = (this && this.__importDefault) || function (mod) {
26
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
27
4
  };
28
5
  Object.defineProperty(exports, "__esModule", { value: true });
29
- const react_1 = __importStar(require("react"));
6
+ const react_1 = __importDefault(require("react"));
30
7
  const material_1 = require("@mui/material");
31
8
  const mui_1 = require("tss-react/mui");
32
9
  const mobx_react_1 = require("mobx-react");
@@ -34,16 +11,12 @@ const mobx_react_1 = require("mobx-react");
34
11
  const Clear_1 = __importDefault(require("@mui/icons-material/Clear"));
35
12
  const HamburgerMenu_1 = __importDefault(require("./HamburgerMenu"));
36
13
  const ShoppingCart_1 = __importDefault(require("../ShoppingCart"));
37
- // lazies
38
- const FacetedDialog = (0, react_1.lazy)(() => Promise.resolve().then(() => __importStar(require('../faceted/FacetedDialog'))));
14
+ const FavoriteTracks_1 = __importDefault(require("./FavoriteTracks"));
15
+ const RecentlyUsedTracks_1 = __importDefault(require("./RecentlyUsedTracks"));
39
16
  const useStyles = (0, mui_1.makeStyles)()(theme => ({
40
17
  searchBox: {
41
18
  margin: theme.spacing(2),
42
19
  },
43
- menuIcon: {
44
- marginRight: theme.spacing(1),
45
- marginBottom: 0,
46
- },
47
20
  }));
48
21
  const SearchTracksTextField = (0, mobx_react_1.observer)(function ({ model, }) {
49
22
  const { filterText } = model;
@@ -55,14 +28,12 @@ const SearchTracksTextField = (0, mobx_react_1.observer)(function ({ model, }) {
55
28
  } }));
56
29
  });
57
30
  const HierarchicalTrackSelectorHeader = (0, mobx_react_1.observer)(function ({ model, setHeaderHeight, }) {
58
- const { classes } = useStyles();
59
- const [facetedOpen, setFacetedOpen] = (0, react_1.useState)(false);
60
31
  return (react_1.default.createElement("div", { ref: ref => setHeaderHeight((ref === null || ref === void 0 ? void 0 : ref.getBoundingClientRect().height) || 0), "data-testid": "hierarchical_track_selector" },
61
32
  react_1.default.createElement("div", { style: { display: 'flex' } },
62
33
  react_1.default.createElement(HamburgerMenu_1.default, { model: model }),
63
34
  react_1.default.createElement(ShoppingCart_1.default, { model: model }),
64
35
  react_1.default.createElement(SearchTracksTextField, { model: model }),
65
- react_1.default.createElement(material_1.Button, { className: classes.menuIcon, onClick: () => setFacetedOpen(true) }, "Open faceted selector")),
66
- react_1.default.createElement(react_1.Suspense, { fallback: react_1.default.createElement("div", null) }, facetedOpen ? (react_1.default.createElement(FacetedDialog, { handleClose: () => setFacetedOpen(false), model: model })) : null)));
36
+ react_1.default.createElement(RecentlyUsedTracks_1.default, { model: model }),
37
+ react_1.default.createElement(FavoriteTracks_1.default, { model: model }))));
67
38
  });
68
39
  exports.default = HierarchicalTrackSelectorHeader;
@@ -32,8 +32,8 @@ const react_vtree_1 = require("react-vtree");
32
32
  const util_1 = require("@jbrowse/core/util");
33
33
  const TrackListNode_1 = __importDefault(require("./TrackListNode"));
34
34
  function getNodeData(node, nestingLevel, extra, selection) {
35
- const isLeaf = !!node.conf;
36
- const selected = !!selection[node.id];
35
+ const isLeaf = node.type === 'track';
36
+ const selected = isLeaf ? selection[node.trackId] : false;
37
37
  return {
38
38
  data: {
39
39
  defaultHeight: isLeaf ? 22 : 40,
@@ -58,7 +58,12 @@ const HierarchicalTree = (0, mobx_react_1.observer)(function HierarchicalTree({
58
58
  const { drawerPosition } = session;
59
59
  const obj = (0, react_1.useMemo)(() => Object.fromEntries(selection.map(s => [s.trackId, s])), [selection]);
60
60
  const extra = (0, react_1.useMemo)(() => ({
61
- onChange: (trackId) => view.toggleTrack(trackId),
61
+ onChange: (trackId) => {
62
+ const trackTurnedOn = view.toggleTrack(trackId);
63
+ if (trackTurnedOn) {
64
+ model.addToRecentlyUsed(trackId);
65
+ }
66
+ },
62
67
  toggleCollapse: (pathName) => model.toggleCategory(pathName),
63
68
  tree,
64
69
  model,