@jbrowse/plugin-data-management 1.5.1 → 1.5.2

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.
@@ -10,7 +10,7 @@ import { openLocation } from '@jbrowse/core/util/io';
10
10
  import { generateUnknownTrackConf, generateUnsupportedTrackConf, guessAdapter, getFileName, UNSUPPORTED, guessTrackType, UNKNOWN } from '@jbrowse/core/util/tracks';
11
11
  import { ElementId } from '@jbrowse/core/util/types/mst';
12
12
  import { observer, PropTypes } from 'mobx-react';
13
- import { ListItem, IconButton, Typography, Tooltip, Dialog, DialogTitle, DialogContent, DialogActions, Button, List, Card, CardContent, Link, CardActions, makeStyles as makeStyles$1, TextField, InputAdornment, Accordion, AccordionSummary, TableRow, TableCell, TableContainer, Paper, Table, TableHead, TableBody, Grid, MenuItem, Fab, Menu, FormControlLabel, Checkbox, ListSubheader, Stepper, Step, StepLabel, StepContent, DialogContentText } from '@material-ui/core';
13
+ import { ListItem, IconButton, Typography, Tooltip, Dialog, DialogTitle, DialogContent, DialogActions, Button, List, Card, CardContent, Link, CardActions, makeStyles as makeStyles$1, DialogContentText, TextField, Collapse, InputAdornment, Accordion, AccordionSummary, TableRow, TableCell, TableContainer, Paper, Table, TableHead, TableBody, Grid, MenuItem, Fab, Menu, FormControlLabel, Checkbox, ListSubheader, Stepper, Step, StepLabel, StepContent } from '@material-ui/core';
14
14
  import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
15
15
  import ClearIcon from '@material-ui/icons/Clear';
16
16
  import InfoOutlinedIcon from '@material-ui/icons/InfoOutlined';
@@ -21,6 +21,7 @@ import { isSessionWithSessionPlugins } from '@jbrowse/core/util/types';
21
21
  import PersonIcon from '@material-ui/icons/Person';
22
22
  import AddIcon from '@material-ui/icons/Add';
23
23
  import CheckIcon from '@material-ui/icons/Check';
24
+ import clsx from 'clsx';
24
25
  import IconButton$1 from '@material-ui/core/IconButton';
25
26
  import ArrowBackIosIcon from '@material-ui/icons/ArrowBackIos';
26
27
  import CreateIcon from '@material-ui/icons/Create';
