@jbrowse/plugin-data-management 1.5.0 → 1.5.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/dist/AddTrackWidget/model.d.ts +1 -434
  2. package/dist/AssemblyManager/AssemblyTable.d.ts +8 -2
  3. package/dist/PluginStoreWidget/components/CustomPluginForm.d.ts +1 -1
  4. package/dist/PluginStoreWidget/components/PluginCard.d.ts +2 -2
  5. package/dist/SetDefaultSession/SetDefaultSession.d.ts +4 -6
  6. package/dist/index.d.ts +8 -12
  7. package/dist/plugin-data-management.cjs.development.js +387 -324
  8. package/dist/plugin-data-management.cjs.development.js.map +1 -1
  9. package/dist/plugin-data-management.cjs.production.min.js +1 -1
  10. package/dist/plugin-data-management.cjs.production.min.js.map +1 -1
  11. package/dist/plugin-data-management.esm.js +389 -326
  12. package/dist/plugin-data-management.esm.js.map +1 -1
  13. package/package.json +3 -2
  14. package/src/AddTrackWidget/components/AddTrackWidget.test.js +1 -1
  15. package/src/AddTrackWidget/components/AddTrackWidget.tsx +3 -1
  16. package/src/AddTrackWidget/components/ConfirmTrack.tsx +101 -32
  17. package/src/AddTrackWidget/components/TrackSourceSelect.tsx +2 -3
  18. package/src/AddTrackWidget/index.test.jsx +34 -15
  19. package/src/AddTrackWidget/model.ts +5 -14
  20. package/src/AssemblyManager/AssemblyManager.tsx +3 -1
  21. package/src/AssemblyManager/AssemblyTable.tsx +40 -39
  22. package/src/HierarchicalTrackSelectorWidget/model.js +3 -2
  23. package/src/PluginStoreWidget/components/CustomPluginForm.tsx +164 -56
  24. package/src/PluginStoreWidget/components/InstalledPlugin.tsx +16 -11
  25. package/src/PluginStoreWidget/components/PluginCard.tsx +7 -9
  26. package/src/PluginStoreWidget/components/PluginStoreWidget.test.js +8 -7
  27. package/src/PluginStoreWidget/components/PluginStoreWidget.tsx +34 -25
  28. package/src/PluginStoreWidget/components/__snapshots__/PluginStoreWidget.test.js.snap +69 -52
  29. package/src/SetDefaultSession/SetDefaultSession.test.tsx +6 -81
  30. package/src/SetDefaultSession/SetDefaultSession.tsx +51 -162
@@ -40,29 +40,15 @@ var core = require('@material-ui/core');
40
40
  var ExpandMoreIcon = _interopDefault(require('@material-ui/icons/ExpandMore'));
41
41
  var ClearIcon = _interopDefault(require('@material-ui/icons/Clear'));
42
42
  var InfoOutlinedIcon = _interopDefault(require('@material-ui/icons/InfoOutlined'));
43
- var styles = require('@material-ui/core/styles');
44
43
  var CloseIcon = _interopDefault(require('@material-ui/icons/Close'));
45
44
  var LockIcon = _interopDefault(require('@material-ui/icons/Lock'));
46
45
  var types = require('@jbrowse/core/util/types');
47
46
  var PersonIcon = _interopDefault(require('@material-ui/icons/Person'));
48
47
  var AddIcon = _interopDefault(require('@material-ui/icons/Add'));
49
48
  var CheckIcon = _interopDefault(require('@material-ui/icons/Check'));
50
- var Dialog = _interopDefault(require('@material-ui/core/Dialog'));
51
- var DialogTitle = _interopDefault(require('@material-ui/core/DialogTitle'));
52
- var TextField = _interopDefault(require('@material-ui/core/TextField'));
53
- var Button = _interopDefault(require('@material-ui/core/Button'));
49
+ var clsx = _interopDefault(require('clsx'));
54
50
  var IconButton = _interopDefault(require('@material-ui/core/IconButton'));
55
- var DialogContent = _interopDefault(require('@material-ui/core/DialogContent'));
56
- var DialogActions = _interopDefault(require('@material-ui/core/DialogActions'));
57
- var List = _interopDefault(require('@material-ui/core/List'));
58
- var ListItem = _interopDefault(require('@material-ui/core/ListItem'));
59
- var ListItemIcon = _interopDefault(require('@material-ui/core/ListItemIcon'));
60
- var ListItemText = _interopDefault(require('@material-ui/core/ListItemText'));
61
- var ListSubheader = _interopDefault(require('@material-ui/core/ListSubheader'));
62
- var Paper = _interopDefault(require('@material-ui/core/Paper'));
63
- var Typography = _interopDefault(require('@material-ui/core/Typography'));
64
- var Radio = _interopDefault(require('@material-ui/core/Radio'));
65
- var pluralize = _interopDefault(require('pluralize'));
51
+ var styles = require('@material-ui/core/styles');
66
52
  var ArrowBackIosIcon = _interopDefault(require('@material-ui/icons/ArrowBackIos'));
67
53
  var CreateIcon = _interopDefault(require('@material-ui/icons/Create'));
68
54
  var DeleteIcon = _interopDefault(require('@material-ui/icons/Delete'));
