@jbrowse/plugin-config 4.3.0 → 5.0.0-beta.10
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/esm/ConfigurationEditorWidget/components/AddNewField.d.ts +6 -0
- package/esm/ConfigurationEditorWidget/components/AddNewField.js +29 -0
- package/esm/ConfigurationEditorWidget/components/BooleanEditor.d.ts +3 -2
- package/esm/ConfigurationEditorWidget/components/BooleanEditor.js +6 -4
- package/esm/ConfigurationEditorWidget/components/CallbackEditor.d.ts +4 -2
- package/esm/ConfigurationEditorWidget/components/CallbackEditor.js +24 -42
- package/esm/ConfigurationEditorWidget/components/ColorEditor.d.ts +5 -12
- package/esm/ConfigurationEditorWidget/components/ColorEditor.js +47 -22
- package/esm/ConfigurationEditorWidget/components/ConfigurationEditor.d.ts +2 -3
- package/esm/ConfigurationEditorWidget/components/ConfigurationEditor.js +168 -29
- package/esm/ConfigurationEditorWidget/components/ConfigurationTextField.d.ts +1 -1
- package/esm/ConfigurationEditorWidget/components/ConfigurationTextField.js +10 -2
- package/esm/ConfigurationEditorWidget/components/EntryListEditor.d.ts +17 -0
- package/esm/ConfigurationEditorWidget/components/EntryListEditor.js +35 -0
- package/esm/ConfigurationEditorWidget/components/HeadingComponent.d.ts +1 -1
- package/esm/ConfigurationEditorWidget/components/IntegerEditor.d.ts +10 -0
- package/esm/ConfigurationEditorWidget/components/IntegerEditor.js +9 -0
- package/esm/ConfigurationEditorWidget/components/JsonEditor.d.ts +2 -1
- package/esm/ConfigurationEditorWidget/components/JsonEditor.js +24 -41
- package/esm/ConfigurationEditorWidget/components/MapEntryCard.d.ts +8 -0
- package/esm/ConfigurationEditorWidget/components/MapEntryCard.js +23 -0
- package/esm/ConfigurationEditorWidget/components/MapSlotEditor.d.ts +8 -0
- package/esm/ConfigurationEditorWidget/components/MapSlotEditor.js +18 -0
- package/esm/ConfigurationEditorWidget/components/NumberEditor.d.ts +5 -4
- package/esm/ConfigurationEditorWidget/components/NumberEditor.js +15 -15
- package/esm/ConfigurationEditorWidget/components/NumberMapEditor.d.ts +4 -4
- package/esm/ConfigurationEditorWidget/components/NumberMapEditor.js +7 -31
- package/esm/ConfigurationEditorWidget/components/SlotEditor.d.ts +4 -5
- package/esm/ConfigurationEditorWidget/components/SlotEditor.js +88 -49
- package/esm/ConfigurationEditorWidget/components/StringArrayEditor.d.ts +16 -10
- package/esm/ConfigurationEditorWidget/components/StringArrayEditor.js +22 -25
- package/esm/ConfigurationEditorWidget/components/StringArrayMapEditor.d.ts +3 -6
- package/esm/ConfigurationEditorWidget/components/StringArrayMapEditor.js +14 -39
- package/esm/ConfigurationEditorWidget/components/StringMapEditor.d.ts +10 -0
- package/esm/ConfigurationEditorWidget/components/StringMapEditor.js +13 -0
- package/esm/ConfigurationEditorWidget/components/TypeSelector.d.ts +2 -2
- package/esm/ConfigurationEditorWidget/components/TypeSelector.js +2 -2
- package/esm/ConfigurationEditorWidget/components/singularSlotName.d.ts +13 -0
- package/esm/ConfigurationEditorWidget/components/singularSlotName.js +23 -0
- package/esm/ConfigurationEditorWidget/components/useSlotEditorStyles.d.ts +2 -2
- package/esm/ConfigurationEditorWidget/components/useSlotEditorStyles.js +6 -1
- package/esm/ConfigurationEditorWidget/index.js +4 -4
- package/esm/ConfigurationEditorWidget/model.d.ts +8 -1
- package/esm/ConfigurationEditorWidget/model.js +40 -1
- package/esm/FromConfigAdapter/FromConfigAdapter.d.ts +6 -1
- package/esm/FromConfigAdapter/FromConfigAdapter.js +31 -1
- package/esm/FromConfigAdapter/configSchema.d.ts +32 -4
- package/esm/FromConfigAdapter/configSchema.js +34 -2
- package/esm/FromConfigAdapter/index.js +2 -2
- package/esm/FromConfigRegionsAdapter/FromConfigRegionsAdapter.d.ts +8 -0
- package/esm/FromConfigRegionsAdapter/FromConfigRegionsAdapter.js +10 -25
- package/esm/FromConfigRegionsAdapter/configSchema.d.ts +38 -4
- package/esm/FromConfigRegionsAdapter/configSchema.js +39 -2
- package/esm/FromConfigRegionsAdapter/index.js +2 -2
- package/esm/FromConfigSequenceAdapter/FromConfigSequenceAdapter.d.ts +15 -2
- package/esm/FromConfigSequenceAdapter/FromConfigSequenceAdapter.js +32 -40
- package/esm/FromConfigSequenceAdapter/configSchema.d.ts +37 -4
- package/esm/FromConfigSequenceAdapter/configSchema.js +38 -2
- package/esm/FromConfigSequenceAdapter/index.js +2 -2
- package/esm/NcbiSequenceReportAliasAdapter/NcbiSequenceReportAliasAdapter.d.ts +5 -4
- package/esm/NcbiSequenceReportAliasAdapter/NcbiSequenceReportAliasAdapter.js +28 -24
- package/esm/NcbiSequenceReportAliasAdapter/configSchema.d.ts +69 -10
- package/esm/NcbiSequenceReportAliasAdapter/configSchema.js +82 -18
- package/esm/NcbiSequenceReportAliasAdapter/index.js +3 -2
- package/esm/RefNameAliasAdapter/RefNameAliasAdapter.d.ts +4 -3
- package/esm/RefNameAliasAdapter/RefNameAliasAdapter.js +22 -28
- package/esm/RefNameAliasAdapter/configSchema.d.ts +70 -12
- package/esm/RefNameAliasAdapter/configSchema.js +89 -18
- package/esm/RefNameAliasAdapter/index.js +3 -2
- package/esm/aliasUtils.d.ts +4 -0
- package/esm/aliasUtils.js +19 -0
- package/esm/index.d.ts +2 -2
- package/esm/index.js +7 -7
- package/package.json +11 -15
|
@@ -1,43 +1,18 @@
|
|
|
1
|
-
import { jsx as _jsx
|
|
2
|
-
import { useState } from 'react';
|
|
3
|
-
import { makeStyles } from '@jbrowse/core/util/tss-react';
|
|
4
|
-
import AddIcon from '@mui/icons-material/Add';
|
|
5
|
-
import DeleteIcon from '@mui/icons-material/Delete';
|
|
6
|
-
import { Card, CardContent, CardHeader, FormHelperText, IconButton, InputAdornment, InputLabel, TextField, } from '@mui/material';
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
7
2
|
import { observer } from 'mobx-react';
|
|
8
|
-
import
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
marginTop: theme.spacing(1),
|
|
12
|
-
},
|
|
13
|
-
}));
|
|
3
|
+
import MapSlotEditor from './MapSlotEditor.js';
|
|
4
|
+
import StringArrayEditor from './StringArrayEditor.js';
|
|
5
|
+
/** #slotEditor one card per key, each holding that key's "todolist" of strings */
|
|
14
6
|
const StringArrayMapEditor = observer(function StringArrayMapEditor({ slot, }) {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
},
|
|
26
|
-
removeAtIndex: (idx) => {
|
|
27
|
-
slot.removeAtKeyIndex(key, idx);
|
|
28
|
-
},
|
|
29
|
-
add: (val) => {
|
|
30
|
-
slot.addToKey(key, val);
|
|
31
|
-
},
|
|
32
|
-
} }) })] }, key))), _jsx(Card, { raised: true, className: classes.card, children: _jsx(CardHeader, { disableTypography: true, title: _jsx(TextField, { fullWidth: true, value: value, placeholder: "add new", onChange: event => {
|
|
33
|
-
setValue(event.target.value);
|
|
34
|
-
}, slotProps: {
|
|
35
|
-
input: {
|
|
36
|
-
endAdornment: (_jsx(InputAdornment, { position: "end", children: _jsx(IconButton, { disabled: value === '', onClick: () => {
|
|
37
|
-
slot.add(value, []);
|
|
38
|
-
setValue('');
|
|
39
|
-
}, children: _jsx(AddIcon, {}) }) })),
|
|
40
|
-
},
|
|
41
|
-
} }) }) }), _jsx(FormHelperText, { children: slot.description })] }));
|
|
7
|
+
return (_jsx(MapSlotEditor, { name: slot.name, description: slot.description,
|
|
8
|
+
// deep copy so per-entry edits never reuse the live MST array nodes
|
|
9
|
+
entries: [...slot.value].map(([k, v]) => [k, [...v]]), emptyValue: [], setMap: val => {
|
|
10
|
+
slot.set(val);
|
|
11
|
+
}, renderValue: (val, set, key) => (_jsx(StringArrayEditor, { slot: {
|
|
12
|
+
name: '',
|
|
13
|
+
value: val,
|
|
14
|
+
description: `Values associated with entry ${key}`,
|
|
15
|
+
set,
|
|
16
|
+
} })) }));
|
|
42
17
|
});
|
|
43
18
|
export default StringArrayMapEditor;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** #slotEditor one card per key, each holding that key's text field */
|
|
2
|
+
declare const StringMapEditor: ({ slot, }: {
|
|
3
|
+
slot: {
|
|
4
|
+
name: string;
|
|
5
|
+
value: Map<string, string>;
|
|
6
|
+
set: (val: Record<string, string>) => void;
|
|
7
|
+
description: string;
|
|
8
|
+
};
|
|
9
|
+
}) => import("react").JSX.Element;
|
|
10
|
+
export default StringMapEditor;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { TextField } from '@mui/material';
|
|
3
|
+
import { observer } from 'mobx-react';
|
|
4
|
+
import MapSlotEditor from './MapSlotEditor.js';
|
|
5
|
+
/** #slotEditor one card per key, each holding that key's text field */
|
|
6
|
+
const StringMapEditor = observer(function StringMapEditor({ slot, }) {
|
|
7
|
+
return (_jsx(MapSlotEditor, { name: slot.name, description: slot.description, entries: [...slot.value], emptyValue: "", setMap: val => {
|
|
8
|
+
slot.set(val);
|
|
9
|
+
}, renderValue: (val, set) => (_jsx(TextField, { fullWidth: true, value: val, onChange: evt => {
|
|
10
|
+
set(evt.target.value);
|
|
11
|
+
} })) }));
|
|
12
|
+
});
|
|
13
|
+
export default StringMapEditor;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { AnyConfigurationModel } from '@jbrowse/core/configuration';
|
|
2
2
|
declare const TypeSelector: ({ typeNameChoices, slot, slotName, onChange, }: {
|
|
3
3
|
typeNameChoices: string[];
|
|
4
|
-
slot: AnyConfigurationModel;
|
|
4
|
+
slot: AnyConfigurationModel | undefined;
|
|
5
5
|
slotName: string;
|
|
6
6
|
onChange: (event: React.ChangeEvent<HTMLInputElement>) => void;
|
|
7
|
-
}) => import("react
|
|
7
|
+
}) => import("react").JSX.Element;
|
|
8
8
|
export default TypeSelector;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { MenuItem, Paper, TextField } from '@mui/material';
|
|
3
3
|
import { observer } from 'mobx-react';
|
|
4
|
-
import { useSlotEditorStyles } from
|
|
4
|
+
import { useSlotEditorStyles } from './useSlotEditorStyles.js';
|
|
5
5
|
const TypeSelector = observer(function TypeSelector({ typeNameChoices, slot, slotName, onChange, }) {
|
|
6
6
|
const { classes } = useSlotEditorStyles();
|
|
7
|
-
return (_jsx(Paper, { className: classes.paper, children: _jsx("div", { className: classes.paperContent, children: _jsx(TextField, { value: slot
|
|
7
|
+
return (_jsx(Paper, { className: classes.paper, children: _jsx("div", { className: classes.paperContent, children: _jsx(TextField, { value: slot?.type ?? '', label: `Type of ${slotName}`, select: true, variant: "outlined", fullWidth: true, onChange: onChange, children: typeNameChoices.map(str => (_jsx(MenuItem, { value: str, children: str }, str))) }) }) }));
|
|
8
8
|
});
|
|
9
9
|
export default TypeSelector;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Singularize a config schema slot name for the per-entry label an array-typed
|
|
3
|
+
* sub-schema renders ("displays" -> "display LinearBasicDisplay").
|
|
4
|
+
*
|
|
5
|
+
* Slot names are developer-authored camelCase identifiers — `displays`,
|
|
6
|
+
* `tracks`, `connections` are the ones in tree — so the regular English endings
|
|
7
|
+
* are the whole domain. This replaced the `pluralize` dependency, whose value
|
|
8
|
+
* is its irregular-noun table, and nothing here is ever an irregular noun.
|
|
9
|
+
*
|
|
10
|
+
* The counterpart for label text, where the noun comes from a display rather
|
|
11
|
+
* than a schema key, is core's own `pluralize(count, noun)` in `stringUtils`.
|
|
12
|
+
*/
|
|
13
|
+
export declare function singularSlotName(name: string): string;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Singularize a config schema slot name for the per-entry label an array-typed
|
|
3
|
+
* sub-schema renders ("displays" -> "display LinearBasicDisplay").
|
|
4
|
+
*
|
|
5
|
+
* Slot names are developer-authored camelCase identifiers — `displays`,
|
|
6
|
+
* `tracks`, `connections` are the ones in tree — so the regular English endings
|
|
7
|
+
* are the whole domain. This replaced the `pluralize` dependency, whose value
|
|
8
|
+
* is its irregular-noun table, and nothing here is ever an irregular noun.
|
|
9
|
+
*
|
|
10
|
+
* The counterpart for label text, where the noun comes from a display rather
|
|
11
|
+
* than a schema key, is core's own `pluralize(count, noun)` in `stringUtils`.
|
|
12
|
+
*/
|
|
13
|
+
export function singularSlotName(name) {
|
|
14
|
+
return /[^aeiou]ies$/.test(name)
|
|
15
|
+
? `${name.slice(0, -3)}y`
|
|
16
|
+
: /(?:s|sh|ch|x|z)es$/.test(name)
|
|
17
|
+
? name.slice(0, -2)
|
|
18
|
+
: // a trailing `s` after `a`/`i`/`u`/`s` belongs to a word that is already
|
|
19
|
+
// singular — `bias`, `alias`, `axis`, `status`, `class` — not to a plural
|
|
20
|
+
/[^saiu]s$/.test(name)
|
|
21
|
+
? name.slice(0, -1)
|
|
22
|
+
: name;
|
|
23
|
+
}
|
|
@@ -3,8 +3,8 @@ export declare const useSlotEditorStyles: (_params?: unknown, muiStyleOverridesP
|
|
|
3
3
|
classes?: Record<string, string>;
|
|
4
4
|
};
|
|
5
5
|
} | undefined) => {
|
|
6
|
-
classes: Record<"paper" | "paperContent" | "slotModeSwitch", string>;
|
|
7
|
-
theme: import("@
|
|
6
|
+
classes: Record<"paper" | "paperContent" | "resetButton" | "slotModeSwitch", string>;
|
|
7
|
+
theme: import("@jbrowse/core/ui/styleTheme").JBrowseStyleTheme;
|
|
8
8
|
css: import("@jbrowse/core/util/tss-react/types").Css;
|
|
9
9
|
cx: import("@jbrowse/core/util/tss-react/types").Cx;
|
|
10
10
|
};
|
|
@@ -6,7 +6,8 @@ export const useSlotEditorStyles = makeStyles()(theme => ({
|
|
|
6
6
|
position: 'relative',
|
|
7
7
|
},
|
|
8
8
|
paperContent: {
|
|
9
|
-
|
|
9
|
+
flex: 1,
|
|
10
|
+
minWidth: 0,
|
|
10
11
|
},
|
|
11
12
|
slotModeSwitch: {
|
|
12
13
|
width: 24,
|
|
@@ -15,4 +16,8 @@ export const useSlotEditorStyles = makeStyles()(theme => ({
|
|
|
15
16
|
justifyContent: 'center',
|
|
16
17
|
alignItems: 'center',
|
|
17
18
|
},
|
|
19
|
+
resetButton: {
|
|
20
|
+
display: 'flex',
|
|
21
|
+
alignItems: 'center',
|
|
22
|
+
},
|
|
18
23
|
}));
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { lazy } from 'react';
|
|
2
1
|
import { ConfigurationSchema } from '@jbrowse/core/configuration';
|
|
3
2
|
import { WidgetType } from '@jbrowse/core/pluggableElementTypes';
|
|
4
|
-
import
|
|
5
|
-
import
|
|
3
|
+
import { lazyWithPreload } from '@jbrowse/core/util/lazyWithPreload';
|
|
4
|
+
import HeadingComponent from './components/HeadingComponent.js';
|
|
5
|
+
import stateModelFactory from './model.js';
|
|
6
6
|
const configSchema = ConfigurationSchema('ConfigurationEditorWidget', {});
|
|
7
|
-
const LazyConfigurationEditorComponent =
|
|
7
|
+
const LazyConfigurationEditorComponent = lazyWithPreload(() => import('./components/ConfigurationEditor.js'));
|
|
8
8
|
export default function registerConfigurationEditorWidget(pluginManager) {
|
|
9
9
|
pluginManager.addWidgetType(() => {
|
|
10
10
|
return new WidgetType({
|
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
import type PluginManager from '@jbrowse/core/PluginManager';
|
|
2
2
|
import type { AnyConfigurationModel } from '@jbrowse/core/configuration';
|
|
3
|
+
/**
|
|
4
|
+
* #stateModel ConfigurationEditorWidget
|
|
5
|
+
* Widget for editing a config model's slots in a form: holds the target
|
|
6
|
+
* configuration and debounce-saves edits back to the session.
|
|
7
|
+
*/
|
|
3
8
|
export default function stateModelFactory(_pluginManager: PluginManager): import("@jbrowse/mobx-state-tree").IModelType<{
|
|
4
9
|
id: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").ISimpleType<string>, [undefined]>;
|
|
5
|
-
type: import("@jbrowse/mobx-state-tree").
|
|
10
|
+
type: import("@jbrowse/mobx-state-tree").ILiteralType<"ConfigurationEditorWidget">;
|
|
6
11
|
}, {
|
|
7
12
|
target: AnyConfigurationModel | undefined;
|
|
13
|
+
expandedDisplayId: string | undefined;
|
|
8
14
|
} & {
|
|
9
15
|
setTarget(newTarget: AnyConfigurationModel | undefined): void;
|
|
16
|
+
setExpandedDisplayId(displayId: string | undefined): void;
|
|
10
17
|
afterCreate(): void;
|
|
11
18
|
}, import("@jbrowse/mobx-state-tree")._NotCustomized, import("@jbrowse/mobx-state-tree")._NotCustomized>;
|
|
@@ -2,6 +2,11 @@ import { getSession } from '@jbrowse/core/util';
|
|
|
2
2
|
import { ElementId } from '@jbrowse/core/util/types/mst';
|
|
3
3
|
import { addDisposer, getSnapshot, types } from '@jbrowse/mobx-state-tree';
|
|
4
4
|
import { autorun } from 'mobx';
|
|
5
|
+
/**
|
|
6
|
+
* #stateModel ConfigurationEditorWidget
|
|
7
|
+
* Widget for editing a config model's slots in a form: holds the target
|
|
8
|
+
* configuration and debounce-saves edits back to the session.
|
|
9
|
+
*/
|
|
5
10
|
export default function stateModelFactory(_pluginManager) {
|
|
6
11
|
return types
|
|
7
12
|
.model('ConfigurationEditorWidget', {
|
|
@@ -9,24 +14,58 @@ export default function stateModelFactory(_pluginManager) {
|
|
|
9
14
|
type: types.literal('ConfigurationEditorWidget'),
|
|
10
15
|
})
|
|
11
16
|
.volatile(() => ({
|
|
17
|
+
// Target is stored as volatile since it doesn't need to be serialized.
|
|
18
|
+
// The target is an MST model from track.configuration (which creates
|
|
19
|
+
// an MST model from frozen config via ConfigurationReference).
|
|
12
20
|
target: undefined,
|
|
21
|
+
// displayId of the display active in the view this editor was opened
|
|
22
|
+
// from; its config accordion expands by default while the track's other
|
|
23
|
+
// (incompatible/inactive) displays start collapsed
|
|
24
|
+
expandedDisplayId: undefined,
|
|
13
25
|
}))
|
|
14
26
|
.actions(self => ({
|
|
15
27
|
setTarget(newTarget) {
|
|
16
28
|
self.target = newTarget;
|
|
17
29
|
},
|
|
30
|
+
setExpandedDisplayId(displayId) {
|
|
31
|
+
self.expandedDisplayId = displayId;
|
|
32
|
+
},
|
|
18
33
|
afterCreate() {
|
|
19
34
|
let timeout;
|
|
35
|
+
// Auto-save configuration changes with 400ms debounce. The autorun
|
|
36
|
+
// reacts to any changes in the target configuration model and persists
|
|
37
|
+
// them back to the session after a short delay via
|
|
38
|
+
// updateTrackConfiguration, which routes admin edits to the jbrowse
|
|
39
|
+
// config in place and everyone else's to a shareable per-track delta
|
|
40
|
+
// (trackConfigDeltas) against the admin base. It keys off trackId; in
|
|
41
|
+
// practice the widget is only opened on track configs. A config with no
|
|
42
|
+
// trackId (assembly/connection) degrades gracefully: updateTrackConfiguration
|
|
43
|
+
// finds no base/session/connection home and the edit just applies to the
|
|
44
|
+
// live MST node in memory for this session.
|
|
45
|
+
//
|
|
46
|
+
// BaseTrackModel's afterAttach runs a sibling debounced save (a reaction
|
|
47
|
+
// on the same config node) for direct setSlot quick-edits on a *shown*
|
|
48
|
+
// track. Both intentionally coexist: this widget also handles an unshown
|
|
49
|
+
// track edited from the selector, which has no BaseTrackModel. When both
|
|
50
|
+
// fire they compute an identical delta, deduped in updateTrackConfiguration
|
|
51
|
+
// — don't drop one to "simplify".
|
|
20
52
|
addDisposer(self, autorun(() => {
|
|
21
53
|
if (self.target) {
|
|
54
|
+
// track configs (the practical case) carry a trackId; a
|
|
55
|
+
// trackId-less snapshot degrades to an in-memory edit (see above)
|
|
22
56
|
const snapshot = getSnapshot(self.target);
|
|
23
57
|
clearTimeout(timeout);
|
|
24
58
|
timeout = setTimeout(() => {
|
|
25
59
|
const session = getSession(self);
|
|
26
|
-
session.
|
|
60
|
+
session.updateTrackConfiguration(snapshot);
|
|
27
61
|
}, 400);
|
|
28
62
|
}
|
|
29
63
|
}));
|
|
64
|
+
// ensure a pending debounced save can't fire after disposal, where
|
|
65
|
+
// getSession(self) would throw on the now-detached node
|
|
66
|
+
addDisposer(self, () => {
|
|
67
|
+
clearTimeout(timeout);
|
|
68
|
+
});
|
|
30
69
|
},
|
|
31
70
|
}));
|
|
32
71
|
}
|
|
@@ -4,6 +4,11 @@ import type { AnyConfigurationModel } from '@jbrowse/core/configuration';
|
|
|
4
4
|
import type { getSubAdapterType } from '@jbrowse/core/data_adapters/dataAdapterCache';
|
|
5
5
|
import type { Feature, SimpleFeatureSerialized } from '@jbrowse/core/util/simpleFeature';
|
|
6
6
|
import type { NoAssemblyRegion } from '@jbrowse/core/util/types';
|
|
7
|
+
export declare function mergeFeaturesToRegions(features: Map<string, Feature[]>): {
|
|
8
|
+
refName: string;
|
|
9
|
+
start: number;
|
|
10
|
+
end: number;
|
|
11
|
+
}[];
|
|
7
12
|
export declare function makeFeatures(fdata: SimpleFeatureSerialized[]): Map<string, Feature[]>;
|
|
8
13
|
export default class FromConfigAdapter extends BaseFeatureDataAdapter {
|
|
9
14
|
protected features: Map<string, Feature[]>;
|
|
@@ -11,7 +16,7 @@ export default class FromConfigAdapter extends BaseFeatureDataAdapter {
|
|
|
11
16
|
getRefNames(): Promise<string[]>;
|
|
12
17
|
getRefNameAliases(): Promise<{
|
|
13
18
|
refName: string;
|
|
14
|
-
aliases:
|
|
19
|
+
aliases: unknown;
|
|
15
20
|
}[]>;
|
|
16
21
|
getFeatures(region: NoAssemblyRegion): import("rxjs").Observable<Feature>;
|
|
17
22
|
}
|
|
@@ -2,6 +2,35 @@ import { readConfObject } from '@jbrowse/core/configuration';
|
|
|
2
2
|
import { BaseFeatureDataAdapter } from '@jbrowse/core/data_adapters/BaseAdapter';
|
|
3
3
|
import { ObservableCreate } from '@jbrowse/core/util/rxjs';
|
|
4
4
|
import SimpleFeature from '@jbrowse/core/util/simpleFeature';
|
|
5
|
+
export function mergeFeaturesToRegions(features) {
|
|
6
|
+
const regions = [];
|
|
7
|
+
for (const [refName, feats] of features) {
|
|
8
|
+
let currentRegion;
|
|
9
|
+
for (const feature of feats) {
|
|
10
|
+
if (currentRegion &&
|
|
11
|
+
currentRegion.end >= feature.get('start') &&
|
|
12
|
+
currentRegion.start <= feature.get('end')) {
|
|
13
|
+
// take the max: a fully-contained feature (smaller end) must not
|
|
14
|
+
// shrink the merged region
|
|
15
|
+
currentRegion.end = Math.max(currentRegion.end, feature.get('end'));
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
if (currentRegion) {
|
|
19
|
+
regions.push(currentRegion);
|
|
20
|
+
}
|
|
21
|
+
currentRegion = {
|
|
22
|
+
refName,
|
|
23
|
+
start: feature.get('start'),
|
|
24
|
+
end: feature.get('end'),
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
if (currentRegion) {
|
|
29
|
+
regions.push(currentRegion);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return regions;
|
|
33
|
+
}
|
|
5
34
|
export function makeFeatures(fdata) {
|
|
6
35
|
const features = new Map();
|
|
7
36
|
for (const entry of fdata) {
|
|
@@ -14,6 +43,7 @@ export function makeFeatures(fdata) {
|
|
|
14
43
|
}
|
|
15
44
|
bucket.push(f);
|
|
16
45
|
}
|
|
46
|
+
// sort the features on each reference sequence by start coordinate
|
|
17
47
|
for (const refFeatures of features.values()) {
|
|
18
48
|
refFeatures.sort((a, b) => a.get('start') - b.get('start'));
|
|
19
49
|
}
|
|
@@ -38,7 +68,7 @@ export default class FromConfigAdapter extends BaseFeatureDataAdapter {
|
|
|
38
68
|
getFeatures(region) {
|
|
39
69
|
const { refName, start, end } = region;
|
|
40
70
|
return ObservableCreate(async (observer) => {
|
|
41
|
-
const features = this.features.get(refName)
|
|
71
|
+
const features = this.features.get(refName) ?? [];
|
|
42
72
|
for (const f of features) {
|
|
43
73
|
if (f.get('end') > start && f.get('start') < end) {
|
|
44
74
|
observer.next(f);
|
|
@@ -1,7 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* #config FromConfigAdapter
|
|
3
|
+
* #trackType FeatureTrack
|
|
4
|
+
* #fileFormat inline | Inline features | Features written straight into config.json
|
|
5
|
+
* supplies features inline in the config instead of reading a file, useful for
|
|
6
|
+
* small feature sets added via a URL or session spec
|
|
7
|
+
*
|
|
8
|
+
* #example
|
|
9
|
+
* ```js
|
|
10
|
+
* {
|
|
11
|
+
* type: 'FromConfigAdapter',
|
|
12
|
+
* features: [
|
|
13
|
+
* { uniqueId: 'f1', refName: 'ctgA', start: 100, end: 200, name: 'feature1' },
|
|
14
|
+
* ],
|
|
15
|
+
* }
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
1
18
|
declare const configSchema: import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
|
|
2
|
-
|
|
3
|
-
type: string;
|
|
4
|
-
|
|
19
|
+
type: {
|
|
20
|
+
type: "string";
|
|
21
|
+
} & {
|
|
22
|
+
defaultValue: string;
|
|
5
23
|
};
|
|
6
|
-
|
|
24
|
+
readonly adapterId: {
|
|
25
|
+
type: "string";
|
|
26
|
+
} & {
|
|
27
|
+
defaultValue: string;
|
|
28
|
+
};
|
|
29
|
+
readonly features: {
|
|
30
|
+
type: "frozen";
|
|
31
|
+
} & {
|
|
32
|
+
defaultValue: unknown;
|
|
33
|
+
};
|
|
34
|
+
}, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, undefined, true, import("@jbrowse/core/configuration").ConfigurationSchemaRequirement<Partial<Record<string, string[]>>, string>, any>>;
|
|
7
35
|
export default configSchema;
|
|
@@ -1,9 +1,41 @@
|
|
|
1
1
|
import { ConfigurationSchema } from '@jbrowse/core/configuration';
|
|
2
|
-
|
|
2
|
+
/**
|
|
3
|
+
* #config FromConfigAdapter
|
|
4
|
+
* #trackType FeatureTrack
|
|
5
|
+
* #fileFormat inline | Inline features | Features written straight into config.json
|
|
6
|
+
* supplies features inline in the config instead of reading a file, useful for
|
|
7
|
+
* small feature sets added via a URL or session spec
|
|
8
|
+
*
|
|
9
|
+
* #example
|
|
10
|
+
* ```js
|
|
11
|
+
* {
|
|
12
|
+
* type: 'FromConfigAdapter',
|
|
13
|
+
* features: [
|
|
14
|
+
* { uniqueId: 'f1', refName: 'ctgA', start: 100, end: 200, name: 'feature1' },
|
|
15
|
+
* ],
|
|
16
|
+
* }
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
3
19
|
const configSchema = ConfigurationSchema('FromConfigAdapter', {
|
|
20
|
+
/**
|
|
21
|
+
* #slot
|
|
22
|
+
* stable identifier used as the adapter cache key; avoids hashing the
|
|
23
|
+
* (potentially large) features array. optional — falls back to hash.
|
|
24
|
+
*/
|
|
25
|
+
adapterId: {
|
|
26
|
+
type: 'string',
|
|
27
|
+
defaultValue: '',
|
|
28
|
+
},
|
|
29
|
+
/**
|
|
30
|
+
* #slot
|
|
31
|
+
* the features themselves, as an array of plain objects. Each needs a
|
|
32
|
+
* `uniqueId`, `refName`, `start` and `end` (0-based half-open); anything
|
|
33
|
+
* else — `name`, `type`, `score`, `strand`, nested `subfeatures` — is
|
|
34
|
+
* carried through onto the feature as-is.
|
|
35
|
+
*/
|
|
4
36
|
features: {
|
|
5
37
|
type: 'frozen',
|
|
6
38
|
defaultValue: [],
|
|
7
39
|
},
|
|
8
|
-
}, { explicitlyTyped: true
|
|
40
|
+
}, { explicitlyTyped: true });
|
|
9
41
|
export default configSchema;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { AdapterType } from '@jbrowse/core/pluggableElementTypes';
|
|
2
|
-
import configSchema from
|
|
2
|
+
import configSchema from './configSchema.js';
|
|
3
3
|
export default function FromConfigAdapterF(pluginManager) {
|
|
4
4
|
pluginManager.addAdapterType(() => new AdapterType({
|
|
5
5
|
name: 'FromConfigAdapter',
|
|
6
6
|
configSchema,
|
|
7
|
-
getAdapterClass: () => import(
|
|
7
|
+
getAdapterClass: () => import('./FromConfigAdapter.js').then(r => r.default),
|
|
8
8
|
adapterMetadata: {
|
|
9
9
|
hiddenFromGUI: true,
|
|
10
10
|
},
|
|
@@ -3,9 +3,17 @@ import type PluginManager from '@jbrowse/core/PluginManager';
|
|
|
3
3
|
import type { AnyConfigurationModel } from '@jbrowse/core/configuration';
|
|
4
4
|
import type { RegionsAdapter } from '@jbrowse/core/data_adapters/BaseAdapter';
|
|
5
5
|
import type { getSubAdapterType } from '@jbrowse/core/data_adapters/dataAdapterCache';
|
|
6
|
+
/**
|
|
7
|
+
* Adapter that just returns the features defined in its `features` configuration
|
|
8
|
+
* key, like:
|
|
9
|
+
* `"features": [ { "refName": "ctgA", "start":1, "end":20 }, ... ]`
|
|
10
|
+
*/
|
|
6
11
|
export default class FromConfigRegionsAdapter extends BaseAdapter implements RegionsAdapter {
|
|
7
12
|
private features;
|
|
8
13
|
constructor(config: AnyConfigurationModel, getSubAdapter?: getSubAdapterType, pluginManager?: PluginManager);
|
|
14
|
+
/**
|
|
15
|
+
* Get refName, start, and end for all features after collapsing any overlaps
|
|
16
|
+
*/
|
|
9
17
|
getRegions(): Promise<{
|
|
10
18
|
refName: string;
|
|
11
19
|
start: number;
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { readConfObject } from '@jbrowse/core/configuration';
|
|
2
2
|
import { BaseAdapter } from '@jbrowse/core/data_adapters/BaseAdapter';
|
|
3
|
-
import { makeFeatures } from
|
|
3
|
+
import { makeFeatures, mergeFeaturesToRegions, } from '../FromConfigAdapter/FromConfigAdapter.js';
|
|
4
|
+
/**
|
|
5
|
+
* Adapter that just returns the features defined in its `features` configuration
|
|
6
|
+
* key, like:
|
|
7
|
+
* `"features": [ { "refName": "ctgA", "start":1, "end":20 }, ... ]`
|
|
8
|
+
*/
|
|
4
9
|
export default class FromConfigRegionsAdapter extends BaseAdapter {
|
|
5
10
|
features;
|
|
6
11
|
constructor(config, getSubAdapter, pluginManager) {
|
|
@@ -8,31 +13,11 @@ export default class FromConfigRegionsAdapter extends BaseAdapter {
|
|
|
8
13
|
const f = readConfObject(config, 'features');
|
|
9
14
|
this.features = makeFeatures(f);
|
|
10
15
|
}
|
|
16
|
+
/**
|
|
17
|
+
* Get refName, start, and end for all features after collapsing any overlaps
|
|
18
|
+
*/
|
|
11
19
|
async getRegions() {
|
|
12
|
-
const regions =
|
|
13
|
-
for (const [refName, features] of this.features) {
|
|
14
|
-
let currentRegion;
|
|
15
|
-
for (const feature of features) {
|
|
16
|
-
if (currentRegion &&
|
|
17
|
-
currentRegion.end >= feature.get('start') &&
|
|
18
|
-
currentRegion.start <= feature.get('end')) {
|
|
19
|
-
currentRegion.end = feature.get('end');
|
|
20
|
-
}
|
|
21
|
-
else {
|
|
22
|
-
if (currentRegion) {
|
|
23
|
-
regions.push(currentRegion);
|
|
24
|
-
}
|
|
25
|
-
currentRegion = {
|
|
26
|
-
refName,
|
|
27
|
-
start: feature.get('start'),
|
|
28
|
-
end: feature.get('end'),
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
if (currentRegion) {
|
|
33
|
-
regions.push(currentRegion);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
20
|
+
const regions = mergeFeaturesToRegions(this.features);
|
|
36
21
|
regions.sort((a, b) => a.refName.localeCompare(b.refName));
|
|
37
22
|
return regions;
|
|
38
23
|
}
|
|
@@ -1,7 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* #config FromConfigRegionsAdapter
|
|
3
|
+
* #trackType ReferenceSequenceTrack
|
|
4
|
+
* #fileFormat inline | Inline regions | refNames and sizes only, no sequence
|
|
5
|
+
* used for specifying refNames+sizes of an assembly
|
|
6
|
+
*
|
|
7
|
+
* #example
|
|
8
|
+
* Supplies refNames+sizes with no sequence, as the adapter of an assembly's
|
|
9
|
+
* `sequence` (a `ReferenceSequenceTrack`):
|
|
10
|
+
* ```js
|
|
11
|
+
* {
|
|
12
|
+
* type: 'ReferenceSequenceTrack',
|
|
13
|
+
* trackId: 'my_refseq',
|
|
14
|
+
* adapter: {
|
|
15
|
+
* type: 'FromConfigRegionsAdapter',
|
|
16
|
+
* features: [
|
|
17
|
+
* { uniqueId: 'ctgA', refName: 'ctgA', start: 0, end: 50000 },
|
|
18
|
+
* { uniqueId: 'ctgB', refName: 'ctgB', start: 0, end: 6079 },
|
|
19
|
+
* ],
|
|
20
|
+
* },
|
|
21
|
+
* }
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
1
24
|
declare const regionsConfigSchema: import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
|
|
2
|
-
|
|
3
|
-
type: string;
|
|
4
|
-
|
|
25
|
+
type: {
|
|
26
|
+
type: "string";
|
|
27
|
+
} & {
|
|
28
|
+
defaultValue: string;
|
|
5
29
|
};
|
|
6
|
-
|
|
30
|
+
readonly adapterId: {
|
|
31
|
+
type: "string";
|
|
32
|
+
} & {
|
|
33
|
+
defaultValue: string;
|
|
34
|
+
};
|
|
35
|
+
readonly features: {
|
|
36
|
+
type: "frozen";
|
|
37
|
+
} & {
|
|
38
|
+
defaultValue: unknown;
|
|
39
|
+
};
|
|
40
|
+
}, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, undefined, true, import("@jbrowse/core/configuration").ConfigurationSchemaRequirement<Partial<Record<string, string[]>>, string>, any>>;
|
|
7
41
|
export default regionsConfigSchema;
|
|
@@ -1,12 +1,49 @@
|
|
|
1
1
|
import { ConfigurationSchema } from '@jbrowse/core/configuration';
|
|
2
|
-
|
|
2
|
+
/**
|
|
3
|
+
* #config FromConfigRegionsAdapter
|
|
4
|
+
* #trackType ReferenceSequenceTrack
|
|
5
|
+
* #fileFormat inline | Inline regions | refNames and sizes only, no sequence
|
|
6
|
+
* used for specifying refNames+sizes of an assembly
|
|
7
|
+
*
|
|
8
|
+
* #example
|
|
9
|
+
* Supplies refNames+sizes with no sequence, as the adapter of an assembly's
|
|
10
|
+
* `sequence` (a `ReferenceSequenceTrack`):
|
|
11
|
+
* ```js
|
|
12
|
+
* {
|
|
13
|
+
* type: 'ReferenceSequenceTrack',
|
|
14
|
+
* trackId: 'my_refseq',
|
|
15
|
+
* adapter: {
|
|
16
|
+
* type: 'FromConfigRegionsAdapter',
|
|
17
|
+
* features: [
|
|
18
|
+
* { uniqueId: 'ctgA', refName: 'ctgA', start: 0, end: 50000 },
|
|
19
|
+
* { uniqueId: 'ctgB', refName: 'ctgB', start: 0, end: 6079 },
|
|
20
|
+
* ],
|
|
21
|
+
* },
|
|
22
|
+
* }
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
3
25
|
const regionsConfigSchema = ConfigurationSchema('FromConfigRegionsAdapter', {
|
|
26
|
+
/**
|
|
27
|
+
* #slot
|
|
28
|
+
* stable identifier used as the adapter cache key; avoids hashing the
|
|
29
|
+
* (potentially large) features array. optional — falls back to hash.
|
|
30
|
+
*/
|
|
31
|
+
adapterId: {
|
|
32
|
+
type: 'string',
|
|
33
|
+
defaultValue: '',
|
|
34
|
+
},
|
|
35
|
+
/**
|
|
36
|
+
* #slot
|
|
37
|
+
* one entry per reference sequence, each with a `uniqueId`, `refName`,
|
|
38
|
+
* `start: 0` and `end` set to that sequence's length. This is what defines
|
|
39
|
+
* the assembly's reference names and sizes; no bases are supplied, so
|
|
40
|
+
* base-level views are empty.
|
|
41
|
+
*/
|
|
4
42
|
features: {
|
|
5
43
|
type: 'frozen',
|
|
6
44
|
defaultValue: [],
|
|
7
45
|
},
|
|
8
46
|
}, {
|
|
9
47
|
explicitlyTyped: true,
|
|
10
|
-
implicitIdentifier: 'adapterId',
|
|
11
48
|
});
|
|
12
49
|
export default regionsConfigSchema;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { AdapterType } from '@jbrowse/core/pluggableElementTypes';
|
|
2
|
-
import configSchema from
|
|
2
|
+
import configSchema from './configSchema.js';
|
|
3
3
|
export default function FromConfigRegionsAdapterF(pluginManager) {
|
|
4
4
|
pluginManager.addAdapterType(() => new AdapterType({
|
|
5
5
|
name: 'FromConfigRegionsAdapter',
|
|
6
6
|
configSchema,
|
|
7
|
-
getAdapterClass: () => import(
|
|
7
|
+
getAdapterClass: () => import('./FromConfigRegionsAdapter.js').then(r => r.default),
|
|
8
8
|
adapterMetadata: {
|
|
9
9
|
hiddenFromGUI: true,
|
|
10
10
|
},
|