@jbrowse/plugin-data-management 4.0.3 → 4.0.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.
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Suspense, useEffect, useState } from 'react';
2
+ import { Suspense, useEffect } from 'react';
3
3
  import { AssemblySelector } from '@jbrowse/core/ui';
4
4
  import { getEnv, getSession, isElectron, isSupportedIndexingAdapter, } from '@jbrowse/core/util';
5
5
  import { UNKNOWN } from '@jbrowse/core/util/tracks';
@@ -16,17 +16,21 @@ const useStyles = makeStyles()(theme => ({
16
16
  spacing: {
17
17
  marginBottom: theme.spacing(3),
18
18
  },
19
+ selectorsContainer: {
20
+ display: 'flex',
21
+ flexDirection: 'column',
22
+ gap: 10,
23
+ },
19
24
  }));
20
25
  const ConfirmTrack = observer(function ConfirmTrack({ model, }) {
21
26
  const { classes } = useStyles();
22
- const [check, setCheck] = useState(true);
23
27
  const session = getSession(model);
24
- const { trackName, unsupported, trackAdapter, trackType, warningMessage, adapterHint, } = model;
28
+ const { trackName, unsupported, trackAdapter, trackType, warningMessage, adapterHint, textIndexTrack, } = model;
25
29
  useEffect(() => {
26
30
  if (adapterHint === '' && trackAdapter) {
27
31
  model.setAdapterHint(trackAdapter.type);
28
32
  }
29
- }, [adapterHint, trackAdapter, trackAdapter?.type, model]);
33
+ }, [adapterHint, trackAdapter, model]);
30
34
  if (unsupported) {
31
35
  return _jsx(Unsupported, {});
32
36
  }
@@ -49,20 +53,15 @@ const ConfirmTrack = observer(function ConfirmTrack({ model, }) {
49
53
  },
50
54
  },
51
55
  } })), { model });
52
- return (_jsxs("div", { children: [_jsx(StatusMessage, { trackAdapter: trackAdapter, trackType: trackType }), warningMessage ? (_jsx(Typography, { color: "warning", children: warningMessage })) : null, _jsx(TextField, { className: classes.spacing, label: "trackName", helperText: "A name for this track", fullWidth: true, value: trackName, onChange: event => {
56
+ return (_jsxs("div", { children: [_jsx(StatusMessage, { trackAdapter: trackAdapter, trackType: trackType }), warningMessage ? (_jsx(Typography, { color: "warning", children: warningMessage })) : null, _jsx(TextField, { className: classes.spacing, label: "Track name", helperText: "A name for this track", fullWidth: true, value: trackName, onChange: event => {
53
57
  model.setTrackName(event.target.value);
54
58
  }, slotProps: {
55
59
  htmlInput: {
56
60
  'data-testid': 'trackNameInput',
57
61
  },
58
- } }), _jsxs("div", { style: {
59
- display: 'flex',
60
- flexDirection: 'column',
61
- gap: 10,
62
- }, children: [_jsx(TrackAdapterSelector, { model: model }), _jsx(TrackTypeSelector, { model: model }), _jsx(Suspense, { fallback: null, children: _jsx(Component, { model: model }) })] }), isElectron && supportedForIndexing && (_jsx(FormControl, { children: _jsx(FormControlLabel, { label: "Index track for text searching?", control: _jsx(Checkbox, { checked: check, onChange: e => {
63
- setCheck(e.target.checked);
62
+ } }), _jsxs("div", { className: classes.selectorsContainer, children: [_jsx(TrackAdapterSelector, { model: model }), _jsx(TrackTypeSelector, { model: model }), _jsx(Suspense, { fallback: null, children: _jsx(Component, { model: model }) })] }), isElectron && supportedForIndexing && (_jsx(FormControl, { children: _jsx(FormControlLabel, { label: "Index track for text searching?", control: _jsx(Checkbox, { checked: textIndexTrack, onChange: e => {
64
63
  model.setTextIndexTrack(e.target.checked);
65
- } }) }) })), isElectron && check && supportedForIndexing ? (_jsx(TextIndexingConfig, { model: model })) : null] }));
64
+ } }) }) })), isElectron && textIndexTrack && supportedForIndexing ? (_jsx(TextIndexingConfig, { model: model })) : null] }));
66
65
  }
67
66
  });
68
67
  export default ConfirmTrack;
@@ -35,7 +35,7 @@ const PasteConfigAddTrackWorkflow = observer(function PasteConfigAddTrackWorkflo
35
35
  session.addTrackConf(c);
36
36
  }