@@ -76,14 +62,16 @@ var PowerOutlinedIcon = _interopDefault(require('@material-ui/icons/PowerOutline
76
62
  var AutoSizer = _interopDefault(require('react-virtualized-auto-sizer'));
77
63
  var JBrowseMenu = _interopDefault(require('@jbrowse/core/ui/Menu'));
78
64
  var reactVtree = require('react-vtree');
79
- var Link = _interopDefault(require('@material-ui/core/Link'));
80
- var MenuItem = _interopDefault(require('@material-ui/core/MenuItem'));
81
- var ui = require('@jbrowse/core/ui');
82
65
  var lab = require('@material-ui/lab');
66
+ var ui = require('@jbrowse/core/ui');
67
+ var Button = _interopDefault(require('@material-ui/core/Button'));
83
68
  var Step = _interopDefault(require('@material-ui/core/Step'));
84
69
  var StepContent = _interopDefault(require('@material-ui/core/StepContent'));
85
70
  var StepLabel = _interopDefault(require('@material-ui/core/StepLabel'));
86
71
  var Stepper = _interopDefault(require('@material-ui/core/Stepper'));
72
+ var Typography = _interopDefault(require('@material-ui/core/Typography'));
73
+ var MenuItem = _interopDefault(require('@material-ui/core/MenuItem'));
74
+ var TextField = _interopDefault(require('@material-ui/core/TextField'));
87
75
  var OpenInNewIcon = _interopDefault(require('@material-ui/icons/OpenInNew'));
88
76
 
89
77
  function ownKeys(object, enumerableOnly) {
@@ -91,14 +79,9 @@ function ownKeys(object, enumerableOnly) {
91
79
 
92
80
  if (Object.getOwnPropertySymbols) {
93
81
  var symbols = Object.getOwnPropertySymbols(object);
94
-
95
- if (enumerableOnly) {
96
- symbols = symbols.filter(function (sym) {
97
- return Object.getOwnPropertyDescriptor(object, sym).enumerable;
98
- });
99
- }
100
-
101
- keys.push.apply(keys, symbols);
82
+ enumerableOnly && (symbols = symbols.filter(function (sym) {
83
+ return Object.getOwnPropertyDescriptor(object, sym).enumerable;
84
+ })), keys.push.apply(keys, symbols);
102
85
  }
103
86
 
104
87
  return keys;
@@ -106,19 +89,12 @@ function ownKeys(object, enumerableOnly) {
106
89
 
107
90
  function _objectSpread2(target) {
108
91
  for (var i = 1; i < arguments.length; i++) {
109
- var source = arguments[i] != null ? arguments[i] : {};
110
-
111
- if (i % 2) {
112
- ownKeys(Object(source), true).forEach(function (key) {
113
- _defineProperty(target, key, source[key]);
114
- });
115
- } else if (Object.getOwnPropertyDescriptors) {
116
- Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
117
- } else {
118
- ownKeys(Object(source)).forEach(function (key) {
119
- Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
120
- });
121
- }
92
+ var source = null != arguments[i] ? arguments[i] : {};
93
+ i % 2 ? ownKeys(Object(source), !0).forEach(function (key) {
94
+ _defineProperty(target, key, source[key]);
95
+ }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) {
96
+ Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
97
+ });
122
98
  }
123
99
 
124
100
  return target;
@@ -127,17 +103,11 @@ function _objectSpread2(target) {
127
103
  function _typeof(obj) {
128
104
  "@babel/helpers - typeof";
129
105
 
130
- if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
131
- _typeof = function (obj) {
132
- return typeof obj;
133
- };
134
- } else {
135
- _typeof = function (obj) {
136
- return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
137
- };
138
- }
139
-
140
- return _typeof(obj);
106
+ return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) {
107
+ return typeof obj;
108
+ } : function (obj) {
109
+ return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
110
+ }, _typeof(obj);
141
111
  }
142
112
 
143
113
  function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
@@ -195,6 +165,9 @@ function _defineProperties(target, props) {
195
165
  function _createClass(Constructor, protoProps, staticProps) {
196
166
  if (protoProps) _defineProperties(Constructor.prototype, protoProps);
197
167
  if (staticProps) _defineProperties(Constructor, staticProps);
168
+ Object.defineProperty(Constructor, "prototype", {
169
+ writable: false
170
+ });
198
171
  return Constructor;
199
172
  }
200
173
 
@@ -218,12 +191,15 @@ function _inherits(subClass, superClass) {
218
191
  throw new TypeError("Super expression must either be null or a function");
219
192
  }
220
193
 
221
- subClass.prototype = Object.create(superClass && superClass.prototype, {
222
- constructor: {
223
- value: subClass,
224
- writable: true,
225
- configurable: true
226
- }
194
+ Object.defineProperty(subClass, "prototype", {
195
+ value: Object.create(superClass && superClass.prototype, {
196
+ constructor: {
197
+ value: subClass,
198
+ writable: true,
199
+ configurable: true
200
+ }
201
+ }),
202
+ writable: false
227
203
  });
228
204
  if (superClass) _setPrototypeOf(subClass, superClass);
229
205
  }
@@ -1745,13 +1721,6 @@ function isAbsoluteUrl() {
1745
1721
  }
1746
1722
  }
1747
1723
 
1748
- function getFileName(track) {
1749
- var uri = 'uri' in track ? track.uri : undefined;
1750
- var localPath = 'localPath' in track ? track.localPath : undefined;
1751
- var blob = 'blobId' in track ? track : undefined;
1752
- return (blob === null || blob === void 0 ? void 0 : blob.name) || (uri === null || uri === void 0 ? void 0 : uri.slice(uri.lastIndexOf('/') + 1)) || (localPath === null || localPath === void 0 ? void 0 : localPath.slice(localPath.lastIndexOf('/') + 1)) || '';
1753
- }
1754
-
1755
1724
  function f(pluginManager) {
1756
1725
  return mobxStateTree.types.model('AddTrackModel', {
1757
1726
  id: mst.ElementId,
@@ -1807,11 +1776,11 @@ function f(pluginManager) {
1807
1776
  var trackData = self.trackData,
1808
1777
  indexTrackData = self.indexTrackData,
1809
1778
  adapterHint = self.adapterHint;
1810
- return trackData ? tracks.guessAdapter(trackData, indexTrackData, getFileName, adapterHint) : undefined;
1779
+ return trackData ? tracks.guessAdapter(trackData, indexTrackData, adapterHint, self) : undefined;
1811
1780
  },
1812
1781
 
1813
1782
  get trackName() {
1814
- return self.altTrackName || (self.trackData ? getFileName(self.trackData) : '');
1783
+ return self.altTrackName || (self.trackData ? tracks.getFileName(self.trackData) : '');
1815
1784
  },
1816
1785
 
1817
1786
  get isFtp() {
@@ -1819,7 +1788,8 @@ function f(pluginManager) {
1819
1788
 
1820
1789
  var track = self.trackData,
1821
1790
  index = self.indexTrackData;
1822
- return !!(index !== null && index !== void 0 && (_index$uri = index.uri) !== null && _index$uri !== void 0 && _index$uri.startsWith('ftp://') || track !== null && track !== void 0 && (_track$uri = track.uri) !== null && _track$uri !== void 0 && _track$uri.startsWith('ftp://'));
1791
+ return !!( // @ts-ignore
1792
+ index !== null && index !== void 0 && (_index$uri = index.uri) !== null && _index$uri !== void 0 && _index$uri.startsWith('ftp://') || track !== null && track !== void 0 && (_track$uri = track.uri) !== null && _track$uri !== void 0 && _track$uri.startsWith('ftp://'));
1823
1793
  },
1824
1794
 
1825
1795
  get isRelativeTrackUrl() {
@@ -1873,7 +1843,7 @@ function f(pluginManager) {
1873
1843
  },
1874
1844
 
1875
1845
  get trackType() {
1876
- return self.altTrackType || (this.trackAdapter ? tracks.guessTrackType(this.trackAdapter.type) : '');
1846
+ return self.altTrackType || (this.trackAdapter ? tracks.guessTrackType(this.trackAdapter.type, self) : '');
1877
1847
  }
1878
1848
 
1879
1849
  };
@@ -1915,9 +1885,9 @@ var hasAnyOverlap = function hasAnyOverlap() {
1915
1885
  function passesFilter(filter, config) {
1916
1886
  var name = getTrackName(config);
1917
1887
  var categories = configuration.readConfObject(config, 'category') || [];
1918
- var regexp = new RegExp(filter, 'i');
1919
- return !!name.match(regexp) || categories.filter(function (cat) {
1920
- return !!cat.match(regexp);
1888
+ var filterLower = filter.toLowerCase();
1889
+ return !!name.toLowerCase().includes(filterLower) || categories.filter(function (cat) {
1890
+ return !!cat.toLowerCase().includes(filterLower);
1921
1891
  }).length;
1922
1892
  }
1923
1893
 
@@ -2183,7 +2153,7 @@ var HierarchicalTrackSelectorStateModelFactory = (function (pluginManager) {
2183
2153
 
2184
2154
  var configSchema$2 = /*#__PURE__*/configuration.ConfigurationSchema('HierarchicalTrackSelectorWidget', {});
2185
2155
 
2186
- var useStyles = /*#__PURE__*/styles.makeStyles(function () {
2156
+ var useStyles = /*#__PURE__*/core.makeStyles(function () {
2187
2157
  return {
2188
2158
  closeDialog: {
2189
2159
  position: 'absolute',
@@ -2192,15 +2162,17 @@ var useStyles = /*#__PURE__*/styles.makeStyles(function () {
2192
2162
  },
2193
2163
  dialogContainer: {
2194
2164
  margin: 15
2165
+ },
2166
+ lockedPluginTooltip: {
2167
+ marginRight: '0.5rem'
2195
2168
  }
2196
2169
  };
2197
2170
  });
2198
2171
 
2199
2172
  function LockedPlugin() {
2173
+ var classes = useStyles();
2200
2174
  return /*#__PURE__*/React__default.createElement(core.Tooltip, {
2201
- style: {
2202
- marginRight: '0.5rem'
2203
- },
2175
+ className: classes.lockedPluginTooltip,
2204
2176
  title: "This plugin was installed by an administrator, you cannot remove it."
2205
2177
  }, /*#__PURE__*/React__default.createElement(LockIcon, null));
2206
2178
  }
@@ -2220,7 +2192,7 @@ function PluginDialog(_ref) {
2220
2192
  onClick: function onClick() {
2221
2193
  return _onClose();
2222
2194
  }
2223
- }, /*#__PURE__*/React__default.createElement(CloseIcon, null))), /*#__PURE__*/React__default.createElement(core.DialogContent, null, /*#__PURE__*/React__default.createElement(core.Typography, null, "Please confirm that you want to remove ", plugin, ":"), /*#__PURE__*/React__default.createElement(core.DialogActions, null, /*#__PURE__*/React__default.createElement(core.Button, {
2195
+ }, /*#__PURE__*/React__default.createElement(CloseIcon, null))), /*#__PURE__*/React__default.createElement(core.DialogContent, null, /*#__PURE__*/React__default.createElement(core.Typography, null, "Please confirm that you want to remove ", plugin, ". Note: if any resources in this session still use this plugin, it may cause your session to crash"), /*#__PURE__*/React__default.createElement(core.DialogActions, null, /*#__PURE__*/React__default.createElement(core.Button, {
2224
2196
  variant: "contained",
2225
2197
  color: "primary",
2226
2198
  onClick: function onClick() {
@@ -2248,8 +2220,7 @@ function InstalledPlugin(_ref2) {
2248
2220
  dialogPlugin = _useState2[0],
2249
2221
  setDialogPlugin = _useState2[1];
2250
2222
 
2251
- var session = util.getSession(model); // @ts-ignore
2252
-
2223
+ var session = util.getSession(model);
2253
2224
  var sessionPlugins = session.sessionPlugins;
2254
2225
  var isSessionPlugin = sessionPlugins === null || sessionPlugins === void 0 ? void 0 : sessionPlugins.some(function (p) {
2255
2226
  return pluginManager.pluginMetadata[plugin.name].url === p.url;
@@ -2262,12 +2233,11 @@ function InstalledPlugin(_ref2) {
2262
2233
  onClose: function onClose(name) {
2263
2234
  if (name) {
2264
2235
  var pluginMetadata = pluginManager.pluginMetadata[plugin.name];
2265
- var pluginUrl = pluginMetadata.url;
2266
2236
 
2267
2237
  if (adminMode) {
2268
- jbrowse.removePlugin(pluginUrl);
2238
+ jbrowse.removePlugin(pluginMetadata);
2269
2239
  } else if (types.isSessionWithSessionPlugins(session)) {
2270
- session.removeSessionPlugin(pluginUrl);
2240
+ session.removeSessionPlugin(pluginMetadata);
2271
2241
  }
2272
2242
  }
2273
2243
 
@@ -2314,7 +2284,7 @@ function InstalledPluginsList(_ref) {
2314
2284
 
2315
2285
  var InstalledPluginsList$1 = /*#__PURE__*/mobxReact.observer(InstalledPluginsList);
2316
2286
 
2317
- var useStyles$1 = /*#__PURE__*/styles.makeStyles(function () {
2287
+ var useStyles$1 = /*#__PURE__*/core.makeStyles(function () {
2318
2288
  return {
2319
2289
  card: {
2320
2290
  margin: '1em'
@@ -2398,101 +2368,194 @@ function PluginCard(_ref) {
2398
2368
 
2399
2369
  var PluginCard$1 = /*#__PURE__*/mobxReact.observer(PluginCard);
2400
2370
 
2401
- var useStyles$2 = /*#__PURE__*/styles.makeStyles(function () {
2371
+ var useStyles$2 = /*#__PURE__*/core.makeStyles(function (theme) {
2402
2372
  return {
2403
- closeDialog: {
2373
+ closeButton: {
2404
2374
  position: 'absolute',
2405
- right: 0,
2406
- top: 0
2375
+ right: theme.spacing(1),
2376
+ top: theme.spacing(1)
2407
2377
  },
2408
- dialogContainer: {
2409
- margin: 15,
2378
+ dialogContent: {
2410
2379
  display: 'flex',
2411
2380
  flexDirection: 'column'
2381
+ },
2382
+ expand: {
2383
+ transform: 'rotate(0deg)',
2384
+ marginLeft: 'auto',
2385
+ transition: theme.transitions.create('transform', {
2386
+ duration: theme.transitions.duration.shortest
2387
+ })
2388
+ },
2389
+ expandOpen: {
2390
+ transform: 'rotate(180deg)'
2412
2391
  }
2413
2392
  };
2414
2393
  });
2415
2394
 
2416
2395
  function CustomPluginForm(_ref) {
2417
2396
  var open = _ref.open,
2418
- _onClose = _ref.onClose,
2397
+ onClose = _ref.onClose,
2419
2398
  model = _ref.model;
2420
2399
  var classes = useStyles$2();
2421
2400
 
2422
- var _useState = React.useState({
2423
- name: '',
2424
- url: ''
2425
- }),
2401
+ var _useState = React.useState(''),
2426
2402
  _useState2 = _slicedToArray(_useState, 2),
2427
- formInput = _useState2[0],
2428
- setFormInput = _useState2[1];
2403
+ umdPluginName = _useState2[0],
2404
+ setUMDPluginName = _useState2[1];
2429
2405
 
2430
- var handleChange = function handleChange(event) {
2431
- setFormInput(_objectSpread2(_objectSpread2({}, formInput), {}, _defineProperty({}, event.target.name, event.target.value)));
2432
- };
2406
+ var _useState3 = React.useState(''),
2407
+ _useState4 = _slicedToArray(_useState3, 2),
2408
+ umdPluginUrl = _useState4[0],
2409
+ setUMDPluginUrl = _useState4[1];
2410
+
2411
+ var _useState5 = React.useState(''),
2412
+ _useState6 = _slicedToArray(_useState5, 2),
2413
+ esmPluginUrl = _useState6[0],
2414
+ setESMPluginUrl = _useState6[1];
2415
+
2416
+ var _useState7 = React.useState(''),
2417
+ _useState8 = _slicedToArray(_useState7, 2),
2418
+ cjsPluginUrl = _useState8[0],
2419
+ setCJSPluginUrl = _useState8[1];
2420
+
2421
+ var _useState9 = React.useState(false),
2422
+ _useState10 = _slicedToArray(_useState9, 2),
2423
+ advancedOptionsOpen = _useState10[0],
2424
+ setAdvancedOptionsOpen = _useState10[1];
2425
+
2426
+ function handleChange(event) {
2427
+ var _event$target = event.target,
2428
+ name = _event$target.name,
2429
+ value = _event$target.value;
2430
+
2431
+ if (name === 'umdName') {
2432
+ setUMDPluginName(value);
2433
+ }
2434
+
2435
+ if (name === 'umdUrl') {
2436
+ setUMDPluginUrl(value);
2437
+ }
2438
+
2439
+ if (name === 'esmUrl') {
2440
+ setESMPluginUrl(value);
2441
+ }
2442
+
2443
+ if (name === 'cjsUrl') {
2444
+ setCJSPluginUrl(value);
2445
+ }
2446
+ }
2447
+
2448
+ function handleOpenAdvancedOptions() {
2449
+ setAdvancedOptionsOpen(!advancedOptionsOpen);
2450
+ }
2433
2451
 
2434
2452
  var rootModel = mobxStateTree.getRoot(model);
2435
2453
  var jbrowse = rootModel.jbrowse;
2454
+ var ready = Boolean(umdPluginName && umdPluginUrl || esmPluginUrl || cjsPluginUrl);
2436
2455
 
2437
- var handleSubmit = function handleSubmit() {
2438
- jbrowse.addPlugin({
2439
- name: formInput.name,
2440
- url: formInput.url
2441
- });
2442
- };
2456
+ function handleSubmit() {
2457
+ if (!ready) {
2458
+ return;
2459
+ }
2443
2460
 
2444
- return /*#__PURE__*/React__default.createElement(Dialog, {
2445
- open: open,
2446
- onClose: function onClose() {
2447
- return _onClose(false);
2461
+ var pluginDefinition = {};
2462
+
2463
+ if (umdPluginName && umdPluginUrl) {
2464
+ pluginDefinition.name = umdPluginName;
2465
+ pluginDefinition.umdUrl = umdPluginUrl;
2448
2466
  }
2449
- }, /*#__PURE__*/React__default.createElement(DialogTitle, null, /*#__PURE__*/React__default.createElement(IconButton, {
2450
- className: classes.closeDialog,
2451
- "aria-label": "close-dialog",
2467
+
2468
+ if (esmPluginUrl) {
2469
+ pluginDefinition.esmUrl = esmPluginUrl;
2470
+ }
2471
+
2472
+ if (cjsPluginUrl) {
2473
+ pluginDefinition.cjsUrl = cjsPluginUrl;
2474
+ }
2475
+
2476
+ jbrowse.addPlugin(pluginDefinition);
2477
+ }
2478
+
2479
+ function handleClose() {
2480
+ setUMDPluginName('');
2481
+ setUMDPluginUrl('');
2482
+ setESMPluginUrl('');
2483
+ setCJSPluginUrl('');
2484
+ onClose();
2485
+ }
2486
+
2487
+ return /*#__PURE__*/React__default.createElement(core.Dialog, {
2488
+ open: open,
2489
+ onClose: handleClose
2490
+ }, /*#__PURE__*/React__default.createElement(core.DialogTitle, null, "Add custom plugin", /*#__PURE__*/React__default.createElement(IconButton, {
2491
+ size: "medium",
2492
+ className: classes.closeButton,
2452
2493
  onClick: function onClick() {
2453
- return _onClose(false);
2494
+ return onClose();
2454
2495
  }
2455
- }, /*#__PURE__*/React__default.createElement(CloseIcon, null))), /*#__PURE__*/React__default.createElement("div", {
2456
- className: classes.dialogContainer
2457
- }, /*#__PURE__*/React__default.createElement(TextField, {
2458
- id: "name-input",
2459
- name: "name",
2496
+ }, /*#__PURE__*/React__default.createElement(CloseIcon, null))), /*#__PURE__*/React__default.createElement("form", {
2497
+ onSubmit: handleSubmit
2498
+ }, /*#__PURE__*/React__default.createElement(core.DialogContent, {
2499
+ className: classes.dialogContent
2500
+ }, /*#__PURE__*/React__default.createElement(core.DialogContentText, null, "Enter the name of the plugin and its URL. The name should match what is defined in the plugin's build."), /*#__PURE__*/React__default.createElement(core.TextField, {
2501
+ id: "umd-name-input",
2502
+ name: "umdName",
2460
2503
  label: "Plugin name",
2461
2504
  variant: "outlined",
2462
- value: formInput.name,
2463
- onChange: handleChange,
2464
- multiline: true
2465
- }), /*#__PURE__*/React__default.createElement(TextField, {
2466
- id: "url-input",
2467
- name: "url",
2505
+ value: umdPluginName,
2506
+ onChange: handleChange
2507
+ }), /*#__PURE__*/React__default.createElement(core.TextField, {
2508
+ id: "umd-url-input",
2509
+ name: "umdUrl",
2468
2510
  label: "Plugin URL",
2469
2511
  variant: "outlined",
2470
- value: formInput.url,
2471
- onChange: handleChange,
2472
- multiline: true
2473
- }), /*#__PURE__*/React__default.createElement(Button, {
2512
+ value: umdPluginUrl,
2513
+ onChange: handleChange
2514
+ }), /*#__PURE__*/React__default.createElement(core.DialogContentText, {
2515
+ onClick: handleOpenAdvancedOptions
2516
+ }, /*#__PURE__*/React__default.createElement(IconButton, {
2517
+ className: clsx(classes.expand, _defineProperty({}, classes.expandOpen, advancedOptionsOpen)),
2518
+ "aria-expanded": advancedOptionsOpen,
2519
+ "aria-label": "show more"
2520
+ }, /*#__PURE__*/React__default.createElement(ExpandMoreIcon, null)), "Advanced options"), /*#__PURE__*/React__default.createElement(core.Collapse, {
2521
+ "in": advancedOptionsOpen
2522
+ }, /*#__PURE__*/React__default.createElement("div", {
2523
+ className: classes.dialogContent
2524
+ }, /*#__PURE__*/React__default.createElement(core.DialogContentText, null, "The above fields assume that the plugin is built in UMD format. If your plugin is in another format, or you have additional builds you want to add (such as a CJS build for using NodeJS APIs in desktop), you can enter the URLs for those builds below."), /*#__PURE__*/React__default.createElement(core.TextField, {
2525
+ id: "esm-url-input",
2526
+ name: "esmUrl",
2527
+ label: "ESM build URL",
2528
+ variant: "outlined",
2529
+ value: esmPluginUrl,
2530
+ onChange: handleChange
2531
+ }), /*#__PURE__*/React__default.createElement(core.TextField, {
2532
+ id: "cjs-url-input",
2533
+ name: "cjsUrl",
2534
+ label: "CJS build URL",
2535
+ variant: "outlined",
2536
+ value: cjsPluginUrl,
2537
+ onChange: handleChange
2538
+ })))), /*#__PURE__*/React__default.createElement(core.DialogActions, null, /*#__PURE__*/React__default.createElement(core.Button, {
2539
+ variant: "contained",
2540
+ onClick: handleClose
2541
+ }, "Cancel"), /*#__PURE__*/React__default.createElement(core.Button, {
2474
2542
  variant: "contained",
2475
2543
  color: "primary",
2476
- style: {
2477
- marginTop: '1.5rem'
2478
- },
2479
- onClick: handleSubmit
2480
- }, "Add plugin")));
2544
+ onClick: handleSubmit,
2545
+ disabled: !ready
2546
+ }, "Submit"))));
2481
2547
  }
2482
2548
 
2483
2549
  var CustomPluginForm$1 = /*#__PURE__*/mobxReact.observer(CustomPluginForm);
2484
2550
 
2485
2551
  var useStyles$3 = /*#__PURE__*/core.makeStyles(function (theme) {
2486
2552
  return {
2487
- accordion: {
2488
- marginTop: '1em'
2553
+ root: {
2554
+ margin: theme.spacing(1)
2489
2555
  },
2490
2556
  expandIcon: {
2491
2557
  color: '#fff'
2492
2558
  },
2493
- searchBox: {
2494
- marginBottom: theme.spacing(2)
2495
- },
2496
2559
  adminBadge: {
2497
2560
  margin: '0.5em',
2498
2561
  borderRadius: 3,
@@ -2514,7 +2577,7 @@ function PluginStoreWidget(_ref) {
2514
2577
  var model = _ref.model;
2515
2578
  var classes = useStyles$3();
2516
2579
 
2517
- var _useState = React.useState([]),
2580
+ var _useState = React.useState(),
2518
2581
  _useState2 = _slicedToArray(_useState, 2),
2519
2582
  pluginArray = _useState2[0],
2520
2583
  setPluginArray = _useState2[1];
@@ -2536,61 +2599,71 @@ function PluginStoreWidget(_ref) {
2536
2599
  pluginManager = _getEnv.pluginManager;
2537
2600
 
2538
2601
  React.useEffect(function () {
2539
- var killed = false;
2602
+ var controller = new AbortController();
2603
+ var signal = controller.signal;
2540
2604
 
2541
2605
  _asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee() {
2542
- var fetchResult, array;
2606
+ var response, err, array;
2543
2607
  return runtime_1.wrap(function _callee$(_context) {
2544
2608
  while (1) {
2545
2609
  switch (_context.prev = _context.next) {
2546
2610
  case 0:
2547
2611
  _context.prev = 0;
2548
2612
  _context.next = 3;
2549
- return fetch('https://jbrowse.org/plugin-store/plugins.json');
2613
+ return fetch('https://jbrowse.org/plugin-store/plugins.json', {
2614
+ signal: signal
2615
+ });
2550
2616
 
2551
2617
  case 3:
2552
- fetchResult = _context.sent;
2618
+ response = _context.sent;
2553
2619
 
2554
- if (fetchResult.ok) {
2555
- _context.next = 6;
2620
+ if (response.ok) {
2621
+ _context.next = 9;
2556
2622
  break;
2557
2623
  }
2558
2624
 
2559
- throw new Error('Failed to fetch plugin data');
2625
+ _context.next = 7;
2626
+ return response.text();
2560
2627
 
2561
- case 6:
2562
- _context.next = 8;
2563
- return fetchResult.json();
2628
+ case 7:
2629
+ err = _context.sent;
2630
+ throw new Error("Failed to fetch plugin data: ".concat(response.status, " ").concat(response.statusText, " ").concat(err));
2564
2631
 
2565
- case 8:
2632
+ case 9:
2633
+ _context.next = 11;
2634
+ return response.json();
2635
+
2636
+ case 11:
2566
2637
  array = _context.sent;
2567
2638
 
2568
- if (!killed) {
2639
+ if (!signal.aborted) {
2569
2640
  setPluginArray(array.plugins);
2570
2641
  }
2571
2642
 
2572
- _context.next = 16;
2643
+ _context.next = 19;
2573
2644
  break;
2574
2645
 
2575
- case 12:
2576
- _context.prev = 12;
2646
+ case 15:
2647
+ _context.prev = 15;
2577
2648
  _context.t0 = _context["catch"](0);
2578
2649
  console.error(_context.t0);
2579
2650
  setError(_context.t0);
2580
2651
 
2581
- case 16:
2652
+ case 19:
2582
2653
  case "end":
2583
2654
  return _context.stop();
2584
2655
  }
2585
2656
  }
2586
- }, _callee, null, [[0, 12]]);
2657
+ }, _callee, null, [[0, 15]]);
2587
2658
  }))();
2588
2659
 
2589
2660
  return function () {
2590
- killed = true;
2661
+ controller.abort();
2591
2662
  };
2592
2663
  }, []);
2593
- return /*#__PURE__*/React__default.createElement("div", null, adminMode && /*#__PURE__*/React__default.createElement(React__default.Fragment, null, !util.isElectron && /*#__PURE__*/React__default.createElement("div", {
2664
+ return /*#__PURE__*/React__default.createElement("div", {
2665
+ className: classes.root
2666
+ }, adminMode && /*#__PURE__*/React__default.createElement(React__default.Fragment, null, !util.isElectron && /*#__PURE__*/React__default.createElement("div", {
2594
2667
  className: classes.adminBadge
2595
2668
  }, /*#__PURE__*/React__default.createElement(InfoOutlinedIcon, {
2596
2669
  style: {
@@ -2606,10 +2679,11 @@ function PluginStoreWidget(_ref) {
2606
2679
  }
2607
2680
  }, "Add custom plugin")), /*#__PURE__*/React__default.createElement(CustomPluginForm$1, {
2608
2681
  open: customPluginFormOpen,
2609
- onClose: setCustomPluginFormOpen,
2682
+ onClose: function onClose() {
2683
+ return setCustomPluginFormOpen(false);
2684
+ },
2610
2685
  model: model
2611
2686
  })), /*#__PURE__*/React__default.createElement(core.TextField, {
2612
- className: classes.searchBox,
2613
2687
  label: "Filter plugins",
2614
2688
  value: model.filterText,
2615
2689
  onChange: function onChange(event) {
@@ -2651,7 +2725,12 @@ function PluginStoreWidget(_ref) {
2651
2725
  variant: "h5"
2652
2726
  }, "Available plugins")), error ? /*#__PURE__*/React__default.createElement(core.Typography, {
2653
2727
  color: "error"
2654
- }, "".concat(error)) : pluginArray.length ? pluginArray.filter(function (plugin) {
2728
+ }, "".concat(error)) : pluginArray ? pluginArray.filter(function (plugin) {
2729
+ // If pugin only has cjsUrl, don't display outside desktop
2730
+ if (!util.isElectron && !(plugin.esmUrl || plugin.url || plugin.umdUrl)) {
2731
+ return false;
2732
+ }
2733
+
2655
2734
  return plugin.name.toLowerCase().includes(model.filterText.toLowerCase());
2656
2735
  }).map(function (plugin) {
2657
2736
  return /*#__PURE__*/React__default.createElement(PluginCard$1, {
@@ -2782,128 +2861,50 @@ var _default = /*#__PURE__*/function (_Plugin) {
2782
2861
  return _default;
2783
2862
  }(Plugin);
2784
2863
 
2785
- var useStyles$4 = /*#__PURE__*/styles.makeStyles(function (theme) {
2786
- return {
2787
- root: {
2788
- margin: theme.spacing(1)
2789
- },
2790
- message: {
2791
- padding: theme.spacing(3)
2792
- },
2793
- titleBox: {
2794
- color: '#fff',
2795
- backgroundColor: theme.palette.primary.main,
2796
- textAlign: 'center'
2797
- },
2798
- dialogContent: {
2799
- width: 600
2800
- },
2801
- resetButton: {
2802
- justifyContent: 'center',
2803
- marginBottom: '6px'
2804
- }
2805
- };
2806
- });
2807
- var CurrentSession = /*#__PURE__*/mobxReact.observer(function (_ref) {
2808
- var session = _ref.session,
2809
- selectedDefault = _ref.selectedDefault,
2810
- handleRadio = _ref.handleRadio;
2811
- var classes = useStyles$4();
2812
- return /*#__PURE__*/React__default.createElement(Paper, {
2813
- className: classes.root
2814
- }, /*#__PURE__*/React__default.createElement(List, {
2815
- subheader: /*#__PURE__*/React__default.createElement(ListSubheader, null, "Currently open session")
2816
- }, /*#__PURE__*/React__default.createElement(ListItem, null, /*#__PURE__*/React__default.createElement(ListItemIcon, null, /*#__PURE__*/React__default.createElement(Radio, {
2817
- checked: session.name === selectedDefault,
2818
- onChange: function onChange() {
2819
- return handleRadio(session);
2820
- }
2821
- })), /*#__PURE__*/React__default.createElement(ListItemText, {
2822
- primary: session.name
2823
- }))));
2824
- });
2825
- var SetDefaultSession$1 = /*#__PURE__*/mobxReact.observer(function (_ref2) {
2826
- var rootModel = _ref2.rootModel,
2827
- open = _ref2.open,
2828
- onClose = _ref2.onClose,
2829
- currentDefault = _ref2.currentDefault;
2830
- var classes = useStyles$4();
2831
- var session = rootModel.session;
2864
+ function canSetDefaultSession(obj) {
2865
+ return _typeof(obj) === 'object' && !!obj && 'jbrowse' in obj;
2866
+ }
2832
2867
 
2833
- var _useState = React.useState(currentDefault),
2834
- _useState2 = _slicedToArray(_useState, 2),
2835
- selectedDefault = _useState2[0],
2836
- setSelectedDefault = _useState2[1]; // eslint-disable-next-line @typescript-eslint/no-explicit-any
2868
+ var SetDefaultSession$1 = /*#__PURE__*/mobxReact.observer(function (_ref) {
2869
+ var rootModel = _ref.rootModel,
2870
+ onClose = _ref.onClose;
2837
2871
 
2872
+ if (!rootModel) {
2873
+ return null;
2874
+ }
2838
2875
 
2839
- function handleRadio(sessionSnapshot) {
2840
- setSelectedDefault(sessionSnapshot.name);
2841
- rootModel.jbrowse.setDefaultSessionConf(sessionSnapshot);
2842
- session.notify("Set default session to ".concat(sessionSnapshot.name), 'success');
2876
+ if (!canSetDefaultSession(rootModel)) {
2877
+ console.error('Incorrect rootmodel');
2878
+ return null;
2843
2879
  }
2844
2880
 
2845
- return /*#__PURE__*/React__default.createElement(Dialog, {
2846
- open: open
2847
- }, /*#__PURE__*/React__default.createElement(DialogTitle, {
2848
- className: classes.titleBox
2849
- }, "Set Default Session"), /*#__PURE__*/React__default.createElement(DialogContent, null, /*#__PURE__*/React__default.createElement(core.Grid, {
2850
- className: classes.resetButton,
2851
- container: true
2852
- }, /*#__PURE__*/React__default.createElement(core.Grid, {
2853
- item: true
2854
- }, /*#__PURE__*/React__default.createElement(Button, {
2855
- color: "secondary",
2881
+ var jbrowse = rootModel.jbrowse,
2882
+ session = rootModel.session;
2883
+ return /*#__PURE__*/React__default.createElement(core.Dialog, {
2884
+ open: true,
2885
+ onClose: onClose
2886
+ }, /*#__PURE__*/React__default.createElement(core.DialogTitle, null, "Set default session"), /*#__PURE__*/React__default.createElement(core.DialogContent, null, /*#__PURE__*/React__default.createElement(core.Typography, null, "Select \"Set current session as default\" to make your current session saved to the config file. You can also hit \"Clear default session\", which would remove the default session from the config.")), /*#__PURE__*/React__default.createElement(core.DialogActions, null, /*#__PURE__*/React__default.createElement(core.Button, {
2856
2887
  variant: "contained",
2857
2888
  onClick: function onClick() {
2858
- setSelectedDefault('New session');
2859
- rootModel.jbrowse.setDefaultSessionConf({
2889
+ jbrowse.setDefaultSessionConf({
2860
2890
  name: "New session"
2861
2891
  });
2862
- session.notify('Reset default session', 'success');
2892
+ onClose();
2863
2893
  }
2864
- }, "Clear default session"))), /*#__PURE__*/React__default.createElement(CurrentSession, {
2865
- session: session,
2866
- selectedDefault: selectedDefault,
2867
- handleRadio: handleRadio
2868
- }), /*#__PURE__*/React__default.createElement(Paper, {
2869
- className: classes.root
2870
- }, /*#__PURE__*/React__default.createElement(List, {
2871
- subheader: /*#__PURE__*/React__default.createElement(ListSubheader, null, "Saved sessions")
2872
- }, session.savedSessions.length ? session.savedSessions.map( // eslint-disable-next-line @typescript-eslint/no-explicit-any
2873
- function (sessionSnapshot) {
2874
- var _sessionSnapshot$view = sessionSnapshot.views,
2875
- views = _sessionSnapshot$view === void 0 ? [] : _sessionSnapshot$view;
2876
- var totalTracks = views // eslint-disable-next-line @typescript-eslint/no-explicit-any
2877
- .map(function (view) {
2878
- return view.tracks.length;
2879
- }).reduce(function (a, b) {
2880
- return a + b;
2881
- }, 0);
2882
-
2883
- if (sessionSnapshot.name !== session.name) {
2884
- return /*#__PURE__*/React__default.createElement(ListItem, {
2885
- key: sessionSnapshot.name
2886
- }, /*#__PURE__*/React__default.createElement(ListItemIcon, null, /*#__PURE__*/React__default.createElement(Radio, {
2887
- checked: sessionSnapshot.name === selectedDefault,
2888
- onChange: function onChange() {
2889
- return handleRadio(sessionSnapshot);
2890
- }
2891
- })), /*#__PURE__*/React__default.createElement(ListItemText, {
2892
- primary: sessionSnapshot.name,
2893
- secondary: "".concat(views.length, " ").concat(pluralize('view', views.length), "; ").concat(totalTracks, "\n open ").concat(pluralize('track', totalTracks))
2894
- }));
2895
- }
2896
-
2897
- return null;
2898
- }) : /*#__PURE__*/React__default.createElement(Typography, {
2899
- className: classes.message
2900
- }, "No saved sessions found")))), /*#__PURE__*/React__default.createElement(DialogActions, null, /*#__PURE__*/React__default.createElement(Button, {
2894
+ }, "Clear default session"), /*#__PURE__*/React__default.createElement(core.Button, {
2901
2895
  color: "secondary",
2902
2896
  variant: "contained",
2903
2897
  onClick: function onClick() {
2904
- onClose(false);
2898
+ return onClose();
2899
+ }
2900
+ }, "Cancel"), /*#__PURE__*/React__default.createElement(core.Button, {
2901
+ color: "primary",
2902
+ variant: "contained",
2903
+ onClick: function onClick() {
2904
+ jbrowse.setDefaultSessionConf(session);
2905
+ onClose();
2905
2906
  }
2906
- }, "Return")));
2907
+ }, "Set current session as default")));
2907
2908
  });
2908
2909
 
2909
2910
 
@@ -2913,7 +2914,7 @@ var index = {
2913
2914
  'default': SetDefaultSession$1
2914
2915
  };
2915
2916
 
2916
- var useStyles$5 = /*#__PURE__*/core.makeStyles(function () {
2917
+ var useStyles$4 = /*#__PURE__*/core.makeStyles(function () {
2917
2918
  return {
2918
2919
  table: {
2919
2920
  minWidth: 500,
@@ -2934,7 +2935,7 @@ var AssemblyTable = /*#__PURE__*/mobxReact.observer(function (_ref) {
2934
2935
  var rootModel = _ref.rootModel,
2935
2936
  setIsAssemblyBeingEdited = _ref.setIsAssemblyBeingEdited,
2936
2937
  setAssemblyBeingEdited = _ref.setAssemblyBeingEdited;
2937
- var classes = useStyles$5();
2938
+ var classes = useStyles$4();
2938
2939
 
2939
2940
  function removeAssembly(name) {
2940
2941
  rootModel.jbrowse.removeAssemblyConf(name);
@@ -2982,7 +2983,7 @@ var AssemblyTable = /*#__PURE__*/mobxReact.observer(function (_ref) {
2982
2983
  }, "Actions")))), /*#__PURE__*/React__default.createElement(core.TableBody, null, rows)));
2983
2984
  });
2984
2985
 
2985
- var useStyles$6 = /*#__PURE__*/core.makeStyles(function (theme) {
2986
+ var useStyles$5 = /*#__PURE__*/core.makeStyles(function (theme) {
2986
2987
  return {
2987
2988
  root: {
2988
2989
  flexGrow: 1,
@@ -3100,7 +3101,7 @@ var blank = {
3100
3101
  var AssemblyAddForm = /*#__PURE__*/mobxReact.observer(function (_ref3) {
3101
3102
  var rootModel = _ref3.rootModel,
3102
3103
  setFormOpen = _ref3.setFormOpen;
3103
- var classes = useStyles$6();
3104
+ var classes = useStyles$5();
3104
3105
  var adapterTypes = ['IndexedFastaAdapter', 'BgzipFastaAdapter', 'TwoBitAdapter'];
3105
3106
 
3106
3107
  var _useState = React.useState(''),
@@ -3262,7 +3263,7 @@ var AssemblyEditor = /*#__PURE__*/mobxReact.observer(function (_ref) {
3262
3263
  });
3263
3264
  });
3264
3265
 
3265
- var useStyles$7 = /*#__PURE__*/styles.makeStyles(function (theme) {
3266
+ var useStyles$6 = /*#__PURE__*/styles.makeStyles(function (theme) {
3266
3267
  return {
3267
3268
  titleBox: {
3268
3269
  color: '#fff',
@@ -3289,7 +3290,7 @@ var useStyles$7 = /*#__PURE__*/styles.makeStyles(function (theme) {
3289
3290
  var AssemblyManager$1 = /*#__PURE__*/mobxReact.observer(function (_ref) {
3290
3291
  var rootModel = _ref.rootModel,
3291
3292
  _onClose = _ref.onClose;
3292
- var classes = useStyles$7();
3293
+ var classes = useStyles$6();
3293
3294
 
3294
3295
  var _useState = React.useState(false),
3295
3296
  _useState2 = _slicedToArray(_useState, 2),
@@ -3386,7 +3387,7 @@ var ManageConnectionsDialog = /*#__PURE__*/React.lazy(function () {
3386
3387
  var ToggleConnectionsDialog = /*#__PURE__*/React.lazy(function () {
3387
3388
  return Promise.resolve().then(function () { return ToggleConnectionsDialog$2; });
3388
3389
  });
3389
- var useStyles$8 = /*#__PURE__*/core.makeStyles(function (theme) {
3390
+ var useStyles$7 = /*#__PURE__*/core.makeStyles(function (theme) {
3390
3391
  var _theme$palette$tertia, _theme$palette$tertia2;
3391
3392
 
3392
3393
  return {
@@ -3458,7 +3459,7 @@ var Node = function Node(props) {
3458
3459
  conf = data.conf,
3459
3460
  onMoreInfo = data.onMoreInfo,
3460
3461
  drawerPosition = data.drawerPosition;
3461
- var classes = useStyles$8();
3462
+ var classes = useStyles$7();
3462
3463
  var width = 10;
3463
3464
  var marginLeft = nestingLevel * width + (isLeaf ? width : 0);
3464
3465
  var unsupported = name && (name.endsWith('(Unsupported)') || name.endsWith('(Unknown)'));
@@ -3684,7 +3685,7 @@ var HierarchicalTrackSelectorContainer = /*#__PURE__*/mobxReact.observer(functio
3684
3685
  var model = _ref5.model,
3685
3686
  toolbarHeight = _ref5.toolbarHeight,
3686
3687
  overrideDimensions = _ref5.overrideDimensions;
3687
- var classes = useStyles$8();
3688
+ var classes = useStyles$7();
3688
3689
  var session = util.getSession(model);
3689
3690
 
3690
3691
  var _useState3 = React.useState(null),
@@ -3735,7 +3736,7 @@ var HierarchicalTrackSelectorHeader = /*#__PURE__*/mobxReact.observer(function (
3735
3736
  setHeaderHeight = _ref6.setHeaderHeight,
3736
3737
  setAssemblyIdx = _ref6.setAssemblyIdx,
3737
3738
  assemblyIdx = _ref6.assemblyIdx;
3738
- var classes = useStyles$8();
3739
+ var classes = useStyles$7();
3739
3740
  var session = util.getSession(model);
3740
3741
 
3741
3742
  var _useState5 = React.useState(),
@@ -3953,7 +3954,7 @@ var HierarchicalTrackSelector$1 = {
3953
3954
  'default': HierarchicalTrackSelectorContainer
3954
3955
  };
3955
3956
 
3956
- var useStyles$9 = /*#__PURE__*/styles.makeStyles(function (theme) {
3957
+ var useStyles$8 = /*#__PURE__*/core.makeStyles(function (theme) {
3957
3958
  return {
3958
3959
  spacing: {
3959
3960
  marginBottom: theme.spacing(3)
@@ -3966,24 +3967,72 @@ function StatusMessage(_ref) {
3966
3967
 
3967
3968
  var trackAdapter = _ref.trackAdapter,
3968
3969
  trackType = _ref.trackType;
3969
- var classes = useStyles$9();
3970
- return trackAdapter.type === 'SNPCoverageAdapter' ? /*#__PURE__*/React__default.createElement(Typography, {
3970
+ var classes = useStyles$8();
3971
+ return trackAdapter.type === 'SNPCoverageAdapter' ? /*#__PURE__*/React__default.createElement(core.Typography, {
3971
3972
  className: classes.spacing
3972
- }, "Selected ", /*#__PURE__*/React__default.createElement("code", null, trackType), ". Using adapter", ' ', /*#__PURE__*/React__default.createElement("code", null, trackAdapter.type), " with subadapter", ' ', /*#__PURE__*/React__default.createElement("code", null, (_trackAdapter$subadap = trackAdapter.subadapter) === null || _trackAdapter$subadap === void 0 ? void 0 : _trackAdapter$subadap.type), ". Please enter a track name and, if necessary, update the track type.") : /*#__PURE__*/React__default.createElement(Typography, {
3973
+ }, "Selected ", /*#__PURE__*/React__default.createElement("code", null, trackType), ". Using adapter", ' ', /*#__PURE__*/React__default.createElement("code", null, trackAdapter.type), " with subadapter", ' ', /*#__PURE__*/React__default.createElement("code", null, (_trackAdapter$subadap = trackAdapter.subadapter) === null || _trackAdapter$subadap === void 0 ? void 0 : _trackAdapter$subadap.type), ". Please enter a track name and, if necessary, update the track type.") : /*#__PURE__*/React__default.createElement(core.Typography, {
3973
3974
  className: classes.spacing
3974
3975
  }, "Using adapter ", /*#__PURE__*/React__default.createElement("code", null, trackAdapter.type), " and guessing track type", ' ', /*#__PURE__*/React__default.createElement("code", null, trackType), ". Please enter a track name and, if necessary, update the track type.");
3975
3976
  }
3977
+ /**
3978
+ * categorizeAdapters takes a list of adapters and sorts their menu item elements under an appropriate ListSubheader
3979
+ * element. In this way, adapters that are from external plugins can have headers that differentiate them from the
3980
+ * out-of-the-box plugins.
3981
+ * @param adaptersList - a list of adapters found in the PluginManager
3982
+ * @returns a series of JSX elements that are ListSubheaders followed by the adapters
3983
+ * found under that subheader
3984
+ */
3985
+
3986
+
3987
+ function categorizeAdapters(adaptersList) {
3988
+ var currentCategory = ''; // eslint-disable-next-line @typescript-eslint/no-explicit-any
3989
+
3990
+ var items = [];
3991
+ adaptersList.forEach(function (adapter) {
3992
+ var _adapter$adapterMetad;
3993
+
3994
+ if ((_adapter$adapterMetad = adapter.adapterMetadata) !== null && _adapter$adapterMetad !== void 0 && _adapter$adapterMetad.category) {
3995
+ var _adapter$adapterMetad2, _adapter$adapterMetad7, _adapter$adapterMetad8;
3996
+
3997
+ if (currentCategory !== ((_adapter$adapterMetad2 = adapter.adapterMetadata) === null || _adapter$adapterMetad2 === void 0 ? void 0 : _adapter$adapterMetad2.category)) {
3998
+ var _adapter$adapterMetad3, _adapter$adapterMetad4, _adapter$adapterMetad5, _adapter$adapterMetad6;
3999
+
4000
+ currentCategory = (_adapter$adapterMetad3 = adapter.adapterMetadata) === null || _adapter$adapterMetad3 === void 0 ? void 0 : _adapter$adapterMetad3.category;
4001
+ items.push( /*#__PURE__*/React__default.createElement(core.ListSubheader, {
4002
+ key: (_adapter$adapterMetad4 = adapter.adapterMetadata) === null || _adapter$adapterMetad4 === void 0 ? void 0 : _adapter$adapterMetad4.category,
4003
+ value: (_adapter$adapterMetad5 = adapter.adapterMetadata) === null || _adapter$adapterMetad5 === void 0 ? void 0 : _adapter$adapterMetad5.category
4004
+ }, (_adapter$adapterMetad6 = adapter.adapterMetadata) === null || _adapter$adapterMetad6 === void 0 ? void 0 : _adapter$adapterMetad6.category));
4005
+ }
4006
+
4007
+ items.push( /*#__PURE__*/React__default.createElement(core.MenuItem, {
4008
+ key: adapter.name,
4009
+ value: adapter.name
4010
+ }, (_adapter$adapterMetad7 = adapter.adapterMetadata) !== null && _adapter$adapterMetad7 !== void 0 && _adapter$adapterMetad7.displayName ? (_adapter$adapterMetad8 = adapter.adapterMetadata) === null || _adapter$adapterMetad8 === void 0 ? void 0 : _adapter$adapterMetad8.displayName : adapter.name));
4011
+ }
4012
+ });
4013
+ return items;
4014
+ }
4015
+
4016
+ function getAdapterTypes(pluginManager) {
4017
+ return pluginManager.getElementTypesInGroup('adapter');
4018
+ }
4019
+
4020
+ function getTrackTypes(pluginManager) {
4021
+ return pluginManager.getElementTypesInGroup('track');
4022
+ }
3976
4023
 
3977
4024
  var TrackAdapterSelector = /*#__PURE__*/mobxReact.observer(function (_ref2) {
3978
4025
  var model = _ref2.model;
3979
- var classes = useStyles$9();
4026
+ var classes = useStyles$8();
3980
4027
  var session = util.getSession(model);
3981
- var trackAdapter = model.trackAdapter;
3982
- return /*#__PURE__*/React__default.createElement(TextField, {
4028
+ var trackAdapter = model.trackAdapter; // prettier-ignore
4029
+
4030
+ var adapters = getAdapterTypes(mobxStateTree.getEnv(session).pluginManager);
4031
+ return /*#__PURE__*/React__default.createElement(core.TextField, {
3983
4032
  className: classes.spacing,
3984
- value: trackAdapter === null || trackAdapter === void 0 ? void 0 : trackAdapter.type,
4033
+ value: (trackAdapter === null || trackAdapter === void 0 ? void 0 : trackAdapter.type) !== 'UNKNOWN' ? trackAdapter === null || trackAdapter === void 0 ? void 0 : trackAdapter.type : '',
3985
4034
  label: "adapterType",
3986
- helperText: "An adapter type",
4035
+ helperText: "Select an adapter type",
3987
4036
  select: true,
3988
4037
  fullWidth: true,
3989
4038
  onChange: function onChange(event) {
@@ -3995,27 +4044,35 @@ var TrackAdapterSelector = /*#__PURE__*/mobxReact.observer(function (_ref2) {
3995
4044
  'data-testid': 'adapterTypeSelect'
3996
4045
  }
3997
4046
  }
3998
- }, mobxStateTree.getEnv(session).pluginManager.getElementTypesInGroup('adapter') // Exclude SNPCoverageAdapter from primary adapter user selection
4047
+ }, adapters // Excludes any adapter with the 'adapterMetadata.hiddenFromGUI' property, and anything with the 'adapterMetadata.category' property
3999
4048
  .filter(function (elt) {
4000
- return elt.name !== 'SNPCoverageAdapter';
4049
+ var _elt$adapterMetadata, _elt$adapterMetadata2;
4050
+
4051
+ return !((_elt$adapterMetadata = elt.adapterMetadata) !== null && _elt$adapterMetadata !== void 0 && _elt$adapterMetadata.hiddenFromGUI) && !((_elt$adapterMetadata2 = elt.adapterMetadata) !== null && _elt$adapterMetadata2 !== void 0 && _elt$adapterMetadata2.category);
4001
4052
  }).map(function (elt) {
4002
- return /*#__PURE__*/React__default.createElement(MenuItem, {
4053
+ var _elt$adapterMetadata3, _elt$adapterMetadata4;
4054
+
4055
+ return /*#__PURE__*/React__default.createElement(core.MenuItem, {
4003
4056
  key: elt.name,
4004
4057
  value: elt.name
4005
- }, elt.name);
4006
- }));
4058
+ }, (_elt$adapterMetadata3 = elt.adapterMetadata) !== null && _elt$adapterMetadata3 !== void 0 && _elt$adapterMetadata3.displayName ? (_elt$adapterMetadata4 = elt.adapterMetadata) === null || _elt$adapterMetadata4 === void 0 ? void 0 : _elt$adapterMetadata4.displayName : elt.name);
4059
+ }), categorizeAdapters(adapters.filter(function (elt) {
4060
+ var _elt$adapterMetadata5;
4061
+
4062
+ return !((_elt$adapterMetadata5 = elt.adapterMetadata) !== null && _elt$adapterMetadata5 !== void 0 && _elt$adapterMetadata5.hiddenFromGUI);
4063
+ })));
4007
4064
  });
4008
4065
 
4009
4066
  function UnknownAdapterPrompt(_ref3) {
4010
4067
  var model = _ref3.model;
4011
- var classes = useStyles$9();
4012
- return /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement(Typography, {
4068
+ var classes = useStyles$8();
4069
+ return /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement(core.Typography, {
4013
4070
  className: classes.spacing
4014
- }, "Was not able to guess the adapter type for this data, but it may be in the list below. If not, you can", ' ', /*#__PURE__*/React__default.createElement(Link, {
4071
+ }, "JBrowse was not able to guess the adapter type for this data, but it may be in the list below. If not, you can", ' ', /*#__PURE__*/React__default.createElement(core.Link, {
4015
4072
  href: "https://github.com/GMOD/jbrowse-components/releases",
4016
4073
  target: "_blank",
4017
4074
  rel: "noopener noreferrer"
4018
- }, "check for new releases"), ' ', "of JBrowse to see if they support this data type or", ' ', /*#__PURE__*/React__default.createElement(Link, {
4075
+ }, "check for new releases"), ' ', "of JBrowse to see if they support this data type or", ' ', /*#__PURE__*/React__default.createElement(core.Link, {
4019
4076
  href: "https://github.com/GMOD/jbrowse-components/issues/new",
4020
4077
  target: "_blank",
4021
4078
  rel: "noopener noreferrer"
@@ -4026,14 +4083,15 @@ function UnknownAdapterPrompt(_ref3) {
4026
4083
 
4027
4084
  var TrackTypeSelector = /*#__PURE__*/mobxReact.observer(function (_ref4) {
4028
4085
  var model = _ref4.model;
4029
- var classes = useStyles$9();
4086
+ var classes = useStyles$8();
4030
4087
  var session = util.getSession(model);
4031
4088
  var trackType = model.trackType;
4032
- return /*#__PURE__*/React__default.createElement(TextField, {
4089
+ var trackTypes = getTrackTypes(mobxStateTree.getEnv(session).pluginManager);
4090
+ return /*#__PURE__*/React__default.createElement(core.TextField, {
4033
4091
  className: classes.spacing,
4034
4092
  value: trackType,
4035
4093
  label: "trackType",
4036
- helperText: "A track type",
4094
+ helperText: "Select a track type",
4037
4095
  select: true,
4038
4096
  fullWidth: true,
4039
4097
  onChange: function onChange(event) {
@@ -4045,10 +4103,9 @@ var TrackTypeSelector = /*#__PURE__*/mobxReact.observer(function (_ref4) {
4045
4103
  'data-testid': 'trackTypeSelect'
4046
4104
  }
4047
4105
  }
4048
- }, mobxStateTree.getEnv(session).pluginManager.getElementTypesInGroup('track') // eslint-disable-next-line @typescript-eslint/no-explicit-any
4049
- .map(function (_ref5) {
4106
+ }, trackTypes.map(function (_ref5) {
4050
4107
  var name = _ref5.name;
4051
- return /*#__PURE__*/React__default.createElement(MenuItem, {
4108
+ return /*#__PURE__*/React__default.createElement(core.MenuItem, {
4052
4109
  key: name,
4053
4110
  value: name
4054
4111
  }, name);
@@ -4058,7 +4115,7 @@ var TrackAssemblySelector = /*#__PURE__*/mobxReact.observer(function (_ref6) {
4058
4115
  var model = _ref6.model;
4059
4116
  var session = util.getSession(model);
4060
4117
  var assembly = model.assembly;
4061
- return /*#__PURE__*/React__default.createElement(TextField, {
4118
+ return /*#__PURE__*/React__default.createElement(core.TextField, {
4062
4119
  value: assembly,
4063
4120
  label: "assemblyName",
4064
4121
  helperText: "Assembly to which the track will be added",
@@ -4074,8 +4131,9 @@ var TrackAssemblySelector = /*#__PURE__*/mobxReact.observer(function (_ref6) {
4074
4131
  }
4075
4132
  }
4076
4133
  }, session.assemblies.map(function (conf) {
4077
- var name = configuration.readConfObject(conf, 'name');
4078
- return /*#__PURE__*/React__default.createElement(MenuItem, {
4134
+ return configuration.readConfObject(conf, 'name');
4135
+ }).map(function (name) {
4136
+ return /*#__PURE__*/React__default.createElement(core.MenuItem, {
4079
4137
  key: name,
4080
4138
  value: name
4081
4139
  }, name);
@@ -4084,20 +4142,21 @@ var TrackAssemblySelector = /*#__PURE__*/mobxReact.observer(function (_ref6) {
4084
4142
 
4085
4143
  function ConfirmTrack(_ref7) {
4086
4144
  var model = _ref7.model;
4087
- var classes = useStyles$9();
4145
+ var classes = useStyles$8();
4088
4146
  var trackName = model.trackName,
4089
4147
  trackAdapter = model.trackAdapter,
4090
4148
  trackType = model.trackType,
4091
- warningMessage = model.warningMessage;
4149
+ warningMessage = model.warningMessage,
4150
+ adapterHint = model.adapterHint;
4092
4151
 
4093
4152
  if (model.unsupported) {
4094
- return /*#__PURE__*/React__default.createElement(Typography, {
4153
+ return /*#__PURE__*/React__default.createElement(core.Typography, {
4095
4154
  className: classes.spacing
4096
- }, "This version of JBrowse cannot display data of this type. It is possible, however, that there is a newer version that can display them. You can", ' ', /*#__PURE__*/React__default.createElement(Link, {
4155
+ }, "This version of JBrowse cannot display data of this type. It is possible, however, that there is a newer version that can display them. You can", ' ', /*#__PURE__*/React__default.createElement(core.Link, {
4097
4156
  href: "https://github.com/GMOD/jbrowse-components/releases",
4098
4157
  target: "_blank",
4099
4158
  rel: "noopener noreferrer"
4100
- }, "check for new releases"), ' ', "of JBrowse or", ' ', /*#__PURE__*/React__default.createElement(Link, {
4159
+ }, "check for new releases"), ' ', "of JBrowse or", ' ', /*#__PURE__*/React__default.createElement(core.Link, {
4101
4160
  href: "https://github.com/GMOD/jbrowse-components/issues/new",
4102
4161
  target: "_blank",
4103
4162
  rel: "noopener noreferrer"
@@ -4110,18 +4169,22 @@ function ConfirmTrack(_ref7) {
4110
4169
  });
4111
4170
  }
4112
4171
 
4172
+ if (adapterHint === '' && trackAdapter) {
4173
+ model.setAdapterHint(trackAdapter.type);
4174
+ }
4175
+
4113
4176
  if (!(trackAdapter !== null && trackAdapter !== void 0 && trackAdapter.type)) {
4114
- return /*#__PURE__*/React__default.createElement(Typography, null, "Could not recognize this data type.");
4177
+ return /*#__PURE__*/React__default.createElement(core.Typography, null, "Could not recognize this data type.");
4115
4178
  }
4116
4179
 
4117
4180
  return /*#__PURE__*/React__default.createElement("div", null, trackAdapter ? /*#__PURE__*/React__default.createElement(StatusMessage, {
4118
4181
  trackAdapter: trackAdapter,
4119
4182
  trackType: trackType
4120
- }) : null, warningMessage ? /*#__PURE__*/React__default.createElement(Typography, {
4183
+ }) : null, warningMessage ? /*#__PURE__*/React__default.createElement(core.Typography, {
4121
4184
  style: {
4122
4185
  color: 'orange'
4123
4186
  }
4124
- }, warningMessage) : null, /*#__PURE__*/React__default.createElement(TextField, {
4187
+ }, warningMessage) : null, /*#__PURE__*/React__default.createElement(core.TextField, {
4125
4188
  className: classes.spacing,
4126
4189
  label: "trackName",
4127
4190
  helperText: "A name for this track",
@@ -4144,7 +4207,7 @@ function ConfirmTrack(_ref7) {
4144
4207
 
4145
4208
  var ConfirmTrack$1 = /*#__PURE__*/mobxReact.observer(ConfirmTrack);
4146
4209
 
4147
- var useStyles$a = /*#__PURE__*/styles.makeStyles(function (theme) {
4210
+ var useStyles$9 = /*#__PURE__*/core.makeStyles(function (theme) {
4148
4211
  return {
4149
4212
  paper: {
4150
4213
  display: 'flex',
@@ -4159,9 +4222,9 @@ var useStyles$a = /*#__PURE__*/styles.makeStyles(function (theme) {
4159
4222
 
4160
4223
  function TrackSourceSelect(_ref) {
4161
4224
  var model = _ref.model;
4162
- var classes = useStyles$a();
4225
+ var classes = useStyles$9();
4163
4226
  var rootModel = mobxStateTree.getRoot(model);
4164
- return /*#__PURE__*/React__default.createElement(Paper, {
4227
+ return /*#__PURE__*/React__default.createElement(core.Paper, {
4165
4228
  className: classes.paper
4166
4229
  }, /*#__PURE__*/React__default.createElement(ui.FileSelector, {
4167
4230
  name: "Main file",
@@ -4184,7 +4247,7 @@ function TrackSourceSelect(_ref) {
4184
4247
 
4185
4248
  var TrackSourceSelect$1 = /*#__PURE__*/mobxReact.observer(TrackSourceSelect);
4186
4249
 
4187
- var useStyles$b = /*#__PURE__*/core.makeStyles(function (theme) {
4250
+ var useStyles$a = /*#__PURE__*/core.makeStyles(function (theme) {
4188
4251
  return {
4189
4252
  root: {
4190
4253
  marginTop: theme.spacing(1)
@@ -4217,7 +4280,7 @@ function AddTrackWidget(_ref) {
4217
4280
  activeStep = _useState2[0],
4218
4281
  setActiveStep = _useState2[1];
4219
4282
 
4220
- var classes = useStyles$b();
4283
+ var classes = useStyles$a();
4221
4284
  var session = util.getSession(model);
4222
4285
  var assembly = model.assembly,
4223
4286
  trackAdapter = model.trackAdapter,
@@ -4418,7 +4481,7 @@ function ConnectionTypeSelect(props) {
4418
4481
  })));
4419
4482
  }
4420
4483
 
4421
- var useStyles$c = /*#__PURE__*/styles.makeStyles(function (theme) {
4484
+ var useStyles$b = /*#__PURE__*/styles.makeStyles(function (theme) {
4422
4485
  return {
4423
4486
  root: {
4424
4487
  marginTop: theme.spacing(1)
@@ -4460,7 +4523,7 @@ function AddConnectionWidget(_ref) {
4460
4523
  activeStep = _useState8[0],
4461
4524
  setActiveStep = _useState8[1];
4462
4525
 
4463
- var classes = useStyles$c();
4526
+ var classes = useStyles$b();
4464
4527
  var session = util.getSession(model);
4465
4528
 
4466
4529
  var _getEnv = mobxStateTree.getEnv(session),
@@ -4633,7 +4696,7 @@ var DeleteConnectionDialog$3 = {
4633
4696
  'default': DeleteConnectionDialog$2
4634
4697
  };
4635
4698
 
4636
- var useStyles$d = /*#__PURE__*/core.makeStyles(function (theme) {
4699
+ var useStyles$c = /*#__PURE__*/core.makeStyles(function (theme) {
4637
4700
  return {
4638
4701
  closeButton: {
4639
4702
  position: 'absolute',
@@ -4652,7 +4715,7 @@ function ManageConnectionsDlg(_ref) {
4652
4715
  var session = _ref.session,
4653
4716
  handleClose = _ref.handleClose,
4654
4717
  breakConnection = _ref.breakConnection;
4655
- var classes = useStyles$d();
4718
+ var classes = useStyles$c();
4656
4719
  var adminMode = session.adminMode,
4657
4720
  connections = session.connections,
4658
4721
  sessionConnections = session.sessionConnections;
@@ -4698,7 +4761,7 @@ var ManageConnectionsDialog$2 = {
4698
4761
  'default': ManageConnectionsDialog$1
4699
4762
  };
4700
4763
 
4701
- var useStyles$e = /*#__PURE__*/core.makeStyles(function (theme) {
4764
+ var useStyles$d = /*#__PURE__*/core.makeStyles(function (theme) {
4702
4765
  return {
4703
4766
  closeButton: {
4704
4767
  position: 'absolute',
@@ -4718,7 +4781,7 @@ function ToggleConnectionDialog(_ref) {
4718
4781
  handleClose = _ref.handleClose,
4719
4782
  assemblyName = _ref.assemblyName,
4720
4783
  breakConnection = _ref.breakConnection;
4721
- var classes = useStyles$e();
4784
+ var classes = useStyles$d();
4722
4785
  var connections = session.connections,
4723
4786
  connectionInstances = session.connectionInstances;
4724
4787
  var assemblySpecificConnections = connections.filter(function (c) {