@@ -1773,7 +1774,8 @@ function f(pluginManager) {
1773
1774
 
1774
1775
  var track = self.trackData,
1775
1776
  index = self.indexTrackData;
1776
- 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://'));
1777
+ return !!( // @ts-ignore
1778
+ 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://'));
1777
1779
  },
1778
1780
 
1779
1781
  get isRelativeTrackUrl() {
@@ -1869,9 +1871,9 @@ var hasAnyOverlap = function hasAnyOverlap() {
1869
1871
  function passesFilter(filter, config) {
1870
1872
  var name = getTrackName(config);
1871
1873
  var categories = readConfObject(config, 'category') || [];
1872
- var regexp = new RegExp(filter, 'i');
1873
- return !!name.match(regexp) || categories.filter(function (cat) {
1874
- return !!cat.match(regexp);
1874
+ var filterLower = filter.toLowerCase();
1875
+ return !!name.toLowerCase().includes(filterLower) || categories.filter(function (cat) {
1876
+ return !!cat.toLowerCase().includes(filterLower);
1875
1877
  }).length;
1876
1878
  }
1877
1879
 
@@ -2218,7 +2220,7 @@ function InstalledPlugin(_ref2) {
2218
2220
  onClose: function onClose(name) {
2219
2221
  if (name) {
2220
2222
  var pluginMetadata = pluginManager.pluginMetadata[plugin.name];
2221
- var pluginUrl = pluginMetadata.url;
2223
+ var pluginUrl = pluginMetadata.url || pluginMetadata.esmUrl || pluginMetadata.umdUrl || pluginMetadata.cjsUrl;
2222
2224
 
2223
2225
  if (adminMode) {
2224
2226
  jbrowse.removePlugin(pluginUrl);
@@ -2354,87 +2356,182 @@ function PluginCard(_ref) {
2354
2356
 
2355
2357
  var PluginCard$1 = /*#__PURE__*/observer(PluginCard);
2356
2358
 
2357
- var useStyles$2 = /*#__PURE__*/makeStyles$1(function () {
2359
+ var useStyles$2 = /*#__PURE__*/makeStyles$1(function (theme) {
2358
2360
  return {
2359
- closeDialog: {
2361
+ closeButton: {
2360
2362
  position: 'absolute',
2361
- right: 0,
2362
- top: 0
2363
+ right: theme.spacing(1),
2364
+ top: theme.spacing(1)
2363
2365
  },
2364
- dialogContainer: {
2365
- margin: 15,
2366
+ dialogContent: {
2366
2367
  display: 'flex',
2367
2368
  flexDirection: 'column'
2369
+ },
2370
+ expand: {
2371
+ transform: 'rotate(0deg)',
2372
+ marginLeft: 'auto',
2373
+ transition: theme.transitions.create('transform', {
2374
+ duration: theme.transitions.duration.shortest
2375
+ })
2376
+ },
2377
+ expandOpen: {
2378
+ transform: 'rotate(180deg)'
2368
2379
  }
2369
2380
  };
2370
2381
  });
2371
2382
 
2372
2383
  function CustomPluginForm(_ref) {
2373
2384
  var open = _ref.open,
2374
- _onClose = _ref.onClose,
2385
+ onClose = _ref.onClose,
2375
2386
  model = _ref.model;
2376
2387
  var classes = useStyles$2();
2377
2388
 
2378
2389
  var _useState = useState(''),
2379
2390
  _useState2 = _slicedToArray(_useState, 2),
2380
- formName = _useState2[0],
2381
- setFormName = _useState2[1];
2391
+ umdPluginName = _useState2[0],
2392
+ setUMDPluginName = _useState2[1];
2382
2393
 
2383
2394
  var _useState3 = useState(''),
2384
2395
  _useState4 = _slicedToArray(_useState3, 2),
2385
- formUrl = _useState4[0],
2386
- setFormUrl = _useState4[1];
2396
+ umdPluginUrl = _useState4[0],
2397
+ setUMDPluginUrl = _useState4[1];
2398
+
2399
+ var _useState5 = useState(''),
2400
+ _useState6 = _slicedToArray(_useState5, 2),
2401
+ esmPluginUrl = _useState6[0],
2402
+ setESMPluginUrl = _useState6[1];
2403
+
2404
+ var _useState7 = useState(''),
2405
+ _useState8 = _slicedToArray(_useState7, 2),
2406
+ cjsPluginUrl = _useState8[0],
2407
+ setCJSPluginUrl = _useState8[1];
2408
+
2409
+ var _useState9 = useState(false),
2410
+ _useState10 = _slicedToArray(_useState9, 2),
2411
+ advancedOptionsOpen = _useState10[0],
2412
+ setAdvancedOptionsOpen = _useState10[1];
2413
+
2414
+ function handleChange(event) {
2415
+ var _event$target = event.target,
2416
+ name = _event$target.name,
2417
+ value = _event$target.value;
2418
+
2419
+ if (name === 'umdName') {
2420
+ setUMDPluginName(value);
2421
+ }
2422
+
2423
+ if (name === 'umdUrl') {
2424
+ setUMDPluginUrl(value);
2425
+ }
2426
+
2427
+ if (name === 'esmUrl') {
2428
+ setESMPluginUrl(value);
2429
+ }
2430
+
2431
+ if (name === 'cjsUrl') {
2432
+ setCJSPluginUrl(value);
2433
+ }
2434
+ }
2435
+
2436
+ function handleOpenAdvancedOptions() {
2437
+ setAdvancedOptionsOpen(!advancedOptionsOpen);
2438
+ }
2387
2439
 
2388
2440
  var rootModel = getRoot(model);
2389
2441
  var jbrowse = rootModel.jbrowse;
2442
+ var ready = Boolean(umdPluginName && umdPluginUrl || esmPluginUrl || cjsPluginUrl);
2443
+
2444
+ function handleSubmit() {
2445
+ if (!ready) {
2446
+ return;
2447
+ }
2448
+
2449
+ var pluginDefinition = {};
2450
+
2451
+ if (umdPluginName && umdPluginUrl) {
2452
+ pluginDefinition.name = umdPluginName;
2453
+ pluginDefinition.umdUrl = umdPluginUrl;
2454
+ }
2455
+
2456
+ if (esmPluginUrl) {
2457
+ pluginDefinition.esmUrl = esmPluginUrl;
2458
+ }
2459
+
2460
+ if (cjsPluginUrl) {
2461
+ pluginDefinition.cjsUrl = cjsPluginUrl;
2462
+ }
2463
+
2464
+ jbrowse.addPlugin(pluginDefinition);
2465
+ }
2466
+
2467
+ function handleClose() {
2468
+ setUMDPluginName('');
2469
+ setUMDPluginUrl('');
2470
+ setESMPluginUrl('');
2471
+ setCJSPluginUrl('');
2472
+ onClose();
2473
+ }
2474
+
2390
2475
  return /*#__PURE__*/React.createElement(Dialog, {
2391
2476
  open: open,
2392
- onClose: function onClose() {
2393
- return _onClose();
2394
- }
2477
+ onClose: handleClose
2395
2478
  }, /*#__PURE__*/React.createElement(DialogTitle, null, "Add custom plugin", /*#__PURE__*/React.createElement(IconButton$1, {
2396
- className: classes.closeDialog,
2479
+ size: "medium",
2480
+ className: classes.closeButton,
2397
2481
  onClick: function onClick() {
2398
- return _onClose();
2482
+ return onClose();
2399
2483
  }
2400
- }, /*#__PURE__*/React.createElement(CloseIcon, null))), /*#__PURE__*/React.createElement(DialogContent, null, /*#__PURE__*/React.createElement("div", {
2401
- className: classes.dialogContainer
2402
- }, /*#__PURE__*/React.createElement(Typography, null, "Specify the name and URL path of your plugin source"), /*#__PURE__*/React.createElement(TextField, {
2403
- id: "name-input",
2404
- name: "name",
2484
+ }, /*#__PURE__*/React.createElement(CloseIcon, null))), /*#__PURE__*/React.createElement("form", {
2485
+ onSubmit: handleSubmit
2486
+ }, /*#__PURE__*/React.createElement(DialogContent, {
2487
+ className: classes.dialogContent
2488
+ }, /*#__PURE__*/React.createElement(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.createElement(TextField, {
2489
+ id: "umd-name-input",
2490
+ name: "umdName",
2405
2491
  label: "Plugin name",
2406
2492
  variant: "outlined",
2407
- value: formName,
2408
- onChange: function onChange(event) {
2409
- return setFormName(event.target.value);
2410
- }
2493
+ value: umdPluginName,
2494
+ onChange: handleChange
2411
2495
  }), /*#__PURE__*/React.createElement(TextField, {
2412
- id: "url-input",
2413
- name: "url",
2496
+ id: "umd-url-input",
2497
+ name: "umdUrl",
2414
2498
  label: "Plugin URL",
2415
2499
  variant: "outlined",
2416
- value: formUrl,
2417
- onChange: function onChange(event) {
2418
- return setFormUrl(event.target.value);
2419
- }
2420
- }))), /*#__PURE__*/React.createElement(DialogActions, null, /*#__PURE__*/React.createElement(Button, {
2500
+ value: umdPluginUrl,
2501
+ onChange: handleChange
2502
+ }), /*#__PURE__*/React.createElement(DialogContentText, {
2503
+ onClick: handleOpenAdvancedOptions
2504
+ }, /*#__PURE__*/React.createElement(IconButton$1, {
2505
+ className: clsx(classes.expand, _defineProperty({}, classes.expandOpen, advancedOptionsOpen)),
2506
+ "aria-expanded": advancedOptionsOpen,
2507
+ "aria-label": "show more"
2508
+ }, /*#__PURE__*/React.createElement(ExpandMoreIcon, null)), "Advanced options"), /*#__PURE__*/React.createElement(Collapse, {
2509
+ "in": advancedOptionsOpen
2510
+ }, /*#__PURE__*/React.createElement("div", {
2511
+ className: classes.dialogContent
2512
+ }, /*#__PURE__*/React.createElement(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.createElement(TextField, {
2513
+ id: "esm-url-input",
2514
+ name: "esmUrl",
2515
+ label: "ESM build URL",
2516
+ variant: "outlined",
2517
+ value: esmPluginUrl,
2518
+ onChange: handleChange
2519
+ }), /*#__PURE__*/React.createElement(TextField, {
2520
+ id: "cjs-url-input",
2521
+ name: "cjsUrl",
2522
+ label: "CJS build URL",
2523
+ variant: "outlined",
2524
+ value: cjsPluginUrl,
2525
+ onChange: handleChange
2526
+ })))), /*#__PURE__*/React.createElement(DialogActions, null, /*#__PURE__*/React.createElement(Button, {
2421
2527
  variant: "contained",
2422
- color: "secondary",
2423
- onClick: function onClick() {
2424
- return _onClose();
2425
- }
2528
+ onClick: handleClose
2426
2529
  }, "Cancel"), /*#__PURE__*/React.createElement(Button, {
2427
2530
  variant: "contained",
2428
2531
  color: "primary",
2429
- onClick: function onClick() {
2430
- jbrowse.addPlugin({
2431
- name: formName,
2432
- url: formUrl
2433
- });
2434
-
2435
- _onClose();
2436
- }
2437
- }, "Submit")));
2532
+ onClick: handleSubmit,
2533
+ disabled: !ready
2534
+ }, "Submit"))));
2438
2535
  }
2439
2536
 
2440
2537
  var CustomPluginForm$1 = /*#__PURE__*/observer(CustomPluginForm);
@@ -2490,7 +2587,8 @@ function PluginStoreWidget(_ref) {
2490
2587
  pluginManager = _getEnv.pluginManager;
2491
2588
 
2492
2589
  useEffect(function () {
2493
- var killed = false;
2590
+ var controller = new AbortController();
2591
+ var signal = controller.signal;
2494
2592
 
2495
2593
  _asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee() {
2496
2594
  var response, err, array;
@@ -2500,7 +2598,9 @@ function PluginStoreWidget(_ref) {
2500
2598
  case 0:
2501
2599
  _context.prev = 0;
2502
2600
  _context.next = 3;
2503
- return fetch('https://jbrowse.org/plugin-store/plugins.json');
2601
+ return fetch('https://jbrowse.org/plugin-store/plugins.json', {
2602
+ signal: signal
2603
+ });
2504
2604
 
2505
2605
  case 3:
2506
2606
  response = _context.sent;
@@ -2524,7 +2624,7 @@ function PluginStoreWidget(_ref) {
2524
2624
  case 11:
2525
2625
  array = _context.sent;
2526
2626
 
2527
- if (!killed) {
2627
+ if (!signal.aborted) {
2528
2628
  setPluginArray(array.plugins);
2529
2629
  }
2530
2630
 
@@ -2546,7 +2646,7 @@ function PluginStoreWidget(_ref) {
2546
2646
  }))();
2547
2647
 
2548
2648
  return function () {
2549
- killed = true;
2649
+ controller.abort();
2550
2650
  };
2551
2651
  }, []);
2552
2652
  return /*#__PURE__*/React.createElement("div", {
@@ -2614,6 +2714,11 @@ function PluginStoreWidget(_ref) {
2614
2714
  }, "Available plugins")), error ? /*#__PURE__*/React.createElement(Typography, {
2615
2715
  color: "error"
2616
2716
  }, "".concat(error)) : pluginArray ? pluginArray.filter(function (plugin) {
2717
+ // If pugin only has cjsUrl, don't display outside desktop
2718
+ if (!isElectron && !(plugin.esmUrl || plugin.url || plugin.umdUrl)) {
2719
+ return false;
2720
+ }
2721
+
2617
2722
  return plugin.name.toLowerCase().includes(model.filterText.toLowerCase());
2618
2723
  }).map(function (plugin) {
2619
2724
  return /*#__PURE__*/React.createElement(PluginCard$1, {