37
37
  for (const c of confs) {
38
- model.view.showTrack(c.trackId);
38
+ model.view?.showTrack?.(c.trackId);
39
39
  }
40
40
  model.clearData();
41
41
  });
@@ -17,54 +17,46 @@ const useStyles = makeStyles()(theme => ({
17
17
  }));
18
18
  const TextIndexingConfig = observer(function TextIndexingConfig({ model, }) {
19
19
  const { classes } = useStyles();
20
- const [value1, setValue1] = useState('');
21
- const [value2, setValue2] = useState('');
20
+ const [attributeInput, setAttributeInput] = useState('');
21
+ const [excludeInput, setExcludeInput] = useState('');
22
22
  const [attributes, setAttributes] = useState(['Name', 'ID']);
23
23
  const [exclude, setExclude] = useState(['CDS', 'exon']);
24
24
  const sections = [
25
25
  {
26
26
  label: 'Indexing attributes',
27
27
  values: attributes,
28
+ setValues: setAttributes,
29
+ inputValue: attributeInput,
30
+ setInputValue: setAttributeInput,
28
31
  },
29
32
  {
30
33
  label: 'Feature types to exclude',
31
34
  values: exclude,
35
+ setValues: setExclude,
36
+ inputValue: excludeInput,
37
+ setInputValue: setExcludeInput,
32
38
  },
33
39
  ];
34
40
  useEffect(() => {
35
41
  model.setTextIndexingConf({ attributes, exclude });
36
42
  }, [model, attributes, exclude]);
37
- return (_jsxs(Paper, { className: classes.paper, children: [_jsx(InputLabel, { children: "Indexing configuration" }), sections.map((section, index) => (_jsx(Card, { raised: true, className: classes.card, children: _jsxs(CardContent, { children: [_jsx(InputLabel, { children: section.label }), _jsxs(List, { disablePadding: true, children: [section.values.map((val, idx) => (_jsx(ListItem, { disableGutters: true, children: _jsx(TextField, { value: val, slotProps: {
43
+ return (_jsxs(Paper, { className: classes.paper, children: [_jsx(InputLabel, { children: "Indexing configuration" }), sections.map(section => (_jsx(Card, { raised: true, className: classes.card, children: _jsxs(CardContent, { children: [_jsx(InputLabel, { children: section.label }), _jsxs(List, { disablePadding: true, children: [section.values.map((val, idx) => (_jsx(ListItem, { disableGutters: true, children: _jsx(TextField, { value: val, slotProps: {
38
44
  input: {
39
45
  endAdornment: (_jsx(InputAdornment, { position: "end", children: _jsx(IconButton, { onClick: () => {
40
- const newAttr = section.values.filter((_, i) => i !== idx);
41
- if (index === 0) {
42
- setAttributes(newAttr);
43
- }
44
- else {
45
- setExclude(newAttr);
46
- }
46
+ section.setValues(section.values.filter((_, i) => i !== idx));
47
47
  }, children: _jsx(DeleteIcon, {}) }) })),
48
48
  },
49
- } }) }, `${val}-${idx}`))), _jsx(ListItem, { disableGutters: true, children: _jsx(TextField, { value: index === 0 ? value1 : value2, placeholder: "add new", onChange: event => {
50
- if (index === 0) {
51
- setValue1(event.target.value);
52
- }
53
- else {
54
- setValue2(event.target.value);
55
- }
49
+ } }) }, `${val}-${idx}`))), _jsx(ListItem, { disableGutters: true, children: _jsx(TextField, { value: section.inputValue, placeholder: "add new", onChange: event => {
50
+ section.setInputValue(event.target.value);
56
51
  }, slotProps: {
57
52
  input: {
58
53
  endAdornment: (_jsx(InputAdornment, { position: "end", children: _jsx(IconButton, { onClick: () => {
59
- if (index === 0) {
60
- setAttributes([...attributes, value1]);
61
- setValue1('');
62
- }
63
- else {
64
- setExclude([...exclude, value2]);
65
- setValue2('');
66
- }
67
- }, disabled: index === 0 ? value1 === '' : value2 === '', "data-testid": "stringArrayAdd-Feat", children: _jsx(AddIcon, {}) }) })),
54
+ section.setValues([
55
+ ...section.values,
56
+ section.inputValue,
57
+ ]);
58
+ section.setInputValue('');
59
+ }, disabled: section.inputValue === '', "data-testid": "stringArrayAdd-Feat", children: _jsx(AddIcon, {}) }) })),
68
60
  },
69
61
  } }) })] })] }) }, section.label)))] }));
70
62
  });
@@ -15,6 +15,6 @@ const useStyles = makeStyles()(theme => ({
15
15
  const TrackSourceSelect = observer(function TrackSourceSelect({ model, }) {
16
16
  const { classes } = useStyles();
17
17
  const rootModel = getRoot(model);
18
- return (_jsxs(Paper, { className: classes.paper, children: [_jsx(FileSelector, { name: "Main file", description: "", location: model.trackData, setLocation: model.setTrackData, setName: model.setTrackName, rootModel: rootModel }), _jsx("div", { className: classes.spacer }), _jsx(FileSelector, { name: "Index file", description: "(Optional) The URL of the index file is automatically inferred from the URL of the main file if it is not supplied.", location: model.indexTrackData, setLocation: model.setIndexTrackData, setName: model.setTrackName, rootModel: rootModel })] }));
18
+ return (_jsxs(Paper, { className: classes.paper, children: [_jsx(FileSelector, { name: "Main file", description: "", location: model.trackData, setLocation: model.setTrackData, setName: model.setTrackName, rootModel: rootModel }), _jsx("div", { className: classes.spacer }), _jsx(FileSelector, { name: "Index file", description: "(Optional) The URL of the index file is automatically inferred from the URL of the main file if it is not supplied.", location: model.indexTrackData, setLocation: model.setIndexTrackData, rootModel: rootModel })] }));
19
19
  });
20
20
  export default TrackSourceSelect;
@@ -37,7 +37,7 @@ export function doSubmit({ model }) {
37
37
  isSupportedIndexingAdapter(trackAdapter.type)) {
38
38
  doTextIndexTrack({
39
39
  model,
40
- trackId,
40
+ trackId: String(trackId),
41
41
  });
42
42
  }
43
43
  model.clearData();
@@ -10,7 +10,6 @@ export default function f(pluginManager: PluginManager): import("@jbrowse/mobx-s
10
10
  type: import("@jbrowse/mobx-state-tree").ISimpleType<"AddTrackWidget">;
11
11
  view: import("@jbrowse/mobx-state-tree").IMaybe<import("@jbrowse/mobx-state-tree").IReferenceType<import("@jbrowse/mobx-state-tree").IAnyType>>;
12
12
  }, {
13
- trackSource: string;
14
13
  trackData: FileLocation | undefined;
15
14
  indexTrackData: FileLocation | undefined;
16
15
  altAssemblyName: string;
@@ -19,11 +18,10 @@ export default function f(pluginManager: PluginManager): import("@jbrowse/mobx-s
19
18
  adapterHint: string;
20
19
  textIndexTrack: boolean;
21
20
  textIndexingConf: IndexingAttr | undefined;
22
- mixinData: {};
21
+ mixinData: Record<string, unknown>;
23
22
  } & {
24
23
  setMixinData(arg: Record<string, unknown>): void;
25
24
  setAdapterHint(obj: string): void;
26
- setTrackSource(str: string): void;
27
25
  setTextIndexingConf(conf: IndexingAttr): void;
28
26
  setTextIndexTrack(flag: boolean): void;
29
27
  setTrackData(obj: FileLocation): void;
@@ -39,20 +37,16 @@ export default function f(pluginManager: PluginManager): import("@jbrowse/mobx-s
39
37
  readonly isRelativeTrackUrl: boolean;
40
38
  readonly isRelativeIndexUrl: boolean;
41
39
  readonly isRelativeUrl: boolean;
42
- readonly trackHttp: any;
43
- readonly indexHttp: any;
44
- readonly wrongProtocol: any;
40
+ readonly trackHttp: boolean | undefined;
41
+ readonly indexHttp: boolean | undefined;
42
+ readonly wrongProtocol: boolean | undefined;
45
43
  readonly unsupported: boolean;
46
44
  readonly assembly: any;
47
45
  readonly trackAdapterType: string | undefined;
48
46
  readonly trackType: string;
49
47
  } & {
50
48
  getTrackConfig(timestamp: number): {
51
- trackId: string;
52
- type: string;
53
- name: string;
54
- assemblyNames: any[];
55
- adapter: import("@jbrowse/core/util").AdapterConfig;
49
+ [x: string]: any;
56
50
  } | undefined;
57
51
  readonly warningMessage: "" | "Warning: JBrowse cannot access files using the ftp protocol" | "Warning: one or more of your files do not provide the protocol e.g.\n https://, please provide an absolute URL unless you are sure a\n relative URL is intended." | "Warning: You entered a http:// resources but we cannot access HTTP\n resources from JBrowse when it is running on https. Please use an\n https URL for your track, or access the JBrowse app from the http\n protocol";
58
52
  }, import("@jbrowse/mobx-state-tree")._NotCustomized, import("@jbrowse/mobx-state-tree")._NotCustomized>;
@@ -1,17 +1,31 @@
1
- import { getSession } from '@jbrowse/core/util';
1
+ import { getSession, isUriLocation } from '@jbrowse/core/util';
2
2
  import { UNSUPPORTED, getFileName, guessAdapter, guessTrackType, } from '@jbrowse/core/util/tracks';
3
3
  import { ElementId } from '@jbrowse/core/util/types/mst';
4
4
  import { types } from '@jbrowse/mobx-state-tree';
5
5
  import deepmerge from 'deepmerge';
6
- function isAbsoluteUrl(url = '') {
6
+ function getUri(location) {
7
+ return isUriLocation(location) ? location.uri : undefined;
8
+ }
9
+ function isRelativeUrl(url = '') {
7
10
  try {
8
11
  new URL(url);
9
- return true;
12
+ return false;
10
13
  }
11
- catch (error) {
12
- return url.startsWith('/');
14
+ catch {
15
+ return !url.startsWith('/');
13
16
  }
14
17
  }
18
+ const defaultVolatileState = {
19
+ trackData: undefined,
20
+ indexTrackData: undefined,
21
+ altAssemblyName: '',
22
+ altTrackName: '',
23
+ altTrackType: '',
24
+ adapterHint: '',
25
+ textIndexTrack: true,
26
+ textIndexingConf: undefined,
27
+ mixinData: {},
28
+ };
15
29
  export default function f(pluginManager) {
16
30
  return types
17
31
  .model('AddTrackModel', {
@@ -19,18 +33,7 @@ export default function f(pluginManager) {
19
33
  type: types.literal('AddTrackWidget'),
20
34
  view: types.safeReference(pluginManager.pluggableMstType('view', 'stateModel')),
21
35
  })
22
- .volatile(() => ({
23
- trackSource: 'fromFile',
24
- trackData: undefined,
25
- indexTrackData: undefined,
26
- altAssemblyName: '',
27
- altTrackName: '',
28
- altTrackType: '',
29
- adapterHint: '',
30
- textIndexTrack: true,
31
- textIndexingConf: undefined,
32
- mixinData: {},
33
- }))
36
+ .volatile(() => ({ ...defaultVolatileState }))
34
37
  .actions(self => ({
35
38
  setMixinData(arg) {
36
39
  self.mixinData = arg;
@@ -38,9 +41,6 @@ export default function f(pluginManager) {
38
41
  setAdapterHint(obj) {
39
42
  self.adapterHint = obj;
40
43
  },
41
- setTrackSource(str) {
42
- self.trackSource = str;
43
- },
44
44
  setTextIndexingConf(conf) {
45
45
  self.textIndexingConf = conf;
46
46
  },
@@ -53,6 +53,7 @@ export default function f(pluginManager) {
53
53
  },
54
54
  setIndexTrackData(obj) {
55
55
  self.indexTrackData = obj;
56
+ self.adapterHint = '';
56
57
  },
57
58
  setAssembly(str) {
58
59
  self.altAssemblyName = str;
@@ -64,15 +65,15 @@ export default function f(pluginManager) {
64
65
  self.altTrackType = str;
65
66
  },
66
67
  clearData() {
67
- self.trackSource = '';
68
- self.altTrackName = '';
69
- self.altTrackType = '';
70
- self.altAssemblyName = '';
71
- self.adapterHint = '';
72
- self.indexTrackData = undefined;
73
- self.trackData = undefined;
74
- self.textIndexingConf = undefined;
75
- self.textIndexTrack = true;
68
+ self.altTrackName = defaultVolatileState.altTrackName;
69
+ self.altTrackType = defaultVolatileState.altTrackType;
70
+ self.altAssemblyName = defaultVolatileState.altAssemblyName;
71
+ self.adapterHint = defaultVolatileState.adapterHint;
72
+ self.indexTrackData = defaultVolatileState.indexTrackData;
73
+ self.trackData = defaultVolatileState.trackData;
74
+ self.textIndexingConf = defaultVolatileState.textIndexingConf;
75
+ self.textIndexTrack = defaultVolatileState.textIndexTrack;
76
+ self.mixinData = {};
76
77
  },
77
78
  }))
78
79
  .views(self => ({
@@ -87,25 +88,26 @@ export default function f(pluginManager) {
87
88
  (self.trackData ? getFileName(self.trackData) : ''));
88
89
  },
89
90
  get isFtp() {
90
- const { trackData: track, indexTrackData: index } = self;
91
- return !!((index?.uri?.startsWith('ftp://') || track?.uri?.startsWith('ftp://')));
91
+ const trackUri = getUri(self.trackData);
92
+ const indexUri = getUri(self.indexTrackData);
93
+ return !!(indexUri?.startsWith('ftp://') || trackUri?.startsWith('ftp://'));
92
94
  },
93
95
  get isRelativeTrackUrl() {
94
- const uri = self.trackData?.uri;
95
- return uri ? !isAbsoluteUrl(uri) : false;
96
+ const uri = getUri(self.trackData);
97
+ return uri ? isRelativeUrl(uri) : false;
96
98
  },
97
99
  get isRelativeIndexUrl() {
98
- const uri = self.indexTrackData?.uri;
99
- return uri ? !isAbsoluteUrl(uri) : false;
100
+ const uri = getUri(self.indexTrackData);
101
+ return uri ? isRelativeUrl(uri) : false;
100
102
  },
101
103
  get isRelativeUrl() {
102
104
  return this.isRelativeIndexUrl || this.isRelativeTrackUrl;
103
105
  },
104
106
  get trackHttp() {
105
- return self.trackData?.uri?.startsWith('http://');
107
+ return getUri(self.trackData)?.startsWith('http://');
106
108
  },
107
109
  get indexHttp() {
108
- return self.indexTrackData?.uri?.startsWith('http://');
110
+ return getUri(self.indexTrackData)?.startsWith('http://');
109
111
  },
110
112
  get wrongProtocol() {
111
113
  return (window.location.protocol === 'https:' &&
@@ -115,7 +117,7 @@ export default function f(pluginManager) {
115
117
  return this.trackAdapter?.type === UNSUPPORTED;
116
118
  },
117
119
  get assembly() {
118
- return self.altAssemblyName || self.view.assemblyNames?.[0];
120
+ return self.altAssemblyName || self.view?.assemblyNames?.[0];
119
121
  },
120
122
  get trackAdapterType() {
121
123
  return this.trackAdapter?.type;
@@ -2,7 +2,7 @@ import { HubFile, SingleFileHub } from '@gmod/ucsc-hub';
2
2
  import { getConf } from '@jbrowse/core/configuration';
3
3
  import { getEnv, getSession } from '@jbrowse/core/util';
4
4
  import { openLocation } from '@jbrowse/core/util/io';
5
- import { nanoid } from '@jbrowse/core/util/nanoid';
5
+ import { createElementId } from '@jbrowse/core/util/types/mst';
6
6
  import { generateTracks } from "./ucscTrackHub.js";
7
7
  import { fetchGenomesFile, fetchTrackDbFile, resolve } from "./util.js";
8
8
  export async function doConnect(self) {
@@ -34,7 +34,7 @@ export async function doConnect(self) {
34
34
  }
35
35
  : {}),
36
36
  },
37
- trackId: `${genomeName}-${nanoid()}`,
37
+ trackId: `${genomeName}-${createElementId()}`,
38
38
  adapter: {
39
39
  type: 'TwoBitAdapter',
40
40
  twoBitLocation: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jbrowse/plugin-data-management",
3
- "version": "4.0.3",
3
+ "version": "4.0.4",
4
4
  "description": "JBrowse 2 linear genome view",
5
5
  "keywords": [
6
6
  "jbrowse",
@@ -24,13 +24,13 @@
24
24
  "@jbrowse/mobx-state-tree": "^5.5.0",
25
25
  "@mui/icons-material": "^7.3.6",
26
26
  "@mui/material": "^7.3.6",
27
- "@mui/x-data-grid": "^8.23.0",
27
+ "@mui/x-data-grid": "^8.25.0",
28
28
  "deepmerge": "^4.3.1",
29
29
  "mobx": "^6.15.0",
30
30
  "mobx-react": "^9.2.1",
31
- "@jbrowse/plugin-config": "^4.0.3",
32
- "@jbrowse/product-core": "^4.0.3",
33
- "@jbrowse/core": "^4.0.3"
31
+ "@jbrowse/product-core": "^4.0.4",
32
+ "@jbrowse/core": "^4.0.4",
33
+ "@jbrowse/plugin-config": "^4.0.4"
34
34
  },
35
35
  "peerDependencies": {
36
36
  "react": ">=18.0.0"