@jbrowse/plugin-linear-genome-view 1.7.6 → 1.7.9
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.
- package/dist/BaseLinearDisplay/models/BaseLinearDisplayModel.d.ts +3 -3
- package/dist/BaseLinearDisplay/models/BaseLinearDisplayModel.js +0 -2
- package/dist/LinearGenomeView/components/ExportSvgDialog.js +35 -25
- package/dist/LinearGenomeView/components/ImportForm.js +47 -47
- package/dist/LinearGenomeView/components/RefNameAutocomplete.d.ts +3 -2
- package/dist/LinearGenomeView/components/RefNameAutocomplete.js +7 -5
- package/dist/LinearGenomeView/components/SearchBox.js +31 -22
- package/dist/LinearGenomeView/index.d.ts +4 -3
- package/dist/LinearGenomeView/index.js +1 -1
- package/package.json +2 -2
- package/src/BaseLinearDisplay/models/BaseLinearDisplayModel.tsx +1 -0
- package/src/LinearGenomeView/components/ExportSvgDialog.tsx +24 -11
- package/src/LinearGenomeView/components/ImportForm.tsx +37 -32
- package/src/LinearGenomeView/components/RefNameAutocomplete.tsx +10 -5
- package/src/LinearGenomeView/components/SearchBox.tsx +20 -4
- package/src/LinearGenomeView/index.tsx +2 -1
|
@@ -172,8 +172,8 @@ export declare const BaseLinearDisplay: import("mobx-state-tree").IModelType<{
|
|
|
172
172
|
signal?: AbortSignal;
|
|
173
173
|
filters?: string[];
|
|
174
174
|
}): Promise<{}>;
|
|
175
|
-
setRegionStatsP(p?: Promise<Stats>
|
|
176
|
-
setRegionStats(estimatedRegionStats?: Stats
|
|
175
|
+
setRegionStatsP(p?: Promise<Stats>): void;
|
|
176
|
+
setRegionStats(estimatedRegionStats?: Stats): void;
|
|
177
177
|
clearRegionStats(): void;
|
|
178
178
|
setHeight(displayHeight: number): number;
|
|
179
179
|
resizeHeight(distance: number): number;
|
|
@@ -186,7 +186,7 @@ export declare const BaseLinearDisplay: import("mobx-state-tree").IModelType<{
|
|
|
186
186
|
clearFeatureSelection(): void;
|
|
187
187
|
setFeatureIdUnderMouse(feature: string | undefined): void;
|
|
188
188
|
reload(): void;
|
|
189
|
-
setContextMenuFeature(feature?: Feature
|
|
189
|
+
setContextMenuFeature(feature?: Feature): void;
|
|
190
190
|
} & {
|
|
191
191
|
readonly regionTooLarge: boolean;
|
|
192
192
|
readonly regionTooLargeReason: string;
|
|
@@ -693,8 +693,6 @@ var BaseLinearDisplay = _mobxStateTree.types.compose('BaseLinearDisplay', _model
|
|
|
693
693
|
// version, or just get the default if none available
|
|
694
694
|
|
|
695
695
|
|
|
696
|
-
// regionCannotBeRendered can return jsx so look for plaintext
|
|
697
|
-
// version, or just get the default if none available
|
|
698
696
|
var cannotBeRenderedReason = self.regionCannotBeRenderedText(block) || self.regionCannotBeRendered(block);
|
|
699
697
|
|
|
700
698
|
if (cannotBeRenderedReason) {
|
|
@@ -17,17 +17,17 @@ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/sli
|
|
|
17
17
|
|
|
18
18
|
var _react = _interopRequireWildcard(require("react"));
|
|
19
19
|
|
|
20
|
-
var _styles = require("@material-ui/core/styles");
|
|
21
|
-
|
|
22
20
|
var _core = require("@material-ui/core");
|
|
23
21
|
|
|
22
|
+
var _ui = require("@jbrowse/core/ui");
|
|
23
|
+
|
|
24
24
|
var _Close = _interopRequireDefault(require("@material-ui/icons/Close"));
|
|
25
25
|
|
|
26
26
|
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
27
27
|
|
|
28
28
|
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
29
29
|
|
|
30
|
-
var useStyles = (0,
|
|
30
|
+
var useStyles = (0, _core.makeStyles)(function (theme) {
|
|
31
31
|
return {
|
|
32
32
|
closeButton: {
|
|
33
33
|
position: 'absolute',
|
|
@@ -38,6 +38,17 @@ var useStyles = (0, _styles.makeStyles)(function (theme) {
|
|
|
38
38
|
};
|
|
39
39
|
});
|
|
40
40
|
|
|
41
|
+
function LoadingMessage() {
|
|
42
|
+
return /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement(_core.CircularProgress, {
|
|
43
|
+
size: 20,
|
|
44
|
+
style: {
|
|
45
|
+
marginRight: 20
|
|
46
|
+
}
|
|
47
|
+
}), /*#__PURE__*/_react.default.createElement(_core.Typography, {
|
|
48
|
+
display: "inline"
|
|
49
|
+
}, "Creating SVG"));
|
|
50
|
+
}
|
|
51
|
+
|
|
41
52
|
function ExportSvgDlg(_ref) {
|
|
42
53
|
var model = _ref.model,
|
|
43
54
|
handleClose = _ref.handleClose;
|
|
@@ -54,10 +65,15 @@ function ExportSvgDlg(_ref) {
|
|
|
54
65
|
loading = _useState4[0],
|
|
55
66
|
setLoading = _useState4[1];
|
|
56
67
|
|
|
57
|
-
var _useState5 = (0, _react.useState)(),
|
|
68
|
+
var _useState5 = (0, _react.useState)('jbrowse.svg'),
|
|
58
69
|
_useState6 = (0, _slicedToArray2.default)(_useState5, 2),
|
|
59
|
-
|
|
60
|
-
|
|
70
|
+
filename = _useState6[0],
|
|
71
|
+
setFilename = _useState6[1];
|
|
72
|
+
|
|
73
|
+
var _useState7 = (0, _react.useState)(),
|
|
74
|
+
_useState8 = (0, _slicedToArray2.default)(_useState7, 2),
|
|
75
|
+
error = _useState8[0],
|
|
76
|
+
setError = _useState8[1];
|
|
61
77
|
|
|
62
78
|
var classes = useStyles();
|
|
63
79
|
return /*#__PURE__*/_react.default.createElement(_core.Dialog, {
|
|
@@ -66,18 +82,15 @@ function ExportSvgDlg(_ref) {
|
|
|
66
82
|
}, /*#__PURE__*/_react.default.createElement(_core.DialogTitle, null, "Export SVG", /*#__PURE__*/_react.default.createElement(_core.IconButton, {
|
|
67
83
|
className: classes.closeButton,
|
|
68
84
|
onClick: handleClose
|
|
69
|
-
}, /*#__PURE__*/_react.default.createElement(_Close.default, null))), /*#__PURE__*/_react.default.createElement(_core.DialogContent, null, error ? /*#__PURE__*/_react.default.createElement(
|
|
70
|
-
|
|
71
|
-
|
|
85
|
+
}, /*#__PURE__*/_react.default.createElement(_Close.default, null))), /*#__PURE__*/_react.default.createElement(_core.DialogContent, null, error ? /*#__PURE__*/_react.default.createElement(_ui.ErrorMessage, {
|
|
86
|
+
error: error
|
|
87
|
+
}) : loading ? /*#__PURE__*/_react.default.createElement(LoadingMessage, null) : null, /*#__PURE__*/_react.default.createElement(_core.TextField, {
|
|
88
|
+
helperText: "filename",
|
|
89
|
+
value: filename,
|
|
90
|
+
onChange: function onChange(event) {
|
|
91
|
+
return setFilename(event.target.value);
|
|
72
92
|
}
|
|
73
|
-
},
|
|
74
|
-
size: 20,
|
|
75
|
-
style: {
|
|
76
|
-
marginRight: 20
|
|
77
|
-
}
|
|
78
|
-
}), /*#__PURE__*/_react.default.createElement(_core.Typography, {
|
|
79
|
-
display: "inline"
|
|
80
|
-
}, "Creating SVG")) : null, offscreenCanvas ? /*#__PURE__*/_react.default.createElement(_core.FormControlLabel, {
|
|
93
|
+
}), offscreenCanvas ? /*#__PURE__*/_react.default.createElement(_core.FormControlLabel, {
|
|
81
94
|
control: /*#__PURE__*/_react.default.createElement(_core.Checkbox, {
|
|
82
95
|
checked: rasterizeLayers,
|
|
83
96
|
onChange: function onChange() {
|
|
@@ -107,12 +120,13 @@ function ExportSvgDlg(_ref) {
|
|
|
107
120
|
_context.prev = 2;
|
|
108
121
|
_context.next = 5;
|
|
109
122
|
return model.exportSvg({
|
|
110
|
-
rasterizeLayers: rasterizeLayers
|
|
123
|
+
rasterizeLayers: rasterizeLayers,
|
|
124
|
+
filename: filename
|
|
111
125
|
});
|
|
112
126
|
|
|
113
127
|
case 5:
|
|
114
128
|
handleClose();
|
|
115
|
-
_context.next =
|
|
129
|
+
_context.next = 13;
|
|
116
130
|
break;
|
|
117
131
|
|
|
118
132
|
case 8:
|
|
@@ -120,18 +134,14 @@ function ExportSvgDlg(_ref) {
|
|
|
120
134
|
_context.t0 = _context["catch"](2);
|
|
121
135
|
console.error(_context.t0);
|
|
122
136
|
setError(_context.t0);
|
|
123
|
-
|
|
124
|
-
case 12:
|
|
125
|
-
_context.prev = 12;
|
|
126
137
|
setLoading(false);
|
|
127
|
-
return _context.finish(12);
|
|
128
138
|
|
|
129
|
-
case
|
|
139
|
+
case 13:
|
|
130
140
|
case "end":
|
|
131
141
|
return _context.stop();
|
|
132
142
|
}
|
|
133
143
|
}
|
|
134
|
-
}, _callee, null, [[2, 8
|
|
144
|
+
}, _callee, null, [[2, 8]]);
|
|
135
145
|
}))
|
|
136
146
|
}, "Submit")));
|
|
137
147
|
}
|
|
@@ -70,35 +70,35 @@ var ImportForm = (0, _mobxReact.observer)(function (_ref) {
|
|
|
70
70
|
textSearchManager = session.textSearchManager;
|
|
71
71
|
var rankSearchResults = model.rankSearchResults,
|
|
72
72
|
isSearchDialogDisplayed = model.isSearchDialogDisplayed,
|
|
73
|
-
|
|
73
|
+
error = model.error;
|
|
74
74
|
|
|
75
75
|
var _useState = (0, _react.useState)(assemblyNames[0]),
|
|
76
76
|
_useState2 = (0, _slicedToArray2.default)(_useState, 2),
|
|
77
77
|
selectedAsm = _useState2[0],
|
|
78
78
|
setSelectedAsm = _useState2[1];
|
|
79
79
|
|
|
80
|
-
var _useState3 = (0, _react.useState)(
|
|
80
|
+
var _useState3 = (0, _react.useState)(error),
|
|
81
81
|
_useState4 = (0, _slicedToArray2.default)(_useState3, 2),
|
|
82
|
-
|
|
83
|
-
|
|
82
|
+
importError = _useState4[0],
|
|
83
|
+
setImportError = _useState4[1];
|
|
84
84
|
|
|
85
85
|
var searchScope = model.searchScope(selectedAsm);
|
|
86
86
|
var assembly = assemblyManager.get(selectedAsm);
|
|
87
87
|
var assemblyError = assemblyNames.length ? assembly === null || assembly === void 0 ? void 0 : assembly.error : 'No configured assemblies';
|
|
88
88
|
var regions = (assembly === null || assembly === void 0 ? void 0 : assembly.regions) || [];
|
|
89
|
-
var err = assemblyError ||
|
|
89
|
+
var err = assemblyError || importError;
|
|
90
90
|
|
|
91
|
-
var _useState5 = (0, _react.useState)(),
|
|
91
|
+
var _useState5 = (0, _react.useState)(''),
|
|
92
92
|
_useState6 = (0, _slicedToArray2.default)(_useState5, 2),
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
// won't update in response to an observable
|
|
93
|
+
myVal = _useState6[0],
|
|
94
|
+
setValue = _useState6[1];
|
|
96
95
|
|
|
96
|
+
var value = myVal || ((_regions$ = regions[0]) === null || _regions$ === void 0 ? void 0 : _regions$.refName); // use this instead of useState initializer because the useState initializer
|
|
97
|
+
// won't update in response to an observable
|
|
97
98
|
|
|
98
|
-
var option =
|
|
99
|
-
label:
|
|
99
|
+
var option = new _BaseResults.default({
|
|
100
|
+
label: value
|
|
100
101
|
});
|
|
101
|
-
var selectedRegion = option === null || option === void 0 ? void 0 : option.getLocation();
|
|
102
102
|
|
|
103
103
|
function fetchResults(_x, _x2) {
|
|
104
104
|
return _fetchResults.apply(this, arguments);
|
|
@@ -155,7 +155,7 @@ var ImportForm = (0, _mobxReact.observer)(function (_ref) {
|
|
|
155
155
|
|
|
156
156
|
function _handleSelectedRegion() {
|
|
157
157
|
_handleSelectedRegion = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee2(input) {
|
|
158
|
-
var trackId, location,
|
|
158
|
+
var trackId, location, _location$split, _location$split2, ref, rest, allRefs, results;
|
|
159
159
|
|
|
160
160
|
return _regenerator.default.wrap(function _callee2$(_context2) {
|
|
161
161
|
while (1) {
|
|
@@ -171,61 +171,63 @@ var ImportForm = (0, _mobxReact.observer)(function (_ref) {
|
|
|
171
171
|
case 2:
|
|
172
172
|
trackId = option.getTrackId();
|
|
173
173
|
location = input || option.getLocation() || '';
|
|
174
|
-
|
|
174
|
+
_location$split = location.split(':'), _location$split2 = (0, _slicedToArray2.default)(_location$split, 2), ref = _location$split2[0], rest = _location$split2[1];
|
|
175
|
+
allRefs = (assembly === null || assembly === void 0 ? void 0 : assembly.allRefNames) || [];
|
|
176
|
+
_context2.prev = 6;
|
|
175
177
|
|
|
176
|
-
if (!(
|
|
177
|
-
_context2.next =
|
|
178
|
+
if (!(allRefs.includes(location) || allRefs.includes(ref) && rest !== undefined && !Number.isNaN(parseInt(rest, 10)))) {
|
|
179
|
+
_context2.next = 11;
|
|
178
180
|
break;
|
|
179
181
|
}
|
|
180
182
|
|
|
181
183
|
model.navToLocString(location, selectedAsm);
|
|
182
|
-
_context2.next =
|
|
184
|
+
_context2.next = 22;
|
|
183
185
|
break;
|
|
184
186
|
|
|
185
|
-
case
|
|
186
|
-
_context2.next =
|
|
187
|
+
case 11:
|
|
188
|
+
_context2.next = 13;
|
|
187
189
|
return fetchResults(input, 'exact');
|
|
188
190
|
|
|
189
|
-
case
|
|
191
|
+
case 13:
|
|
190
192
|
results = _context2.sent;
|
|
191
193
|
|
|
192
|
-
if (!(results
|
|
193
|
-
_context2.next =
|
|
194
|
+
if (!(results.length > 1)) {
|
|
195
|
+
_context2.next = 19;
|
|
194
196
|
break;
|
|
195
197
|
}
|
|
196
198
|
|
|
197
199
|
model.setSearchResults(results, input.toLowerCase());
|
|
198
200
|
return _context2.abrupt("return");
|
|
199
201
|
|
|
200
|
-
case
|
|
201
|
-
if (
|
|
202
|
+
case 19:
|
|
203
|
+
if (results.length === 1) {
|
|
202
204
|
location = results[0].getLocation();
|
|
203
205
|
trackId = results[0].getTrackId();
|
|
204
206
|
}
|
|
205
207
|
|
|
206
|
-
case
|
|
208
|
+
case 20:
|
|
207
209
|
model.navToLocString(location, selectedAsm);
|
|
208
210
|
|
|
209
211
|
if (trackId) {
|
|
210
212
|
model.showTrack(trackId);
|
|
211
213
|
}
|
|
212
214
|
|
|
213
|
-
case
|
|
214
|
-
_context2.next =
|
|
215
|
+
case 22:
|
|
216
|
+
_context2.next = 28;
|
|
215
217
|
break;
|
|
216
218
|
|
|
217
|
-
case
|
|
218
|
-
_context2.prev =
|
|
219
|
-
_context2.t0 = _context2["catch"](
|
|
219
|
+
case 24:
|
|
220
|
+
_context2.prev = 24;
|
|
221
|
+
_context2.t0 = _context2["catch"](6);
|
|
220
222
|
console.error(_context2.t0);
|
|
221
223
|
session.notify("".concat(_context2.t0), 'warning');
|
|
222
224
|
|
|
223
|
-
case
|
|
225
|
+
case 28:
|
|
224
226
|
case "end":
|
|
225
227
|
return _context2.stop();
|
|
226
228
|
}
|
|
227
229
|
}
|
|
228
|
-
}, _callee2, null, [[
|
|
230
|
+
}, _callee2, null, [[6, 24]]);
|
|
229
231
|
}));
|
|
230
232
|
return _handleSelectedRegion.apply(this, arguments);
|
|
231
233
|
}
|
|
@@ -241,7 +243,12 @@ var ImportForm = (0, _mobxReact.observer)(function (_ref) {
|
|
|
241
243
|
className: classes.importFormContainer
|
|
242
244
|
}, /*#__PURE__*/_react.default.createElement("form", {
|
|
243
245
|
onSubmit: function onSubmit(event) {
|
|
244
|
-
|
|
246
|
+
event.preventDefault();
|
|
247
|
+
model.setError(undefined);
|
|
248
|
+
|
|
249
|
+
if (value) {
|
|
250
|
+
handleSelectedRegion(value);
|
|
251
|
+
}
|
|
245
252
|
}
|
|
246
253
|
}, /*#__PURE__*/_react.default.createElement(_core.Grid, {
|
|
247
254
|
container: true,
|
|
@@ -252,7 +259,7 @@ var ImportForm = (0, _mobxReact.observer)(function (_ref) {
|
|
|
252
259
|
item: true
|
|
253
260
|
}, /*#__PURE__*/_react.default.createElement(_AssemblySelector.default, {
|
|
254
261
|
onChange: function onChange(val) {
|
|
255
|
-
|
|
262
|
+
setImportError('');
|
|
256
263
|
setSelectedAsm(val);
|
|
257
264
|
},
|
|
258
265
|
session: session,
|
|
@@ -268,15 +275,15 @@ var ImportForm = (0, _mobxReact.observer)(function (_ref) {
|
|
|
268
275
|
style: {
|
|
269
276
|
color: 'red'
|
|
270
277
|
}
|
|
271
|
-
}) :
|
|
278
|
+
}) : value ? /*#__PURE__*/_react.default.createElement(_RefNameAutocomplete.default, {
|
|
272
279
|
fetchResults: fetchResults,
|
|
273
280
|
model: model,
|
|
274
281
|
assemblyName: assemblyError ? undefined : selectedAsm,
|
|
275
|
-
value:
|
|
282
|
+
value: value // note: minWidth 270 accomodates full width of helperText
|
|
276
283
|
,
|
|
277
284
|
minWidth: 270,
|
|
278
|
-
|
|
279
|
-
return
|
|
285
|
+
onChange: function onChange(str) {
|
|
286
|
+
return setValue(str);
|
|
280
287
|
},
|
|
281
288
|
TextFieldProps: {
|
|
282
289
|
variant: 'outlined',
|
|
@@ -298,19 +305,12 @@ var ImportForm = (0, _mobxReact.observer)(function (_ref) {
|
|
|
298
305
|
item: true
|
|
299
306
|
}, /*#__PURE__*/_react.default.createElement(_core.Button, {
|
|
300
307
|
type: "submit",
|
|
301
|
-
disabled: !
|
|
308
|
+
disabled: !value,
|
|
302
309
|
className: classes.button,
|
|
303
|
-
onClick: function onClick() {
|
|
304
|
-
model.setError(undefined);
|
|
305
|
-
|
|
306
|
-
if (selectedRegion) {
|
|
307
|
-
handleSelectedRegion(selectedRegion);
|
|
308
|
-
}
|
|
309
|
-
},
|
|
310
310
|
variant: "contained",
|
|
311
311
|
color: "primary"
|
|
312
312
|
}, "Open"), /*#__PURE__*/_react.default.createElement(_core.Button, {
|
|
313
|
-
disabled: !
|
|
313
|
+
disabled: !value,
|
|
314
314
|
className: classes.button,
|
|
315
315
|
onClick: function onClick() {
|
|
316
316
|
model.setError(undefined);
|
|
@@ -6,9 +6,10 @@ export interface Option {
|
|
|
6
6
|
group?: string;
|
|
7
7
|
result: BaseResult;
|
|
8
8
|
}
|
|
9
|
-
declare function RefNameAutocomplete({ model,
|
|
9
|
+
declare function RefNameAutocomplete({ model, onSelect, assemblyName, style, fetchResults, onChange, value, showHelp, minWidth, TextFieldProps, }: {
|
|
10
10
|
model: LinearGenomeViewModel;
|
|
11
|
-
onSelect
|
|
11
|
+
onSelect?: (region: BaseResult) => void;
|
|
12
|
+
onChange?: (val: string) => void;
|
|
12
13
|
assemblyName?: string;
|
|
13
14
|
value?: string;
|
|
14
15
|
fetchResults: (query: string) => Promise<BaseResult[]>;
|
|
@@ -80,13 +80,14 @@ var MyPopper = function MyPopper(props) {
|
|
|
80
80
|
|
|
81
81
|
function RefNameAutocomplete(_ref) {
|
|
82
82
|
var model = _ref.model,
|
|
83
|
-
_ref$showHelp = _ref.showHelp,
|
|
84
|
-
showHelp = _ref$showHelp === void 0 ? true : _ref$showHelp,
|
|
85
83
|
onSelect = _ref.onSelect,
|
|
86
84
|
assemblyName = _ref.assemblyName,
|
|
87
85
|
style = _ref.style,
|
|
88
86
|
fetchResults = _ref.fetchResults,
|
|
87
|
+
onChange = _ref.onChange,
|
|
89
88
|
value = _ref.value,
|
|
89
|
+
_ref$showHelp = _ref.showHelp,
|
|
90
|
+
showHelp = _ref$showHelp === void 0 ? true : _ref$showHelp,
|
|
90
91
|
_ref$minWidth = _ref.minWidth,
|
|
91
92
|
minWidth = _ref$minWidth === void 0 ? 200 : _ref$minWidth,
|
|
92
93
|
_ref$TextFieldProps = _ref.TextFieldProps,
|
|
@@ -223,7 +224,8 @@ function RefNameAutocomplete(_ref) {
|
|
|
223
224
|
loading: !loaded,
|
|
224
225
|
inputValue: inputValue,
|
|
225
226
|
onInputChange: function onInputChange(event, newInputValue) {
|
|
226
|
-
|
|
227
|
+
setInputValue(newInputValue);
|
|
228
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(newInputValue);
|
|
227
229
|
},
|
|
228
230
|
loadingText: "loading results",
|
|
229
231
|
open: open,
|
|
@@ -246,11 +248,11 @@ function RefNameAutocomplete(_ref) {
|
|
|
246
248
|
|
|
247
249
|
if (typeof selectedOption === 'string') {
|
|
248
250
|
// handles string inputs on keyPress enter
|
|
249
|
-
onSelect(new _BaseResults.default({
|
|
251
|
+
onSelect === null || onSelect === void 0 ? void 0 : onSelect(new _BaseResults.default({
|
|
250
252
|
label: selectedOption
|
|
251
253
|
}));
|
|
252
254
|
} else {
|
|
253
|
-
onSelect(selectedOption.result);
|
|
255
|
+
onSelect === null || onSelect === void 0 ? void 0 : onSelect(selectedOption.result);
|
|
254
256
|
}
|
|
255
257
|
|
|
256
258
|
setInputValue(inputBoxVal);
|
|
@@ -9,6 +9,8 @@ exports.default = void 0;
|
|
|
9
9
|
|
|
10
10
|
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
|
|
11
11
|
|
|
12
|
+
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
|
13
|
+
|
|
12
14
|
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
|
13
15
|
|
|
14
16
|
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
|
|
@@ -54,7 +56,12 @@ function SearchBox(_ref) {
|
|
|
54
56
|
|
|
55
57
|
function fetchResults(_x, _x2) {
|
|
56
58
|
return _fetchResults.apply(this, arguments);
|
|
57
|
-
}
|
|
59
|
+
} // gets a string as input, or use stored option results from previous query,
|
|
60
|
+
// then re-query and
|
|
61
|
+
// 1) if it has multiple results: pop a dialog
|
|
62
|
+
// 2) if it's a single result navigate to it
|
|
63
|
+
// 3) else assume it's a locstring and navigate to it
|
|
64
|
+
|
|
58
65
|
|
|
59
66
|
function _fetchResults() {
|
|
60
67
|
_fetchResults = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(query, searchType) {
|
|
@@ -104,7 +111,7 @@ function SearchBox(_ref) {
|
|
|
104
111
|
|
|
105
112
|
function _handleSelectedRegion() {
|
|
106
113
|
_handleSelectedRegion = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee2(option) {
|
|
107
|
-
var trackId, location, label,
|
|
114
|
+
var trackId, location, label, _location$split, _location$split2, ref, rest, allRefs, results;
|
|
108
115
|
|
|
109
116
|
return _regenerator.default.wrap(function _callee2$(_context2) {
|
|
110
117
|
while (1) {
|
|
@@ -113,61 +120,63 @@ function SearchBox(_ref) {
|
|
|
113
120
|
trackId = option.getTrackId();
|
|
114
121
|
location = option.getLocation();
|
|
115
122
|
label = option.getLabel();
|
|
116
|
-
|
|
123
|
+
_location$split = location.split(':'), _location$split2 = (0, _slicedToArray2.default)(_location$split, 2), ref = _location$split2[0], rest = _location$split2[1];
|
|
124
|
+
allRefs = (assembly === null || assembly === void 0 ? void 0 : assembly.allRefNames) || [];
|
|
125
|
+
_context2.prev = 5;
|
|
117
126
|
|
|
118
|
-
if (!(
|
|
119
|
-
_context2.next =
|
|
127
|
+
if (!(allRefs.includes(location) || allRefs.includes(ref) && rest !== undefined && !Number.isNaN(parseInt(rest, 10)))) {
|
|
128
|
+
_context2.next = 10;
|
|
120
129
|
break;
|
|
121
130
|
}
|
|
122
131
|
|
|
123
|
-
model.navToLocString(location);
|
|
124
|
-
_context2.next =
|
|
132
|
+
model.navToLocString(location, assemblyName);
|
|
133
|
+
_context2.next = 21;
|
|
125
134
|
break;
|
|
126
135
|
|
|
127
|
-
case
|
|
128
|
-
_context2.next =
|
|
136
|
+
case 10:
|
|
137
|
+
_context2.next = 12;
|
|
129
138
|
return fetchResults(label, 'exact');
|
|
130
139
|
|
|
131
|
-
case
|
|
140
|
+
case 12:
|
|
132
141
|
results = _context2.sent;
|
|
133
142
|
|
|
134
|
-
if (!(results
|
|
135
|
-
_context2.next =
|
|
143
|
+
if (!(results.length > 1)) {
|
|
144
|
+
_context2.next = 18;
|
|
136
145
|
break;
|
|
137
146
|
}
|
|
138
147
|
|
|
139
148
|
model.setSearchResults(results, label.toLowerCase());
|
|
140
149
|
return _context2.abrupt("return");
|
|
141
150
|
|
|
142
|
-
case
|
|
143
|
-
if (
|
|
151
|
+
case 18:
|
|
152
|
+
if (results.length === 1) {
|
|
144
153
|
location = results[0].getLocation();
|
|
145
154
|
trackId = results[0].getTrackId();
|
|
146
155
|
}
|
|
147
156
|
|
|
148
|
-
case
|
|
157
|
+
case 19:
|
|
149
158
|
model.navToLocString(location, assemblyName);
|
|
150
159
|
|
|
151
160
|
if (trackId) {
|
|
152
161
|
model.showTrack(trackId);
|
|
153
162
|
}
|
|
154
163
|
|
|
155
|
-
case
|
|
156
|
-
_context2.next =
|
|
164
|
+
case 21:
|
|
165
|
+
_context2.next = 27;
|
|
157
166
|
break;
|
|
158
167
|
|
|
159
|
-
case
|
|
160
|
-
_context2.prev =
|
|
161
|
-
_context2.t0 = _context2["catch"](
|
|
168
|
+
case 23:
|
|
169
|
+
_context2.prev = 23;
|
|
170
|
+
_context2.t0 = _context2["catch"](5);
|
|
162
171
|
console.error(_context2.t0);
|
|
163
172
|
session.notify("".concat(_context2.t0), 'warning');
|
|
164
173
|
|
|
165
|
-
case
|
|
174
|
+
case 27:
|
|
166
175
|
case "end":
|
|
167
176
|
return _context2.stop();
|
|
168
177
|
}
|
|
169
178
|
}
|
|
170
|
-
}, _callee2, null, [[
|
|
179
|
+
}, _callee2, null, [[5, 23]]);
|
|
171
180
|
}));
|
|
172
181
|
return _handleSelectedRegion.apply(this, arguments);
|
|
173
182
|
}
|
|
@@ -20,6 +20,7 @@ export interface BpOffset {
|
|
|
20
20
|
}
|
|
21
21
|
export interface ExportSvgOptions {
|
|
22
22
|
rasterizeLayers?: boolean;
|
|
23
|
+
filename?: string;
|
|
23
24
|
}
|
|
24
25
|
export interface NavLocation {
|
|
25
26
|
refName: string;
|
|
@@ -180,7 +181,7 @@ export declare function stateModelFactory(pluginManager: PluginManager): import(
|
|
|
180
181
|
toggleCenterLine(): void;
|
|
181
182
|
setDisplayedRegions(regions: Region[]): void;
|
|
182
183
|
activateTrackSelector(): import("@jbrowse/core/util").Widget;
|
|
183
|
-
navToLocString(locString: string, optAssemblyName?: string
|
|
184
|
+
navToLocString(locString: string, optAssemblyName?: string): void;
|
|
184
185
|
/**
|
|
185
186
|
* Navigate to a location based on its refName and optionally start, end,
|
|
186
187
|
* and assemblyName. Can handle if there are multiple displayedRegions
|
|
@@ -245,8 +246,8 @@ export declare function stateModelFactory(pluginManager: PluginManager): import(
|
|
|
245
246
|
centerAt(bp: number, refName: string, regionIndex: number): void;
|
|
246
247
|
center(): void;
|
|
247
248
|
showAllRegions(): void;
|
|
248
|
-
showAllRegionsInAssembly(assemblyName?: string
|
|
249
|
-
setDraggingTrackId(idx?: string
|
|
249
|
+
showAllRegionsInAssembly(assemblyName?: string): void;
|
|
250
|
+
setDraggingTrackId(idx?: string): void;
|
|
250
251
|
setScaleFactor(factor: number): void;
|
|
251
252
|
} & {
|
|
252
253
|
slide: (viewWidths: number) => void;
|
|
@@ -1380,7 +1380,7 @@ function stateModelFactory(pluginManager) {
|
|
|
1380
1380
|
blob = new Blob([html], {
|
|
1381
1381
|
type: 'image/svg+xml'
|
|
1382
1382
|
});
|
|
1383
|
-
(0, _fileSaver.saveAs)(blob, 'image.svg');
|
|
1383
|
+
(0, _fileSaver.saveAs)(blob, opts.filename || 'image.svg');
|
|
1384
1384
|
|
|
1385
1385
|
case 6:
|
|
1386
1386
|
case "end":
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jbrowse/plugin-linear-genome-view",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.9",
|
|
4
4
|
"description": "JBrowse 2 linear genome view",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"jbrowse",
|
|
@@ -57,5 +57,5 @@
|
|
|
57
57
|
"publishConfig": {
|
|
58
58
|
"access": "public"
|
|
59
59
|
},
|
|
60
|
-
"gitHead": "
|
|
60
|
+
"gitHead": "a6504c385d703ce6e755d05652ef659ffe28c864"
|
|
61
61
|
}
|
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
import React, { useState } from 'react'
|
|
2
|
-
import { makeStyles } from '@material-ui/core/styles'
|
|
3
2
|
import {
|
|
4
3
|
Button,
|
|
4
|
+
Checkbox,
|
|
5
|
+
CircularProgress,
|
|
5
6
|
Dialog,
|
|
6
7
|
DialogActions,
|
|
7
8
|
DialogContent,
|
|
8
9
|
DialogTitle,
|
|
9
|
-
IconButton,
|
|
10
|
-
Checkbox,
|
|
11
10
|
FormControlLabel,
|
|
12
|
-
|
|
11
|
+
IconButton,
|
|
12
|
+
TextField,
|
|
13
13
|
Typography,
|
|
14
|
+
makeStyles,
|
|
14
15
|
} from '@material-ui/core'
|
|
16
|
+
import { ErrorMessage } from '@jbrowse/core/ui'
|
|
15
17
|
import CloseIcon from '@material-ui/icons/Close'
|
|
16
18
|
import { LinearGenomeViewModel as LGV } from '..'
|
|
17
19
|
|
|
@@ -24,6 +26,15 @@ const useStyles = makeStyles(theme => ({
|
|
|
24
26
|
},
|
|
25
27
|
}))
|
|
26
28
|
|
|
29
|
+
function LoadingMessage() {
|
|
30
|
+
return (
|
|
31
|
+
<div>
|
|
32
|
+
<CircularProgress size={20} style={{ marginRight: 20 }} />
|
|
33
|
+
<Typography display="inline">Creating SVG</Typography>
|
|
34
|
+
</div>
|
|
35
|
+
)
|
|
36
|
+
}
|
|
37
|
+
|
|
27
38
|
export default function ExportSvgDlg({
|
|
28
39
|
model,
|
|
29
40
|
handleClose,
|
|
@@ -35,6 +46,7 @@ export default function ExportSvgDlg({
|
|
|
35
46
|
const offscreenCanvas = typeof OffscreenCanvas !== 'undefined'
|
|
36
47
|
const [rasterizeLayers, setRasterizeLayers] = useState(offscreenCanvas)
|
|
37
48
|
const [loading, setLoading] = useState(false)
|
|
49
|
+
const [filename, setFilename] = useState('jbrowse.svg')
|
|
38
50
|
const [error, setError] = useState<unknown>()
|
|
39
51
|
const classes = useStyles()
|
|
40
52
|
return (
|
|
@@ -47,13 +59,15 @@ export default function ExportSvgDlg({
|
|
|
47
59
|
</DialogTitle>
|
|
48
60
|
<DialogContent>
|
|
49
61
|
{error ? (
|
|
50
|
-
<
|
|
62
|
+
<ErrorMessage error={error} />
|
|
51
63
|
) : loading ? (
|
|
52
|
-
<
|
|
53
|
-
<CircularProgress size={20} style={{ marginRight: 20 }} />
|
|
54
|
-
<Typography display="inline">Creating SVG</Typography>
|
|
55
|
-
</div>
|
|
64
|
+
<LoadingMessage />
|
|
56
65
|
) : null}
|
|
66
|
+
<TextField
|
|
67
|
+
helperText="filename"
|
|
68
|
+
value={filename}
|
|
69
|
+
onChange={event => setFilename(event.target.value)}
|
|
70
|
+
/>
|
|
57
71
|
{offscreenCanvas ? (
|
|
58
72
|
<FormControlLabel
|
|
59
73
|
control={
|
|
@@ -87,12 +101,11 @@ export default function ExportSvgDlg({
|
|
|
87
101
|
setLoading(true)
|
|
88
102
|
setError(undefined)
|
|
89
103
|
try {
|
|
90
|
-
await model.exportSvg({ rasterizeLayers })
|
|
104
|
+
await model.exportSvg({ rasterizeLayers, filename })
|
|
91
105
|
handleClose()
|
|
92
106
|
} catch (e) {
|
|
93
107
|
console.error(e)
|
|
94
108
|
setError(e)
|
|
95
|
-
} finally {
|
|
96
109
|
setLoading(false)
|
|
97
110
|
}
|
|
98
111
|
}}
|
|
@@ -37,13 +37,9 @@ const ImportForm = observer(({ model }: { model: LGV }) => {
|
|
|
37
37
|
const classes = useStyles()
|
|
38
38
|
const session = getSession(model)
|
|
39
39
|
const { assemblyNames, assemblyManager, textSearchManager } = session
|
|
40
|
-
const {
|
|
41
|
-
rankSearchResults,
|
|
42
|
-
isSearchDialogDisplayed,
|
|
43
|
-
error: modelError,
|
|
44
|
-
} = model
|
|
40
|
+
const { rankSearchResults, isSearchDialogDisplayed, error } = model
|
|
45
41
|
const [selectedAsm, setSelectedAsm] = useState(assemblyNames[0])
|
|
46
|
-
const [
|
|
42
|
+
const [importError, setImportError] = useState(error)
|
|
47
43
|
const searchScope = model.searchScope(selectedAsm)
|
|
48
44
|
|
|
49
45
|
const assembly = assemblyManager.get(selectedAsm)
|
|
@@ -51,19 +47,15 @@ const ImportForm = observer(({ model }: { model: LGV }) => {
|
|
|
51
47
|
? assembly?.error
|
|
52
48
|
: 'No configured assemblies'
|
|
53
49
|
const regions = assembly?.regions || []
|
|
54
|
-
const err = assemblyError ||
|
|
55
|
-
|
|
56
|
-
const
|
|
50
|
+
const err = assemblyError || importError
|
|
51
|
+
const [myVal, setValue] = useState('')
|
|
52
|
+
const value = myVal || regions[0]?.refName
|
|
57
53
|
|
|
58
54
|
// use this instead of useState initializer because the useState initializer
|
|
59
55
|
// won't update in response to an observable
|
|
60
|
-
const option =
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
label: regions[0]?.refName,
|
|
64
|
-
})
|
|
65
|
-
|
|
66
|
-
const selectedRegion = option?.getLocation()
|
|
56
|
+
const option = new BaseResult({
|
|
57
|
+
label: value,
|
|
58
|
+
})
|
|
67
59
|
|
|
68
60
|
async function fetchResults(query: string, searchType?: SearchType) {
|
|
69
61
|
if (!textSearchManager) {
|
|
@@ -98,15 +90,26 @@ const ImportForm = observer(({ model }: { model: LGV }) => {
|
|
|
98
90
|
}
|
|
99
91
|
let trackId = option.getTrackId()
|
|
100
92
|
let location = input || option.getLocation() || ''
|
|
93
|
+
const [ref, rest] = location.split(':')
|
|
94
|
+
const allRefs = assembly?.allRefNames || []
|
|
101
95
|
try {
|
|
102
|
-
|
|
96
|
+
// instead of querying text-index, first:
|
|
97
|
+
// - check if input matches a refname directly
|
|
98
|
+
// - or looks like locstring
|
|
99
|
+
// then just navigate as if it were a locstring
|
|
100
|
+
if (
|
|
101
|
+
allRefs.includes(location) ||
|
|
102
|
+
(allRefs.includes(ref) &&
|
|
103
|
+
rest !== undefined &&
|
|
104
|
+
!Number.isNaN(parseInt(rest, 10)))
|
|
105
|
+
) {
|
|
103
106
|
model.navToLocString(location, selectedAsm)
|
|
104
107
|
} else {
|
|
105
108
|
const results = await fetchResults(input, 'exact')
|
|
106
|
-
if (results
|
|
109
|
+
if (results.length > 1) {
|
|
107
110
|
model.setSearchResults(results, input.toLowerCase())
|
|
108
111
|
return
|
|
109
|
-
} else if (results
|
|
112
|
+
} else if (results.length === 1) {
|
|
110
113
|
location = results[0].getLocation()
|
|
111
114
|
trackId = results[0].getTrackId()
|
|
112
115
|
}
|
|
@@ -130,7 +133,15 @@ const ImportForm = observer(({ model }: { model: LGV }) => {
|
|
|
130
133
|
<div className={classes.container}>
|
|
131
134
|
{err ? <ErrorMessage error={err} /> : null}
|
|
132
135
|
<Container className={classes.importFormContainer}>
|
|
133
|
-
<form
|
|
136
|
+
<form
|
|
137
|
+
onSubmit={event => {
|
|
138
|
+
event.preventDefault()
|
|
139
|
+
model.setError(undefined)
|
|
140
|
+
if (value) {
|
|
141
|
+
handleSelectedRegion(value)
|
|
142
|
+
}
|
|
143
|
+
}}
|
|
144
|
+
>
|
|
134
145
|
<Grid
|
|
135
146
|
container
|
|
136
147
|
spacing={1}
|
|
@@ -140,7 +151,7 @@ const ImportForm = observer(({ model }: { model: LGV }) => {
|
|
|
140
151
|
<Grid item>
|
|
141
152
|
<AssemblySelector
|
|
142
153
|
onChange={val => {
|
|
143
|
-
|
|
154
|
+
setImportError('')
|
|
144
155
|
setSelectedAsm(val)
|
|
145
156
|
}}
|
|
146
157
|
session={session}
|
|
@@ -152,15 +163,15 @@ const ImportForm = observer(({ model }: { model: LGV }) => {
|
|
|
152
163
|
{selectedAsm ? (
|
|
153
164
|
err ? (
|
|
154
165
|
<CloseIcon style={{ color: 'red' }} />
|
|
155
|
-
) :
|
|
166
|
+
) : value ? (
|
|
156
167
|
<RefNameAutocomplete
|
|
157
168
|
fetchResults={fetchResults}
|
|
158
169
|
model={model}
|
|
159
170
|
assemblyName={assemblyError ? undefined : selectedAsm}
|
|
160
|
-
value={
|
|
171
|
+
value={value}
|
|
161
172
|
// note: minWidth 270 accomodates full width of helperText
|
|
162
173
|
minWidth={270}
|
|
163
|
-
|
|
174
|
+
onChange={str => setValue(str)}
|
|
164
175
|
TextFieldProps={{
|
|
165
176
|
variant: 'outlined',
|
|
166
177
|
helperText:
|
|
@@ -181,21 +192,15 @@ const ImportForm = observer(({ model }: { model: LGV }) => {
|
|
|
181
192
|
<Grid item>
|
|
182
193
|
<Button
|
|
183
194
|
type="submit"
|
|
184
|
-
disabled={!
|
|
195
|
+
disabled={!value}
|
|
185
196
|
className={classes.button}
|
|
186
|
-
onClick={() => {
|
|
187
|
-
model.setError(undefined)
|
|
188
|
-
if (selectedRegion) {
|
|
189
|
-
handleSelectedRegion(selectedRegion)
|
|
190
|
-
}
|
|
191
|
-
}}
|
|
192
197
|
variant="contained"
|
|
193
198
|
color="primary"
|
|
194
199
|
>
|
|
195
200
|
Open
|
|
196
201
|
</Button>
|
|
197
202
|
<Button
|
|
198
|
-
disabled={!
|
|
203
|
+
disabled={!value}
|
|
199
204
|
className={classes.button}
|
|
200
205
|
onClick={() => {
|
|
201
206
|
model.setError(undefined)
|
|
@@ -66,17 +66,19 @@ const MyPopper = function (
|
|
|
66
66
|
|
|
67
67
|
function RefNameAutocomplete({
|
|
68
68
|
model,
|
|
69
|
-
showHelp = true,
|
|
70
69
|
onSelect,
|
|
71
70
|
assemblyName,
|
|
72
71
|
style,
|
|
73
72
|
fetchResults,
|
|
73
|
+
onChange,
|
|
74
74
|
value,
|
|
75
|
+
showHelp = true,
|
|
75
76
|
minWidth = 200,
|
|
76
77
|
TextFieldProps = {},
|
|
77
78
|
}: {
|
|
78
79
|
model: LinearGenomeViewModel
|
|
79
|
-
onSelect
|
|
80
|
+
onSelect?: (region: BaseResult) => void
|
|
81
|
+
onChange?: (val: string) => void
|
|
80
82
|
assemblyName?: string
|
|
81
83
|
value?: string
|
|
82
84
|
fetchResults: (query: string) => Promise<BaseResult[]>
|
|
@@ -171,7 +173,10 @@ function RefNameAutocomplete({
|
|
|
171
173
|
value={inputBoxVal}
|
|
172
174
|
loading={!loaded}
|
|
173
175
|
inputValue={inputValue}
|
|
174
|
-
onInputChange={(event, newInputValue) =>
|
|
176
|
+
onInputChange={(event, newInputValue) => {
|
|
177
|
+
setInputValue(newInputValue)
|
|
178
|
+
onChange?.(newInputValue)
|
|
179
|
+
}}
|
|
175
180
|
loadingText="loading results"
|
|
176
181
|
open={open}
|
|
177
182
|
onOpen={() => setOpen(true)}
|
|
@@ -190,9 +195,9 @@ function RefNameAutocomplete({
|
|
|
190
195
|
|
|
191
196
|
if (typeof selectedOption === 'string') {
|
|
192
197
|
// handles string inputs on keyPress enter
|
|
193
|
-
onSelect(new BaseResult({ label: selectedOption }))
|
|
198
|
+
onSelect?.(new BaseResult({ label: selectedOption }))
|
|
194
199
|
} else {
|
|
195
|
-
onSelect(selectedOption.result)
|
|
200
|
+
onSelect?.(selectedOption.result)
|
|
196
201
|
}
|
|
197
202
|
setInputValue(inputBoxVal)
|
|
198
203
|
}}
|
|
@@ -58,19 +58,35 @@ function SearchBox({
|
|
|
58
58
|
)
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
+
// gets a string as input, or use stored option results from previous query,
|
|
62
|
+
// then re-query and
|
|
63
|
+
// 1) if it has multiple results: pop a dialog
|
|
64
|
+
// 2) if it's a single result navigate to it
|
|
65
|
+
// 3) else assume it's a locstring and navigate to it
|
|
61
66
|
async function handleSelectedRegion(option: BaseResult) {
|
|
62
67
|
let trackId = option.getTrackId()
|
|
63
68
|
let location = option.getLocation()
|
|
64
69
|
const label = option.getLabel()
|
|
70
|
+
const [ref, rest] = location.split(':')
|
|
71
|
+
const allRefs = assembly?.allRefNames || []
|
|
65
72
|
try {
|
|
66
|
-
|
|
67
|
-
|
|
73
|
+
// instead of querying text-index, first:
|
|
74
|
+
// - check if input matches a refName directly
|
|
75
|
+
// - or looks like locString
|
|
76
|
+
// then just navigate as if it were a locString
|
|
77
|
+
if (
|
|
78
|
+
allRefs.includes(location) ||
|
|
79
|
+
(allRefs.includes(ref) &&
|
|
80
|
+
rest !== undefined &&
|
|
81
|
+
!Number.isNaN(parseInt(rest, 10)))
|
|
82
|
+
) {
|
|
83
|
+
model.navToLocString(location, assemblyName)
|
|
68
84
|
} else {
|
|
69
85
|
const results = await fetchResults(label, 'exact')
|
|
70
|
-
if (results
|
|
86
|
+
if (results.length > 1) {
|
|
71
87
|
model.setSearchResults(results, label.toLowerCase())
|
|
72
88
|
return
|
|
73
|
-
} else if (results
|
|
89
|
+
} else if (results.length === 1) {
|
|
74
90
|
location = results[0].getLocation()
|
|
75
91
|
trackId = results[0].getTrackId()
|
|
76
92
|
}
|
|
@@ -67,6 +67,7 @@ export interface BpOffset {
|
|
|
67
67
|
|
|
68
68
|
export interface ExportSvgOptions {
|
|
69
69
|
rasterizeLayers?: boolean
|
|
70
|
+
filename?: string
|
|
70
71
|
}
|
|
71
72
|
|
|
72
73
|
function calculateVisibleLocStrings(contentBlocks: BaseBlock[]) {
|
|
@@ -1330,7 +1331,7 @@ export function stateModelFactory(pluginManager: PluginManager) {
|
|
|
1330
1331
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1331
1332
|
const html = await renderToSvg(self as any, opts)
|
|
1332
1333
|
const blob = new Blob([html], { type: 'image/svg+xml' })
|
|
1333
|
-
saveAs(blob, 'image.svg')
|
|
1334
|
+
saveAs(blob, opts.filename || 'image.svg')
|
|
1334
1335
|
},
|
|
1335
1336
|
}))
|
|
1336
1337
|
.views(self => ({
|