@jbrowse/plugin-data-management 1.7.4 → 1.7.5
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/AddTrackWidget/components/AddTrackWidget.js +38 -2
- package/dist/AddTrackWidget/components/ConfirmTrack.js +154 -13
- package/dist/AddTrackWidget/model.d.ts +9 -0
- package/dist/AddTrackWidget/model.js +11 -1
- package/package.json +2 -2
- package/src/AddTrackWidget/components/AddTrackWidget.tsx +44 -2
- package/src/AddTrackWidget/components/ConfirmTrack.tsx +153 -2
- package/src/AddTrackWidget/model.ts +14 -1
|
@@ -27,6 +27,8 @@ var _configuration = require("@jbrowse/core/configuration");
|
|
|
27
27
|
|
|
28
28
|
var _mobxReact = require("mobx-react");
|
|
29
29
|
|
|
30
|
+
var _mobxStateTree = require("mobx-state-tree");
|
|
31
|
+
|
|
30
32
|
var _lab = require("@material-ui/lab");
|
|
31
33
|
|
|
32
34
|
var _ConfirmTrack = _interopRequireDefault(require("./ConfirmTrack"));
|
|
@@ -76,11 +78,19 @@ function AddTrackWidget(_ref) {
|
|
|
76
78
|
|
|
77
79
|
var classes = useStyles();
|
|
78
80
|
var session = (0, _util.getSession)(model);
|
|
81
|
+
|
|
82
|
+
var _getEnv = (0, _mobxStateTree.getEnv)(session),
|
|
83
|
+
pluginManager = _getEnv.pluginManager;
|
|
84
|
+
|
|
85
|
+
var rootModel = pluginManager.rootModel;
|
|
86
|
+
var jobsManager = rootModel.jobsManager;
|
|
79
87
|
var assembly = model.assembly,
|
|
80
88
|
trackAdapter = model.trackAdapter,
|
|
81
89
|
trackData = model.trackData,
|
|
82
90
|
trackName = model.trackName,
|
|
83
|
-
trackType = model.trackType
|
|
91
|
+
trackType = model.trackType,
|
|
92
|
+
textIndexTrack = model.textIndexTrack,
|
|
93
|
+
textIndexingConf = model.textIndexingConf;
|
|
84
94
|
|
|
85
95
|
var _useState3 = (0, _react.useState)(),
|
|
86
96
|
_useState4 = (0, _slicedToArray2.default)(_useState3, 2),
|
|
@@ -110,7 +120,7 @@ function AddTrackWidget(_ref) {
|
|
|
110
120
|
|
|
111
121
|
function _handleNext() {
|
|
112
122
|
_handleNext = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee() {
|
|
113
|
-
var trackId, assemblyInstance;
|
|
123
|
+
var trackId, assemblyInstance, textSearchingDefault, attr, indexName, indexingParams, newEntry;
|
|
114
124
|
return _regenerator.default.wrap(function _callee$(_context) {
|
|
115
125
|
while (1) {
|
|
116
126
|
switch (_context.prev = _context.next) {
|
|
@@ -138,9 +148,35 @@ function AddTrackWidget(_ref) {
|
|
|
138
148
|
sequenceAdapter: (0, _configuration.getConf)(assemblyInstance, ['sequence', 'adapter'])
|
|
139
149
|
})
|
|
140
150
|
});
|
|
151
|
+
textSearchingDefault = {
|
|
152
|
+
attributes: ['Name', 'ID'],
|
|
153
|
+
exclude: ['CDS', 'exon']
|
|
154
|
+
};
|
|
141
155
|
|
|
142
156
|
if (model.view) {
|
|
143
157
|
model.view.showTrack(trackId);
|
|
158
|
+
|
|
159
|
+
if (_util.isElectron) {
|
|
160
|
+
if (textIndexTrack && (0, _util.supportedIndexingAdapters)(trackAdapter.type)) {
|
|
161
|
+
attr = textIndexingConf || textSearchingDefault;
|
|
162
|
+
indexName = trackName + '-index';
|
|
163
|
+
indexingParams = _objectSpread(_objectSpread({}, attr), {}, {
|
|
164
|
+
assemblies: [assembly],
|
|
165
|
+
tracks: [trackId],
|
|
166
|
+
indexType: 'perTrack',
|
|
167
|
+
name: indexName,
|
|
168
|
+
timestamp: new Date().toISOString()
|
|
169
|
+
});
|
|
170
|
+
newEntry = {
|
|
171
|
+
indexingParams: indexingParams,
|
|
172
|
+
name: indexName,
|
|
173
|
+
cancelCallback: function cancelCallback() {
|
|
174
|
+
jobsManager.abortJob();
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
jobsManager.queueJob(newEntry);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
144
180
|
} else {
|
|
145
181
|
session.notify('Open a new view, or use the track selector in an existing view, to view this track', 'info');
|
|
146
182
|
}
|
|
@@ -2,12 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
4
|
|
|
5
|
+
var _typeof = require("@babel/runtime/helpers/typeof");
|
|
6
|
+
|
|
5
7
|
Object.defineProperty(exports, "__esModule", {
|
|
6
8
|
value: true
|
|
7
9
|
});
|
|
8
10
|
exports.default = void 0;
|
|
9
11
|
|
|
10
|
-
var
|
|
12
|
+
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
|
13
|
+
|
|
14
|
+
var _react = _interopRequireWildcard(require("react"));
|
|
11
15
|
|
|
12
16
|
var _configuration = require("@jbrowse/core/configuration");
|
|
13
17
|
|
|
@@ -15,16 +19,36 @@ var _util = require("@jbrowse/core/util");
|
|
|
15
19
|
|
|
16
20
|
var _core = require("@material-ui/core");
|
|
17
21
|
|
|
22
|
+
var _Delete = _interopRequireDefault(require("@material-ui/icons/Delete"));
|
|
23
|
+
|
|
24
|
+
var _Add = _interopRequireDefault(require("@material-ui/icons/Add"));
|
|
25
|
+
|
|
18
26
|
var _mobxReact = require("mobx-react");
|
|
19
27
|
|
|
20
28
|
var _mobxStateTree = require("mobx-state-tree");
|
|
21
29
|
|
|
22
30
|
var _tracks = require("@jbrowse/core/util/tracks");
|
|
23
31
|
|
|
32
|
+
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); }
|
|
33
|
+
|
|
34
|
+
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; }
|
|
35
|
+
|
|
36
|
+
// icons
|
|
24
37
|
var useStyles = (0, _core.makeStyles)(function (theme) {
|
|
25
38
|
return {
|
|
26
39
|
spacing: {
|
|
27
40
|
marginBottom: theme.spacing(3)
|
|
41
|
+
},
|
|
42
|
+
paper: {
|
|
43
|
+
display: 'flex',
|
|
44
|
+
flexDirection: 'column',
|
|
45
|
+
padding: theme.spacing(1)
|
|
46
|
+
},
|
|
47
|
+
spacer: {
|
|
48
|
+
height: theme.spacing(8)
|
|
49
|
+
},
|
|
50
|
+
card: {
|
|
51
|
+
marginTop: theme.spacing(1)
|
|
28
52
|
}
|
|
29
53
|
};
|
|
30
54
|
});
|
|
@@ -88,9 +112,108 @@ function getTrackTypes(pluginManager) {
|
|
|
88
112
|
return pluginManager.getElementTypesInGroup('track');
|
|
89
113
|
}
|
|
90
114
|
|
|
91
|
-
var
|
|
115
|
+
var TextIndexingConfig = (0, _mobxReact.observer)(function (_ref2) {
|
|
92
116
|
var model = _ref2.model;
|
|
93
117
|
var classes = useStyles();
|
|
118
|
+
|
|
119
|
+
var _useState = (0, _react.useState)(''),
|
|
120
|
+
_useState2 = (0, _slicedToArray2.default)(_useState, 2),
|
|
121
|
+
value1 = _useState2[0],
|
|
122
|
+
setValue1 = _useState2[1];
|
|
123
|
+
|
|
124
|
+
var _useState3 = (0, _react.useState)(''),
|
|
125
|
+
_useState4 = (0, _slicedToArray2.default)(_useState3, 2),
|
|
126
|
+
value2 = _useState4[0],
|
|
127
|
+
setValue2 = _useState4[1];
|
|
128
|
+
|
|
129
|
+
var _useState5 = (0, _react.useState)(['Name', 'ID']),
|
|
130
|
+
_useState6 = (0, _slicedToArray2.default)(_useState5, 2),
|
|
131
|
+
attributes = _useState6[0],
|
|
132
|
+
setAttributes = _useState6[1];
|
|
133
|
+
|
|
134
|
+
var _useState7 = (0, _react.useState)(['CDS', 'exon']),
|
|
135
|
+
_useState8 = (0, _slicedToArray2.default)(_useState7, 2),
|
|
136
|
+
exclude = _useState8[0],
|
|
137
|
+
setExclude = _useState8[1];
|
|
138
|
+
|
|
139
|
+
var sections = [{
|
|
140
|
+
label: 'Indexing attributes',
|
|
141
|
+
values: attributes
|
|
142
|
+
}, {
|
|
143
|
+
label: 'Feature types to exclude',
|
|
144
|
+
values: exclude
|
|
145
|
+
}];
|
|
146
|
+
(0, _react.useEffect)(function () {
|
|
147
|
+
model.setTextIndexingConf({
|
|
148
|
+
attributes: attributes,
|
|
149
|
+
exclude: exclude
|
|
150
|
+
});
|
|
151
|
+
}, [model, attributes, exclude]);
|
|
152
|
+
return /*#__PURE__*/_react.default.createElement(_core.Paper, {
|
|
153
|
+
className: classes.paper
|
|
154
|
+
}, /*#__PURE__*/_react.default.createElement(_core.InputLabel, null, "Indexing configuration"), sections.map(function (section, index) {
|
|
155
|
+
return /*#__PURE__*/_react.default.createElement(_core.Card, {
|
|
156
|
+
raised: true,
|
|
157
|
+
key: section.label,
|
|
158
|
+
className: classes.card
|
|
159
|
+
}, /*#__PURE__*/_react.default.createElement(_core.CardContent, null, /*#__PURE__*/_react.default.createElement(_core.InputLabel, null, section.label), /*#__PURE__*/_react.default.createElement(_core.List, {
|
|
160
|
+
disablePadding: true
|
|
161
|
+
}, section.values.map(function (val, idx) {
|
|
162
|
+
return /*#__PURE__*/_react.default.createElement(_core.ListItem, {
|
|
163
|
+
key: idx,
|
|
164
|
+
disableGutters: true
|
|
165
|
+
}, /*#__PURE__*/_react.default.createElement(_core.TextField, {
|
|
166
|
+
value: val,
|
|
167
|
+
InputProps: {
|
|
168
|
+
endAdornment: /*#__PURE__*/_react.default.createElement(_core.InputAdornment, {
|
|
169
|
+
position: "end"
|
|
170
|
+
}, /*#__PURE__*/_react.default.createElement(_core.IconButton, {
|
|
171
|
+
color: "secondary",
|
|
172
|
+
onClick: function onClick() {
|
|
173
|
+
var newAttr = section.values.filter(function (a, i) {
|
|
174
|
+
return i !== idx;
|
|
175
|
+
});
|
|
176
|
+
index === 0 ? setAttributes(newAttr) : setExclude(newAttr);
|
|
177
|
+
}
|
|
178
|
+
}, /*#__PURE__*/_react.default.createElement(_Delete.default, null)))
|
|
179
|
+
}
|
|
180
|
+
}));
|
|
181
|
+
}), /*#__PURE__*/_react.default.createElement(_core.ListItem, {
|
|
182
|
+
disableGutters: true
|
|
183
|
+
}, /*#__PURE__*/_react.default.createElement(_core.TextField, {
|
|
184
|
+
value: index === 0 ? value1 : value2,
|
|
185
|
+
placeholder: "add new",
|
|
186
|
+
onChange: function onChange(event) {
|
|
187
|
+
index === 0 ? setValue1(event.target.value) : setValue2(event.target.value);
|
|
188
|
+
},
|
|
189
|
+
InputProps: {
|
|
190
|
+
endAdornment: /*#__PURE__*/_react.default.createElement(_core.InputAdornment, {
|
|
191
|
+
position: "end"
|
|
192
|
+
}, /*#__PURE__*/_react.default.createElement(_core.IconButton, {
|
|
193
|
+
onClick: function onClick() {
|
|
194
|
+
if (index === 0) {
|
|
195
|
+
var newAttr = attributes;
|
|
196
|
+
newAttr.push(value1);
|
|
197
|
+
setAttributes(newAttr);
|
|
198
|
+
setValue1('');
|
|
199
|
+
} else {
|
|
200
|
+
var newFeat = exclude;
|
|
201
|
+
newFeat.push(value2);
|
|
202
|
+
setExclude(newFeat);
|
|
203
|
+
setValue2('');
|
|
204
|
+
}
|
|
205
|
+
},
|
|
206
|
+
disabled: index === 0 ? value1 === '' : value2 === '',
|
|
207
|
+
color: "secondary",
|
|
208
|
+
"data-testid": "stringArrayAdd-Feat"
|
|
209
|
+
}, /*#__PURE__*/_react.default.createElement(_Add.default, null)))
|
|
210
|
+
}
|
|
211
|
+
})))));
|
|
212
|
+
}));
|
|
213
|
+
});
|
|
214
|
+
var TrackAdapterSelector = (0, _mobxReact.observer)(function (_ref3) {
|
|
215
|
+
var model = _ref3.model;
|
|
216
|
+
var classes = useStyles();
|
|
94
217
|
var session = (0, _util.getSession)(model);
|
|
95
218
|
var trackAdapter = model.trackAdapter; // prettier-ignore
|
|
96
219
|
|
|
@@ -130,8 +253,8 @@ var TrackAdapterSelector = (0, _mobxReact.observer)(function (_ref2) {
|
|
|
130
253
|
})));
|
|
131
254
|
});
|
|
132
255
|
|
|
133
|
-
function UnknownAdapterPrompt(
|
|
134
|
-
var model =
|
|
256
|
+
function UnknownAdapterPrompt(_ref4) {
|
|
257
|
+
var model = _ref4.model;
|
|
135
258
|
var classes = useStyles();
|
|
136
259
|
return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_core.Typography, {
|
|
137
260
|
className: classes.spacing
|
|
@@ -148,8 +271,8 @@ function UnknownAdapterPrompt(_ref3) {
|
|
|
148
271
|
}));
|
|
149
272
|
}
|
|
150
273
|
|
|
151
|
-
var TrackTypeSelector = (0, _mobxReact.observer)(function (
|
|
152
|
-
var model =
|
|
274
|
+
var TrackTypeSelector = (0, _mobxReact.observer)(function (_ref5) {
|
|
275
|
+
var model = _ref5.model;
|
|
153
276
|
var classes = useStyles();
|
|
154
277
|
var session = (0, _util.getSession)(model);
|
|
155
278
|
var trackType = model.trackType;
|
|
@@ -170,16 +293,16 @@ var TrackTypeSelector = (0, _mobxReact.observer)(function (_ref4) {
|
|
|
170
293
|
'data-testid': 'trackTypeSelect'
|
|
171
294
|
}
|
|
172
295
|
}
|
|
173
|
-
}, trackTypes.map(function (
|
|
174
|
-
var name =
|
|
296
|
+
}, trackTypes.map(function (_ref6) {
|
|
297
|
+
var name = _ref6.name;
|
|
175
298
|
return /*#__PURE__*/_react.default.createElement(_core.MenuItem, {
|
|
176
299
|
key: name,
|
|
177
300
|
value: name
|
|
178
301
|
}, name);
|
|
179
302
|
}));
|
|
180
303
|
});
|
|
181
|
-
var TrackAssemblySelector = (0, _mobxReact.observer)(function (
|
|
182
|
-
var model =
|
|
304
|
+
var TrackAssemblySelector = (0, _mobxReact.observer)(function (_ref7) {
|
|
305
|
+
var model = _ref7.model;
|
|
183
306
|
var session = (0, _util.getSession)(model);
|
|
184
307
|
var assembly = model.assembly;
|
|
185
308
|
return /*#__PURE__*/_react.default.createElement(_core.TextField, {
|
|
@@ -207,9 +330,15 @@ var TrackAssemblySelector = (0, _mobxReact.observer)(function (_ref6) {
|
|
|
207
330
|
}));
|
|
208
331
|
});
|
|
209
332
|
|
|
210
|
-
function ConfirmTrack(
|
|
211
|
-
var model =
|
|
333
|
+
function ConfirmTrack(_ref8) {
|
|
334
|
+
var model = _ref8.model;
|
|
212
335
|
var classes = useStyles();
|
|
336
|
+
|
|
337
|
+
var _useState9 = (0, _react.useState)(true),
|
|
338
|
+
_useState10 = (0, _slicedToArray2.default)(_useState9, 2),
|
|
339
|
+
check = _useState10[0],
|
|
340
|
+
setCheck = _useState10[1];
|
|
341
|
+
|
|
213
342
|
var trackName = model.trackName,
|
|
214
343
|
trackAdapter = model.trackAdapter,
|
|
215
344
|
trackType = model.trackType,
|
|
@@ -244,6 +373,7 @@ function ConfirmTrack(_ref7) {
|
|
|
244
373
|
return /*#__PURE__*/_react.default.createElement(_core.Typography, null, "Could not recognize this data type.");
|
|
245
374
|
}
|
|
246
375
|
|
|
376
|
+
var supportedForIndexing = (0, _util.supportedIndexingAdapters)(trackAdapter === null || trackAdapter === void 0 ? void 0 : trackAdapter.type);
|
|
247
377
|
return /*#__PURE__*/_react.default.createElement("div", null, trackAdapter ? /*#__PURE__*/_react.default.createElement(StatusMessage, {
|
|
248
378
|
trackAdapter: trackAdapter,
|
|
249
379
|
trackType: trackType
|
|
@@ -269,7 +399,18 @@ function ConfirmTrack(_ref7) {
|
|
|
269
399
|
model: model
|
|
270
400
|
}), /*#__PURE__*/_react.default.createElement(TrackAssemblySelector, {
|
|
271
401
|
model: model
|
|
272
|
-
})
|
|
402
|
+
}), _util.isElectron && supportedForIndexing && /*#__PURE__*/_react.default.createElement(_core.FormControl, null, /*#__PURE__*/_react.default.createElement(_core.FormControlLabel, {
|
|
403
|
+
label: 'Index track for text searching?',
|
|
404
|
+
control: /*#__PURE__*/_react.default.createElement(_core.Checkbox, {
|
|
405
|
+
checked: check,
|
|
406
|
+
onChange: function onChange(e) {
|
|
407
|
+
setCheck(e.target.checked);
|
|
408
|
+
model.setTextIndexTrack(e.target.checked);
|
|
409
|
+
}
|
|
410
|
+
})
|
|
411
|
+
})), _util.isElectron && check && supportedForIndexing ? /*#__PURE__*/_react.default.createElement(TextIndexingConfig, {
|
|
412
|
+
model: model
|
|
413
|
+
}) : null);
|
|
273
414
|
}
|
|
274
415
|
|
|
275
416
|
var _default = (0, _mobxReact.observer)(ConfirmTrack);
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { Instance } from 'mobx-state-tree';
|
|
2
2
|
import PluginManager from '@jbrowse/core/PluginManager';
|
|
3
3
|
import { FileLocation } from '@jbrowse/core/util/types';
|
|
4
|
+
interface IndexingAttr {
|
|
5
|
+
attributes: string[];
|
|
6
|
+
exclude: string[];
|
|
7
|
+
}
|
|
4
8
|
export default function f(pluginManager: PluginManager): import("mobx-state-tree").IModelType<{
|
|
5
9
|
id: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<string>, [undefined]>;
|
|
6
10
|
type: import("mobx-state-tree").ISimpleType<"AddTrackWidget">;
|
|
@@ -13,9 +17,13 @@ export default function f(pluginManager: PluginManager): import("mobx-state-tree
|
|
|
13
17
|
altTrackName: string;
|
|
14
18
|
altTrackType: string;
|
|
15
19
|
adapterHint: string;
|
|
20
|
+
textIndexTrack: boolean;
|
|
21
|
+
textIndexingConf: IndexingAttr | undefined;
|
|
16
22
|
} & {
|
|
17
23
|
setAdapterHint(obj: string): void;
|
|
18
24
|
setTrackSource(str: string): void;
|
|
25
|
+
setTextIndexingConf(conf: IndexingAttr): void;
|
|
26
|
+
setTextIndexTrack(flag: boolean): void;
|
|
19
27
|
setTrackData(obj: FileLocation): void;
|
|
20
28
|
setIndexTrackData(obj: FileLocation): void;
|
|
21
29
|
setAssembly(str: string): void;
|
|
@@ -40,3 +48,4 @@ export default function f(pluginManager: PluginManager): import("mobx-state-tree
|
|
|
40
48
|
}, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>;
|
|
41
49
|
export declare type AddTrackStateModel = ReturnType<typeof f>;
|
|
42
50
|
export declare type AddTrackModel = Instance<AddTrackStateModel>;
|
|
51
|
+
export {};
|
|
@@ -36,7 +36,9 @@ function f(pluginManager) {
|
|
|
36
36
|
altAssemblyName: '',
|
|
37
37
|
altTrackName: '',
|
|
38
38
|
altTrackType: '',
|
|
39
|
-
adapterHint: ''
|
|
39
|
+
adapterHint: '',
|
|
40
|
+
textIndexTrack: true,
|
|
41
|
+
textIndexingConf: undefined
|
|
40
42
|
};
|
|
41
43
|
}).actions(function (self) {
|
|
42
44
|
return {
|
|
@@ -46,6 +48,12 @@ function f(pluginManager) {
|
|
|
46
48
|
setTrackSource: function setTrackSource(str) {
|
|
47
49
|
self.trackSource = str;
|
|
48
50
|
},
|
|
51
|
+
setTextIndexingConf: function setTextIndexingConf(conf) {
|
|
52
|
+
self.textIndexingConf = conf;
|
|
53
|
+
},
|
|
54
|
+
setTextIndexTrack: function setTextIndexTrack(flag) {
|
|
55
|
+
self.textIndexTrack = flag;
|
|
56
|
+
},
|
|
49
57
|
setTrackData: function setTrackData(obj) {
|
|
50
58
|
self.trackData = obj;
|
|
51
59
|
},
|
|
@@ -69,6 +77,8 @@ function f(pluginManager) {
|
|
|
69
77
|
self.adapterHint = '';
|
|
70
78
|
self.indexTrackData = undefined;
|
|
71
79
|
self.trackData = undefined;
|
|
80
|
+
self.textIndexingConf = undefined;
|
|
81
|
+
self.textIndexTrack = false;
|
|
72
82
|
}
|
|
73
83
|
};
|
|
74
84
|
}).views(function (self) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jbrowse/plugin-data-management",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.5",
|
|
4
4
|
"description": "JBrowse 2 linear genome view",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"jbrowse",
|
|
@@ -54,5 +54,5 @@
|
|
|
54
54
|
"publishConfig": {
|
|
55
55
|
"access": "public"
|
|
56
56
|
},
|
|
57
|
-
"gitHead": "
|
|
57
|
+
"gitHead": "2c3a1f0c95a47b24eba790eaeb49274caf297aeb"
|
|
58
58
|
}
|
|
@@ -8,9 +8,14 @@ import {
|
|
|
8
8
|
Typography,
|
|
9
9
|
makeStyles,
|
|
10
10
|
} from '@material-ui/core'
|
|
11
|
-
import {
|
|
11
|
+
import {
|
|
12
|
+
getSession,
|
|
13
|
+
isElectron,
|
|
14
|
+
supportedIndexingAdapters,
|
|
15
|
+
} from '@jbrowse/core/util'
|
|
12
16
|
import { getConf } from '@jbrowse/core/configuration'
|
|
13
17
|
import { observer } from 'mobx-react'
|
|
18
|
+
import { getEnv } from 'mobx-state-tree'
|
|
14
19
|
import { Alert } from '@material-ui/lab'
|
|
15
20
|
|
|
16
21
|
// locals
|
|
@@ -46,7 +51,18 @@ function AddTrackWidget({ model }: { model: AddTrackModel }) {
|
|
|
46
51
|
const [activeStep, setActiveStep] = useState(0)
|
|
47
52
|
const classes = useStyles()
|
|
48
53
|
const session = getSession(model)
|
|
49
|
-
const {
|
|
54
|
+
const { pluginManager } = getEnv(session)
|
|
55
|
+
const { rootModel } = pluginManager
|
|
56
|
+
const { jobsManager } = rootModel
|
|
57
|
+
const {
|
|
58
|
+
assembly,
|
|
59
|
+
trackAdapter,
|
|
60
|
+
trackData,
|
|
61
|
+
trackName,
|
|
62
|
+
trackType,
|
|
63
|
+
textIndexTrack,
|
|
64
|
+
textIndexingConf,
|
|
65
|
+
} = model
|
|
50
66
|
const [trackErrorMessage, setTrackErrorMessage] = useState<string>()
|
|
51
67
|
|
|
52
68
|
function getStepContent(step: number) {
|
|
@@ -86,8 +102,34 @@ function AddTrackWidget({ model }: { model: AddTrackModel }) {
|
|
|
86
102
|
sequenceAdapter: getConf(assemblyInstance, ['sequence', 'adapter']),
|
|
87
103
|
},
|
|
88
104
|
})
|
|
105
|
+
const textSearchingDefault = {
|
|
106
|
+
attributes: ['Name', 'ID'],
|
|
107
|
+
exclude: ['CDS', 'exon'],
|
|
108
|
+
}
|
|
89
109
|
if (model.view) {
|
|
90
110
|
model.view.showTrack(trackId)
|
|
111
|
+
if (isElectron) {
|
|
112
|
+
if (textIndexTrack && supportedIndexingAdapters(trackAdapter.type)) {
|
|
113
|
+
const attr = textIndexingConf || textSearchingDefault
|
|
114
|
+
const indexName = trackName + '-index'
|
|
115
|
+
const indexingParams = {
|
|
116
|
+
...attr,
|
|
117
|
+
assemblies: [assembly],
|
|
118
|
+
tracks: [trackId],
|
|
119
|
+
indexType: 'perTrack',
|
|
120
|
+
name: indexName,
|
|
121
|
+
timestamp: new Date().toISOString(),
|
|
122
|
+
}
|
|
123
|
+
const newEntry = {
|
|
124
|
+
indexingParams: indexingParams,
|
|
125
|
+
name: indexName,
|
|
126
|
+
cancelCallback: () => {
|
|
127
|
+
jobsManager.abortJob()
|
|
128
|
+
},
|
|
129
|
+
}
|
|
130
|
+
jobsManager.queueJob(newEntry)
|
|
131
|
+
}
|
|
132
|
+
}
|
|
91
133
|
} else {
|
|
92
134
|
session.notify(
|
|
93
135
|
'Open a new view, or use the track selector in an existing view, to view this track',
|
|
@@ -1,14 +1,34 @@
|
|
|
1
|
-
import React from 'react'
|
|
1
|
+
import React, { useEffect, useState } from 'react'
|
|
2
2
|
import { readConfObject } from '@jbrowse/core/configuration'
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
supportedIndexingAdapters,
|
|
5
|
+
getSession,
|
|
6
|
+
isElectron,
|
|
7
|
+
} from '@jbrowse/core/util'
|
|
4
8
|
import {
|
|
5
9
|
Link,
|
|
6
10
|
MenuItem,
|
|
7
11
|
TextField,
|
|
8
12
|
ListSubheader,
|
|
9
13
|
Typography,
|
|
14
|
+
FormControl,
|
|
15
|
+
FormControlLabel,
|
|
16
|
+
Checkbox,
|
|
17
|
+
Paper,
|
|
18
|
+
Card,
|
|
19
|
+
List,
|
|
20
|
+
ListItem,
|
|
21
|
+
CardContent,
|
|
22
|
+
IconButton,
|
|
23
|
+
InputLabel,
|
|
24
|
+
InputAdornment,
|
|
10
25
|
makeStyles,
|
|
11
26
|
} from '@material-ui/core'
|
|
27
|
+
|
|
28
|
+
// icons
|
|
29
|
+
import DeleteIcon from '@material-ui/icons/Delete'
|
|
30
|
+
import AddIcon from '@material-ui/icons/Add'
|
|
31
|
+
// other
|
|
12
32
|
import PluginManager from '@jbrowse/core/PluginManager'
|
|
13
33
|
import { observer } from 'mobx-react'
|
|
14
34
|
import { getEnv } from 'mobx-state-tree'
|
|
@@ -22,6 +42,17 @@ const useStyles = makeStyles(theme => ({
|
|
|
22
42
|
spacing: {
|
|
23
43
|
marginBottom: theme.spacing(3),
|
|
24
44
|
},
|
|
45
|
+
paper: {
|
|
46
|
+
display: 'flex',
|
|
47
|
+
flexDirection: 'column',
|
|
48
|
+
padding: theme.spacing(1),
|
|
49
|
+
},
|
|
50
|
+
spacer: {
|
|
51
|
+
height: theme.spacing(8),
|
|
52
|
+
},
|
|
53
|
+
card: {
|
|
54
|
+
marginTop: theme.spacing(1),
|
|
55
|
+
},
|
|
25
56
|
}))
|
|
26
57
|
|
|
27
58
|
function StatusMessage({
|
|
@@ -98,6 +129,105 @@ function getTrackTypes(pluginManager: PluginManager) {
|
|
|
98
129
|
return pluginManager.getElementTypesInGroup('track') as { name: string }[]
|
|
99
130
|
}
|
|
100
131
|
|
|
132
|
+
const TextIndexingConfig = observer(({ model }: { model: AddTrackModel }) => {
|
|
133
|
+
const classes = useStyles()
|
|
134
|
+
const [value1, setValue1] = useState('')
|
|
135
|
+
const [value2, setValue2] = useState('')
|
|
136
|
+
const [attributes, setAttributes] = useState(['Name', 'ID'])
|
|
137
|
+
const [exclude, setExclude] = useState(['CDS', 'exon'])
|
|
138
|
+
const sections = [
|
|
139
|
+
{
|
|
140
|
+
label: 'Indexing attributes',
|
|
141
|
+
values: attributes,
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
label: 'Feature types to exclude',
|
|
145
|
+
values: exclude,
|
|
146
|
+
},
|
|
147
|
+
]
|
|
148
|
+
useEffect(() => {
|
|
149
|
+
model.setTextIndexingConf({ attributes, exclude })
|
|
150
|
+
}, [model, attributes, exclude])
|
|
151
|
+
|
|
152
|
+
return (
|
|
153
|
+
<Paper className={classes.paper}>
|
|
154
|
+
<InputLabel>Indexing configuration</InputLabel>
|
|
155
|
+
{sections.map((section, index) => (
|
|
156
|
+
<Card raised key={section.label} className={classes.card}>
|
|
157
|
+
<CardContent>
|
|
158
|
+
<InputLabel>{section.label}</InputLabel>
|
|
159
|
+
<List disablePadding>
|
|
160
|
+
{section.values.map((val: string, idx: number) => (
|
|
161
|
+
<ListItem key={idx} disableGutters>
|
|
162
|
+
<TextField
|
|
163
|
+
value={val}
|
|
164
|
+
InputProps={{
|
|
165
|
+
endAdornment: (
|
|
166
|
+
<InputAdornment position="end">
|
|
167
|
+
<IconButton
|
|
168
|
+
color="secondary"
|
|
169
|
+
onClick={() => {
|
|
170
|
+
const newAttr = section.values.filter((a, i) => {
|
|
171
|
+
return i !== idx
|
|
172
|
+
})
|
|
173
|
+
index === 0
|
|
174
|
+
? setAttributes(newAttr)
|
|
175
|
+
: setExclude(newAttr)
|
|
176
|
+
}}
|
|
177
|
+
>
|
|
178
|
+
<DeleteIcon />
|
|
179
|
+
</IconButton>
|
|
180
|
+
</InputAdornment>
|
|
181
|
+
),
|
|
182
|
+
}}
|
|
183
|
+
/>
|
|
184
|
+
</ListItem>
|
|
185
|
+
))}
|
|
186
|
+
<ListItem disableGutters>
|
|
187
|
+
<TextField
|
|
188
|
+
value={index === 0 ? value1 : value2}
|
|
189
|
+
placeholder="add new"
|
|
190
|
+
onChange={event => {
|
|
191
|
+
index === 0
|
|
192
|
+
? setValue1(event.target.value)
|
|
193
|
+
: setValue2(event.target.value)
|
|
194
|
+
}}
|
|
195
|
+
InputProps={{
|
|
196
|
+
endAdornment: (
|
|
197
|
+
<InputAdornment position="end">
|
|
198
|
+
<IconButton
|
|
199
|
+
onClick={() => {
|
|
200
|
+
if (index === 0) {
|
|
201
|
+
const newAttr: string[] = attributes
|
|
202
|
+
newAttr.push(value1)
|
|
203
|
+
setAttributes(newAttr)
|
|
204
|
+
setValue1('')
|
|
205
|
+
} else {
|
|
206
|
+
const newFeat: string[] = exclude
|
|
207
|
+
newFeat.push(value2)
|
|
208
|
+
setExclude(newFeat)
|
|
209
|
+
setValue2('')
|
|
210
|
+
}
|
|
211
|
+
}}
|
|
212
|
+
disabled={index === 0 ? value1 === '' : value2 === ''}
|
|
213
|
+
color="secondary"
|
|
214
|
+
data-testid={`stringArrayAdd-Feat`}
|
|
215
|
+
>
|
|
216
|
+
<AddIcon />
|
|
217
|
+
</IconButton>
|
|
218
|
+
</InputAdornment>
|
|
219
|
+
),
|
|
220
|
+
}}
|
|
221
|
+
/>
|
|
222
|
+
</ListItem>
|
|
223
|
+
</List>
|
|
224
|
+
</CardContent>
|
|
225
|
+
</Card>
|
|
226
|
+
))}
|
|
227
|
+
</Paper>
|
|
228
|
+
)
|
|
229
|
+
})
|
|
230
|
+
|
|
101
231
|
const TrackAdapterSelector = observer(({ model }: { model: AddTrackModel }) => {
|
|
102
232
|
const classes = useStyles()
|
|
103
233
|
const session = getSession(model)
|
|
@@ -233,6 +363,7 @@ const TrackAssemblySelector = observer(
|
|
|
233
363
|
|
|
234
364
|
function ConfirmTrack({ model }: { model: AddTrackModel }) {
|
|
235
365
|
const classes = useStyles()
|
|
366
|
+
const [check, setCheck] = useState(true)
|
|
236
367
|
const { trackName, trackAdapter, trackType, warningMessage, adapterHint } =
|
|
237
368
|
model
|
|
238
369
|
|
|
@@ -273,6 +404,7 @@ function ConfirmTrack({ model }: { model: AddTrackModel }) {
|
|
|
273
404
|
return <Typography>Could not recognize this data type.</Typography>
|
|
274
405
|
}
|
|
275
406
|
|
|
407
|
+
const supportedForIndexing = supportedIndexingAdapters(trackAdapter?.type)
|
|
276
408
|
return (
|
|
277
409
|
<div>
|
|
278
410
|
{trackAdapter ? (
|
|
@@ -293,6 +425,25 @@ function ConfirmTrack({ model }: { model: AddTrackModel }) {
|
|
|
293
425
|
<TrackAdapterSelector model={model} />
|
|
294
426
|
<TrackTypeSelector model={model} />
|
|
295
427
|
<TrackAssemblySelector model={model} />
|
|
428
|
+
{isElectron && supportedForIndexing && (
|
|
429
|
+
<FormControl>
|
|
430
|
+
<FormControlLabel
|
|
431
|
+
label={'Index track for text searching?'}
|
|
432
|
+
control={
|
|
433
|
+
<Checkbox
|
|
434
|
+
checked={check}
|
|
435
|
+
onChange={e => {
|
|
436
|
+
setCheck(e.target.checked)
|
|
437
|
+
model.setTextIndexTrack(e.target.checked)
|
|
438
|
+
}}
|
|
439
|
+
/>
|
|
440
|
+
}
|
|
441
|
+
/>
|
|
442
|
+
</FormControl>
|
|
443
|
+
)}
|
|
444
|
+
{isElectron && check && supportedForIndexing ? (
|
|
445
|
+
<TextIndexingConfig model={model} />
|
|
446
|
+
) : null}
|
|
296
447
|
</div>
|
|
297
448
|
)
|
|
298
449
|
}
|
|
@@ -17,7 +17,10 @@ function isAbsoluteUrl(url = '') {
|
|
|
17
17
|
return url.startsWith('/')
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
|
-
|
|
20
|
+
interface IndexingAttr {
|
|
21
|
+
attributes: string[]
|
|
22
|
+
exclude: string[]
|
|
23
|
+
}
|
|
21
24
|
export default function f(pluginManager: PluginManager) {
|
|
22
25
|
return types
|
|
23
26
|
.model('AddTrackModel', {
|
|
@@ -38,6 +41,8 @@ export default function f(pluginManager: PluginManager) {
|
|
|
38
41
|
altTrackType: '',
|
|
39
42
|
|
|
40
43
|
adapterHint: '',
|
|
44
|
+
textIndexTrack: true,
|
|
45
|
+
textIndexingConf: undefined as IndexingAttr | undefined,
|
|
41
46
|
}))
|
|
42
47
|
.actions(self => ({
|
|
43
48
|
setAdapterHint(obj: string) {
|
|
@@ -46,6 +51,12 @@ export default function f(pluginManager: PluginManager) {
|
|
|
46
51
|
setTrackSource(str: string) {
|
|
47
52
|
self.trackSource = str
|
|
48
53
|
},
|
|
54
|
+
setTextIndexingConf(conf: IndexingAttr) {
|
|
55
|
+
self.textIndexingConf = conf
|
|
56
|
+
},
|
|
57
|
+
setTextIndexTrack(flag: boolean) {
|
|
58
|
+
self.textIndexTrack = flag
|
|
59
|
+
},
|
|
49
60
|
setTrackData(obj: FileLocation) {
|
|
50
61
|
self.trackData = obj
|
|
51
62
|
},
|
|
@@ -70,6 +81,8 @@ export default function f(pluginManager: PluginManager) {
|
|
|
70
81
|
self.adapterHint = ''
|
|
71
82
|
self.indexTrackData = undefined
|
|
72
83
|
self.trackData = undefined
|
|
84
|
+
self.textIndexingConf = undefined
|
|
85
|
+
self.textIndexTrack = false
|
|
73
86
|
},
|
|
74
87
|
}))
|
|
75
88
|
.views(self => ({
|