@jbrowse/plugin-data-management 2.6.2 → 2.6.3
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/HierarchicalTrackSelectorWidget/components/faceted/FacetedSelector.js +4 -5
- package/dist/HierarchicalTrackSelectorWidget/components/tree/HamburgerMenu.js +35 -19
- package/dist/HierarchicalTrackSelectorWidget/components/tree/HierarchicalHeader.js +10 -6
- package/dist/HierarchicalTrackSelectorWidget/components/tree/HierarchicalTree.d.ts +2 -1
- package/dist/HierarchicalTrackSelectorWidget/components/tree/TrackCategory.js +22 -0
- package/dist/HierarchicalTrackSelectorWidget/components/tree/TrackLabel.js +1 -1
- package/dist/HierarchicalTrackSelectorWidget/components/util.d.ts +2 -1
- package/dist/HierarchicalTrackSelectorWidget/filterTracks.d.ts +12 -0
- package/dist/HierarchicalTrackSelectorWidget/filterTracks.js +32 -0
- package/dist/HierarchicalTrackSelectorWidget/generateHierarchy.d.ts +21 -0
- package/dist/HierarchicalTrackSelectorWidget/generateHierarchy.js +98 -0
- package/dist/HierarchicalTrackSelectorWidget/model.d.ts +68 -28
- package/dist/HierarchicalTrackSelectorWidget/model.js +149 -117
- package/dist/HierarchicalTrackSelectorWidget/util.d.ts +12 -0
- package/dist/HierarchicalTrackSelectorWidget/util.js +53 -0
- package/dist/PluginStoreWidget/components/AddCustomPluginDialog.d.ts +7 -0
- package/dist/PluginStoreWidget/components/{CustomPluginForm.js → AddCustomPluginDialog.js} +12 -21
- package/dist/PluginStoreWidget/components/DeletePluginDialog.d.ts +5 -0
- package/dist/PluginStoreWidget/components/DeletePluginDialog.js +28 -0
- package/dist/PluginStoreWidget/components/InstalledPlugin.d.ts +2 -5
- package/dist/PluginStoreWidget/components/InstalledPlugin.js +19 -50
- package/dist/PluginStoreWidget/components/InstalledPluginsList.d.ts +2 -3
- package/dist/PluginStoreWidget/components/InstalledPluginsList.js +6 -9
- package/dist/PluginStoreWidget/components/PluginCard.js +3 -5
- package/dist/PluginStoreWidget/components/PluginStoreWidget.js +11 -39
- package/dist/PluginStoreWidget/components/util.d.ts +5 -0
- package/dist/PluginStoreWidget/components/util.js +29 -0
- package/dist/PluginStoreWidget/model.d.ts +2 -2
- package/dist/PluginStoreWidget/model.js +2 -2
- package/esm/HierarchicalTrackSelectorWidget/components/faceted/FacetedSelector.js +1 -2
- package/esm/HierarchicalTrackSelectorWidget/components/tree/HamburgerMenu.js +34 -18
- package/esm/HierarchicalTrackSelectorWidget/components/tree/HierarchicalHeader.js +10 -6
- package/esm/HierarchicalTrackSelectorWidget/components/tree/HierarchicalTree.d.ts +2 -1
- package/esm/HierarchicalTrackSelectorWidget/components/tree/TrackCategory.js +22 -0
- package/esm/HierarchicalTrackSelectorWidget/components/tree/TrackLabel.js +1 -1
- package/esm/HierarchicalTrackSelectorWidget/components/util.d.ts +2 -1
- package/esm/HierarchicalTrackSelectorWidget/filterTracks.d.ts +12 -0
- package/esm/HierarchicalTrackSelectorWidget/filterTracks.js +28 -0
- package/esm/HierarchicalTrackSelectorWidget/generateHierarchy.d.ts +21 -0
- package/esm/HierarchicalTrackSelectorWidget/generateHierarchy.js +94 -0
- package/esm/HierarchicalTrackSelectorWidget/model.d.ts +68 -28
- package/esm/HierarchicalTrackSelectorWidget/model.js +151 -116
- package/esm/HierarchicalTrackSelectorWidget/util.d.ts +12 -0
- package/esm/HierarchicalTrackSelectorWidget/util.js +45 -0
- package/esm/PluginStoreWidget/components/AddCustomPluginDialog.d.ts +7 -0
- package/esm/PluginStoreWidget/components/{CustomPluginForm.js → AddCustomPluginDialog.js} +12 -21
- package/esm/PluginStoreWidget/components/DeletePluginDialog.d.ts +5 -0
- package/esm/PluginStoreWidget/components/DeletePluginDialog.js +22 -0
- package/esm/PluginStoreWidget/components/InstalledPlugin.d.ts +2 -5
- package/esm/PluginStoreWidget/components/InstalledPlugin.js +22 -53
- package/esm/PluginStoreWidget/components/InstalledPluginsList.d.ts +2 -3
- package/esm/PluginStoreWidget/components/InstalledPluginsList.js +6 -9
- package/esm/PluginStoreWidget/components/PluginCard.js +3 -5
- package/esm/PluginStoreWidget/components/PluginStoreWidget.js +12 -40
- package/esm/PluginStoreWidget/components/util.d.ts +5 -0
- package/esm/PluginStoreWidget/components/util.js +25 -0
- package/esm/PluginStoreWidget/model.d.ts +2 -2
- package/esm/PluginStoreWidget/model.js +1 -1
- package/package.json +2 -2
- package/dist/PluginStoreWidget/components/CustomPluginForm.d.ts +0 -9
- package/esm/PluginStoreWidget/components/CustomPluginForm.d.ts +0 -9
|
@@ -42,11 +42,10 @@ const util_1 = require("@jbrowse/core/util");
|
|
|
42
42
|
const configuration_1 = require("@jbrowse/core/configuration");
|
|
43
43
|
// icons
|
|
44
44
|
const MoreHoriz_1 = __importDefault(require("@mui/icons-material/MoreHoriz"));
|
|
45
|
-
|
|
46
|
-
const model_1 = require("../../model");
|
|
45
|
+
const util_2 = require("../../util");
|
|
47
46
|
const FacetedHeader_1 = __importDefault(require("./FacetedHeader"));
|
|
48
47
|
const FacetFilters_1 = __importDefault(require("./FacetFilters"));
|
|
49
|
-
const
|
|
48
|
+
const util_3 = require("./util");
|
|
50
49
|
const nonMetadataKeys = ['category', 'adapter', 'description'];
|
|
51
50
|
const frac = 0.75;
|
|
52
51
|
exports.default = (0, mobx_react_1.observer)(function FacetedSelector({ model, }) {
|
|
@@ -70,7 +69,7 @@ exports.default = (0, mobx_react_1.observer)(function FacetedSelector({ model, }
|
|
|
70
69
|
// metadata is spread onto the object for easier access and sorting
|
|
71
70
|
// by the mui data grid (it's unable to sort by nested objects)
|
|
72
71
|
return model.trackConfigurations
|
|
73
|
-
.filter(conf => (0,
|
|
72
|
+
.filter(conf => (0, util_2.matches)(filterDebounced, conf, session))
|
|
74
73
|
.map(track => {
|
|
75
74
|
var _a, _b;
|
|
76
75
|
const metadata = (0, configuration_1.readConfObject)(track, 'metadata');
|
|
@@ -87,7 +86,7 @@ exports.default = (0, mobx_react_1.observer)(function FacetedSelector({ model, }
|
|
|
87
86
|
});
|
|
88
87
|
}, [model, filterDebounced, session]);
|
|
89
88
|
const filteredNonMetadataKeys = (0, react_1.useMemo)(() => nonMetadataKeys.filter(f => !hideSparse ? true : rows.map(r => r[f]).filter(f => !!f).length > 5), [hideSparse, rows]);
|
|
90
|
-
const filteredMetadataKeys = (0, react_1.useMemo)(() => [...new Set(rows.flatMap(row => (0,
|
|
89
|
+
const filteredMetadataKeys = (0, react_1.useMemo)(() => [...new Set(rows.flatMap(row => (0, util_3.getRootKeys)(row.metadata)))].filter(f => !hideSparse
|
|
91
90
|
? true
|
|
92
91
|
: rows.map(r => r.metadata[f]).filter(f => !!f).length > 5), [hideSparse, rows]);
|
|
93
92
|
const fields = (0, react_1.useMemo)(() => ['name', ...filteredNonMetadataKeys, ...filteredMetadataKeys], [filteredNonMetadataKeys, filteredMetadataKeys]);
|
|
@@ -27,33 +27,23 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
27
27
|
};
|
|
28
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
29
|
const react_1 = __importStar(require("react"));
|
|
30
|
-
const material_1 = require("@mui/material");
|
|
31
|
-
const mui_1 = require("tss-react/mui");
|
|
32
30
|
const mobx_react_1 = require("mobx-react");
|
|
33
|
-
const Menu_1 = __importDefault(require("@jbrowse/core/ui/Menu"));
|
|
34
31
|
const util_1 = require("@jbrowse/core/util");
|
|
35
32
|
const configuration_1 = require("@jbrowse/core/configuration");
|
|
33
|
+
const CascadingMenuButton_1 = __importDefault(require("@jbrowse/core/ui/CascadingMenuButton"));
|
|
36
34
|
// icons
|
|
37
|
-
const
|
|
35
|
+
const Menu_1 = __importDefault(require("@mui/icons-material/Menu"));
|
|
38
36
|
// lazy components
|
|
39
37
|
const CloseConnectionDlg = (0, react_1.lazy)(() => Promise.resolve().then(() => __importStar(require('../dialogs/CloseConnectionDialog'))));
|
|
40
38
|
const DeleteConnectionDlg = (0, react_1.lazy)(() => Promise.resolve().then(() => __importStar(require('../dialogs/DeleteConnectionDialog'))));
|
|
41
39
|
const ManageConnectionsDlg = (0, react_1.lazy)(() => Promise.resolve().then(() => __importStar(require('../dialogs/ManageConnectionsDialog'))));
|
|
42
40
|
const ToggleConnectionsDlg = (0, react_1.lazy)(() => Promise.resolve().then(() => __importStar(require('../dialogs/ToggleConnectionsDialog'))));
|
|
43
|
-
const useStyles = (0, mui_1.makeStyles)()(theme => ({
|
|
44
|
-
menuIcon: {
|
|
45
|
-
marginRight: theme.spacing(1),
|
|
46
|
-
marginBottom: 0,
|
|
47
|
-
},
|
|
48
|
-
}));
|
|
49
41
|
exports.default = (0, mobx_react_1.observer)(function HamburgerMenu({ model, }) {
|
|
50
42
|
const session = (0, util_1.getSession)(model);
|
|
51
|
-
const [menuEl, setMenuEl] = (0, react_1.useState)();
|
|
52
43
|
const [modalInfo, setModalInfo] = (0, react_1.useState)();
|
|
53
44
|
const [deleteDlgDetails, setDeleteDlgDetails] = (0, react_1.useState)();
|
|
54
45
|
const [connectionToggleOpen, setConnectionToggleOpen] = (0, react_1.useState)(false);
|
|
55
46
|
const [connectionManagerOpen, setConnectionManagerOpen] = (0, react_1.useState)(false);
|
|
56
|
-
const { classes } = useStyles();
|
|
57
47
|
function breakConnection(connectionConf, deletingConnection) {
|
|
58
48
|
const name = (0, configuration_1.readConfObject)(connectionConf, 'name');
|
|
59
49
|
const result = session.prepareToBreakConnection(connectionConf);
|
|
@@ -76,12 +66,7 @@ exports.default = (0, mobx_react_1.observer)(function HamburgerMenu({ model, })
|
|
|
76
66
|
}
|
|
77
67
|
}
|
|
78
68
|
return (react_1.default.createElement(react_1.default.Fragment, null,
|
|
79
|
-
react_1.default.createElement(
|
|
80
|
-
react_1.default.createElement(Menu_2.default, null)),
|
|
81
|
-
react_1.default.createElement(Menu_1.default, { anchorEl: menuEl, open: Boolean(menuEl), onMenuItemClick: (_, callback) => {
|
|
82
|
-
callback();
|
|
83
|
-
setMenuEl(undefined);
|
|
84
|
-
}, onClose: () => setMenuEl(undefined), menuItems: [
|
|
69
|
+
react_1.default.createElement(CascadingMenuButton_1.default, { menuItems: [
|
|
85
70
|
...((0, util_1.isSessionWithAddTracks)(session)
|
|
86
71
|
? [
|
|
87
72
|
{
|
|
@@ -120,7 +105,38 @@ exports.default = (0, mobx_react_1.observer)(function HamburgerMenu({ model, })
|
|
|
120
105
|
},
|
|
121
106
|
]
|
|
122
107
|
: []),
|
|
123
|
-
|
|
108
|
+
{ type: 'divider' },
|
|
109
|
+
{
|
|
110
|
+
label: 'Sort tracks by name',
|
|
111
|
+
type: 'checkbox',
|
|
112
|
+
checked: model.activeSortTrackNames,
|
|
113
|
+
onClick: () => model.setSortTrackNames(!model.activeSortTrackNames),
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
label: 'Sort categories by name',
|
|
117
|
+
type: 'checkbox',
|
|
118
|
+
checked: model.activeSortCategories,
|
|
119
|
+
onClick: () => model.setSortCategories(!model.activeSortCategories),
|
|
120
|
+
},
|
|
121
|
+
{ type: 'divider' },
|
|
122
|
+
...(model.hasAnySubcategories
|
|
123
|
+
? [
|
|
124
|
+
{
|
|
125
|
+
label: 'Collapse subcategories',
|
|
126
|
+
onClick: () => model.collapseSubCategories(),
|
|
127
|
+
},
|
|
128
|
+
]
|
|
129
|
+
: []),
|
|
130
|
+
{
|
|
131
|
+
label: 'Collapse top-level categories',
|
|
132
|
+
onClick: () => model.collapseTopLevelCategories(),
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
label: 'Expand all categories',
|
|
136
|
+
onClick: () => model.expandAllCategories(),
|
|
137
|
+
},
|
|
138
|
+
] },
|
|
139
|
+
react_1.default.createElement(Menu_1.default, null)),
|
|
124
140
|
react_1.default.createElement(react_1.Suspense, { fallback: react_1.default.createElement(react_1.default.Fragment, null) },
|
|
125
141
|
modalInfo ? (react_1.default.createElement(CloseConnectionDlg, { modalInfo: modalInfo, onClose: () => setModalInfo(undefined) })) : null,
|
|
126
142
|
deleteDlgDetails ? (react_1.default.createElement(DeleteConnectionDlg, { handleClose: () => setDeleteDlgDetails(undefined), deleteDialogDetails: deleteDlgDetails, session: session })) : null,
|
|
@@ -45,19 +45,23 @@ const useStyles = (0, mui_1.makeStyles)()(theme => ({
|
|
|
45
45
|
marginBottom: 0,
|
|
46
46
|
},
|
|
47
47
|
}));
|
|
48
|
+
const SearchTracksTextField = (0, mobx_react_1.observer)(function ({ model, }) {
|
|
49
|
+
const { filterText } = model;
|
|
50
|
+
const { classes } = useStyles();
|
|
51
|
+
return (react_1.default.createElement(material_1.TextField, { className: classes.searchBox, label: "Filter tracks", value: filterText, onChange: event => model.setFilterText(event.target.value), fullWidth: true, InputProps: {
|
|
52
|
+
endAdornment: (react_1.default.createElement(material_1.InputAdornment, { position: "end" },
|
|
53
|
+
react_1.default.createElement(material_1.IconButton, { onClick: () => model.clearFilterText() },
|
|
54
|
+
react_1.default.createElement(Clear_1.default, null)))),
|
|
55
|
+
} }));
|
|
56
|
+
});
|
|
48
57
|
function HierarchicalTrackSelectorHeader({ model, setHeaderHeight, }) {
|
|
49
58
|
const { classes } = useStyles();
|
|
50
59
|
const [facetedOpen, setFacetedOpen] = (0, react_1.useState)(false);
|
|
51
|
-
const { filterText } = model;
|
|
52
60
|
return (react_1.default.createElement("div", { ref: ref => setHeaderHeight((ref === null || ref === void 0 ? void 0 : ref.getBoundingClientRect().height) || 0), "data-testid": "hierarchical_track_selector" },
|
|
53
61
|
react_1.default.createElement("div", { style: { display: 'flex' } },
|
|
54
62
|
react_1.default.createElement(HamburgerMenu_1.default, { model: model }),
|
|
55
63
|
react_1.default.createElement(ShoppingCart_1.default, { model: model }),
|
|
56
|
-
react_1.default.createElement(
|
|
57
|
-
endAdornment: (react_1.default.createElement(material_1.InputAdornment, { position: "end" },
|
|
58
|
-
react_1.default.createElement(material_1.IconButton, { onClick: () => model.clearFilterText() },
|
|
59
|
-
react_1.default.createElement(Clear_1.default, null)))),
|
|
60
|
-
} }),
|
|
64
|
+
react_1.default.createElement(SearchTracksTextField, { model: model }),
|
|
61
65
|
react_1.default.createElement(material_1.Button, { className: classes.menuIcon, onClick: () => setFacetedOpen(true) }, "Open faceted selector")),
|
|
62
66
|
react_1.default.createElement(react_1.Suspense, { fallback: react_1.default.createElement("div", null) }, facetedOpen ? (react_1.default.createElement(FacetedDialog, { handleClose: () => setFacetedOpen(false), model: model })) : null)));
|
|
63
67
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { TreeNode
|
|
2
|
+
import { TreeNode } from '../../generateHierarchy';
|
|
3
|
+
import { HierarchicalTrackSelectorModel } from '../../model';
|
|
3
4
|
declare const _default: ({ height, tree, model, }: {
|
|
4
5
|
height: number;
|
|
5
6
|
tree: TreeNode;
|
|
@@ -80,6 +80,28 @@ function Category({ isOpen, setOpen, data, }) {
|
|
|
80
80
|
model.removeFromSelection((0, util_1.getAllChildren)(r));
|
|
81
81
|
},
|
|
82
82
|
},
|
|
83
|
+
{
|
|
84
|
+
label: 'Show all tracks',
|
|
85
|
+
onClick: () => {
|
|
86
|
+
var _a;
|
|
87
|
+
for (const entry of ((_a = (0, util_1.treeToMap)(tree).get(id)) === null || _a === void 0 ? void 0 : _a.children) || []) {
|
|
88
|
+
if (!entry.children.length) {
|
|
89
|
+
model.view.showTrack(entry.id);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
label: 'Hide all tracks',
|
|
96
|
+
onClick: () => {
|
|
97
|
+
var _a;
|
|
98
|
+
for (const entry of ((_a = (0, util_1.treeToMap)(tree).get(id)) === null || _a === void 0 ? void 0 : _a.children) || []) {
|
|
99
|
+
if (!entry.children.length) {
|
|
100
|
+
model.view.hideTrack(entry.id);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
},
|
|
83
105
|
], onMenuItemClick: (_event, callback) => {
|
|
84
106
|
callback();
|
|
85
107
|
setMenuEl(null);
|
|
@@ -59,7 +59,7 @@ function TrackLabel({ data }) {
|
|
|
59
59
|
react_1.default.createElement(material_1.FormControlLabel, { className: classes.checkboxLabel, control: react_1.default.createElement(material_1.Checkbox, { className: classes.compactCheckbox, checked: checked, onChange: () => onChange(id), disabled: (0, util_2.isUnsupported)(name), inputProps: {
|
|
60
60
|
// @ts-expect-error
|
|
61
61
|
'data-testid': `htsTrackEntry-${id}`,
|
|
62
|
-
} }), label: react_1.default.createElement("div", { style: { background: selected ? '#cccc' : undefined } },
|
|
62
|
+
} }), label: react_1.default.createElement("div", { "data-testid": `htsTrackLabel-${id}`, style: { background: selected ? '#cccc' : undefined } },
|
|
63
63
|
react_1.default.createElement(ui_1.SanitizedHTML, { html: name })) })),
|
|
64
64
|
react_1.default.createElement(material_1.IconButton, { onClick: e => setInfo({ target: e.currentTarget, id, conf }), style: { padding: 0 }, "data-testid": `htsTrackEntryMenu-${id}` },
|
|
65
65
|
react_1.default.createElement(MoreHoriz_1.default, null)),
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { AnyConfigurationModel } from '@jbrowse/core/configuration';
|
|
2
|
-
import { HierarchicalTrackSelectorModel
|
|
2
|
+
import { HierarchicalTrackSelectorModel } from '../model';
|
|
3
|
+
import { TreeNode } from '../generateHierarchy';
|
|
3
4
|
export interface NodeData {
|
|
4
5
|
nestingLevel: number;
|
|
5
6
|
checked: boolean;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { AnyConfigurationModel } from '@jbrowse/core/configuration';
|
|
2
|
+
export declare function filterTracks(tracks: AnyConfigurationModel[], self: {
|
|
3
|
+
view?: {
|
|
4
|
+
type: string;
|
|
5
|
+
trackSelectorAnyOverlap?: boolean;
|
|
6
|
+
};
|
|
7
|
+
assemblyNames: string[];
|
|
8
|
+
}): ({
|
|
9
|
+
[x: string]: any;
|
|
10
|
+
} & import("mobx-state-tree/dist/internal").NonEmptyObject & {
|
|
11
|
+
setSubschema(slotName: string, data: unknown): any;
|
|
12
|
+
} & import("mobx-state-tree").IStateTreeNode<import("@jbrowse/core/configuration").AnyConfigurationSchemaType>)[];
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.filterTracks = void 0;
|
|
4
|
+
const configuration_1 = require("@jbrowse/core/configuration");
|
|
5
|
+
const util_1 = require("@jbrowse/core/util");
|
|
6
|
+
const util_2 = require("./util");
|
|
7
|
+
function filterTracks(tracks, self) {
|
|
8
|
+
const { assemblyManager } = (0, util_1.getSession)(self);
|
|
9
|
+
const { pluginManager } = (0, util_1.getEnv)(self);
|
|
10
|
+
const { view } = self;
|
|
11
|
+
if (!view) {
|
|
12
|
+
return [];
|
|
13
|
+
}
|
|
14
|
+
const trackListAssemblies = self.assemblyNames
|
|
15
|
+
.map(a => assemblyManager.get(a))
|
|
16
|
+
.filter(util_1.notEmpty);
|
|
17
|
+
return tracks
|
|
18
|
+
.filter(c => {
|
|
19
|
+
const trackAssemblyNames = (0, configuration_1.readConfObject)(c, 'assemblyNames');
|
|
20
|
+
const trackAssemblies = trackAssemblyNames === null || trackAssemblyNames === void 0 ? void 0 : trackAssemblyNames.map(name => assemblyManager.get(name)).filter(util_1.notEmpty);
|
|
21
|
+
return view.trackSelectorAnyOverlap
|
|
22
|
+
? (0, util_2.hasAnyOverlap)(trackAssemblies, trackListAssemblies)
|
|
23
|
+
: (0, util_2.hasAllOverlap)(trackAssemblies, trackListAssemblies);
|
|
24
|
+
})
|
|
25
|
+
.filter(c => {
|
|
26
|
+
const { displayTypes } = pluginManager.getViewType(view.type);
|
|
27
|
+
const compatDisplays = displayTypes.map(d => d.name);
|
|
28
|
+
const trackDisplays = c.displays.map((d) => d.type);
|
|
29
|
+
return (0, util_2.hasAnyOverlap)(compatDisplays, trackDisplays);
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
exports.filterTracks = filterTracks;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { AnyConfigurationModel } from '@jbrowse/core/configuration';
|
|
2
|
+
export type TreeNode = {
|
|
3
|
+
name: string;
|
|
4
|
+
id: string;
|
|
5
|
+
conf?: AnyConfigurationModel;
|
|
6
|
+
checked?: boolean;
|
|
7
|
+
isOpenByDefault?: boolean;
|
|
8
|
+
children: TreeNode[];
|
|
9
|
+
};
|
|
10
|
+
export declare function generateHierarchy(model: {
|
|
11
|
+
filterText: string;
|
|
12
|
+
activeSortTrackNames: boolean;
|
|
13
|
+
activeSortCategories: boolean;
|
|
14
|
+
view?: {
|
|
15
|
+
tracks: {
|
|
16
|
+
configuration: AnyConfigurationModel;
|
|
17
|
+
}[];
|
|
18
|
+
};
|
|
19
|
+
}, trackConfs: AnyConfigurationModel[], collapsed: {
|
|
20
|
+
get: (arg: string) => boolean | undefined;
|
|
21
|
+
}, extra?: string): TreeNode[];
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateHierarchy = void 0;
|
|
4
|
+
const configuration_1 = require("@jbrowse/core/configuration");
|
|
5
|
+
const util_1 = require("@jbrowse/core/util");
|
|
6
|
+
const tracks_1 = require("@jbrowse/core/util/tracks");
|
|
7
|
+
// locals
|
|
8
|
+
const util_2 = require("./util");
|
|
9
|
+
function sortConfs(confs, sortNames, sortCategories) {
|
|
10
|
+
// uses readConfObject instead of getTrackName so that the undefined
|
|
11
|
+
// reference sequence track is sorted to the top
|
|
12
|
+
const ret = confs.map(c => {
|
|
13
|
+
var _a, _b, _c;
|
|
14
|
+
return [
|
|
15
|
+
c,
|
|
16
|
+
(0, configuration_1.readConfObject)(c, 'name'),
|
|
17
|
+
((_a = (0, configuration_1.readConfObject)(c, 'category')) === null || _a === void 0 ? void 0 : _a[0]) || '',
|
|
18
|
+
((_b = (0, configuration_1.readConfObject)(c, 'category')) === null || _b === void 0 ? void 0 : _b[1]) || '',
|
|
19
|
+
((_c = (0, configuration_1.readConfObject)(c, 'category')) === null || _c === void 0 ? void 0 : _c[2]) || '',
|
|
20
|
+
];
|
|
21
|
+
});
|
|
22
|
+
if (sortNames) {
|
|
23
|
+
ret.sort((a, b) => a[1].localeCompare(b[1]));
|
|
24
|
+
}
|
|
25
|
+
if (sortCategories) {
|
|
26
|
+
// sort up to three sub-category levels, harder to code it to go deeper
|
|
27
|
+
// than this and likely rarely used
|
|
28
|
+
ret.sort((a, b) => {
|
|
29
|
+
if (a[2] !== b[2]) {
|
|
30
|
+
return a[2].localeCompare(b[2]);
|
|
31
|
+
}
|
|
32
|
+
else if (a[3] !== b[3]) {
|
|
33
|
+
return a[3].localeCompare(b[3]);
|
|
34
|
+
}
|
|
35
|
+
else if (a[4] !== b[4]) {
|
|
36
|
+
return a[4].localeCompare(b[4]);
|
|
37
|
+
}
|
|
38
|
+
return 0;
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
return ret.map(a => a[0]);
|
|
42
|
+
}
|
|
43
|
+
function generateHierarchy(model, trackConfs, collapsed, extra) {
|
|
44
|
+
const hierarchy = { children: [] };
|
|
45
|
+
const { filterText, activeSortTrackNames, activeSortCategories, view } = model;
|
|
46
|
+
if (!view) {
|
|
47
|
+
return [];
|
|
48
|
+
}
|
|
49
|
+
const session = (0, util_1.getSession)(model);
|
|
50
|
+
const viewTracks = view.tracks;
|
|
51
|
+
const confs = trackConfs.filter(conf => (0, util_2.matches)(filterText, conf, session));
|
|
52
|
+
// uses getConf
|
|
53
|
+
for (const conf of sortConfs(confs, activeSortTrackNames, activeSortCategories)) {
|
|
54
|
+
// copy the categories since this array can be mutated downstream
|
|
55
|
+
const categories = [...((0, configuration_1.readConfObject)(conf, 'category') || [])];
|
|
56
|
+
// hack where if trackId ends with sessionTrack, then push it to a
|
|
57
|
+
// category that starts with a space to force sort to the top
|
|
58
|
+
if (conf.trackId.endsWith('sessionTrack')) {
|
|
59
|
+
categories.unshift(' Session tracks');
|
|
60
|
+
}
|
|
61
|
+
let currLevel = hierarchy;
|
|
62
|
+
// find existing category to put track into or create it
|
|
63
|
+
for (let i = 0; i < categories.length; i++) {
|
|
64
|
+
const category = categories[i];
|
|
65
|
+
const ret = currLevel.children.find(c => c.name === category);
|
|
66
|
+
const id = [extra, categories.slice(0, i + 1).join(',')]
|
|
67
|
+
.filter(f => !!f)
|
|
68
|
+
.join('-');
|
|
69
|
+
if (!ret) {
|
|
70
|
+
const n = {
|
|
71
|
+
children: [],
|
|
72
|
+
name: category,
|
|
73
|
+
id,
|
|
74
|
+
isOpenByDefault: !collapsed.get(id),
|
|
75
|
+
};
|
|
76
|
+
currLevel.children.push(n);
|
|
77
|
+
currLevel = n;
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
currLevel = ret;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
// uses splice to try to put all leaf nodes above "category nodes" if you
|
|
84
|
+
// change the splice to a simple push and open
|
|
85
|
+
// test_data/test_order/config.json you will see the weirdness
|
|
86
|
+
const r = currLevel.children.findIndex(elt => elt.children.length);
|
|
87
|
+
const idx = r === -1 ? currLevel.children.length : r;
|
|
88
|
+
currLevel.children.splice(idx, 0, {
|
|
89
|
+
id: conf.trackId,
|
|
90
|
+
name: (0, tracks_1.getTrackName)(conf, session),
|
|
91
|
+
conf,
|
|
92
|
+
checked: viewTracks.some(f => f.configuration === conf),
|
|
93
|
+
children: [],
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
return hierarchy.children;
|
|
97
|
+
}
|
|
98
|
+
exports.generateHierarchy = generateHierarchy;
|
|
@@ -1,19 +1,7 @@
|
|
|
1
1
|
import { Instance } from 'mobx-state-tree';
|
|
2
2
|
import { AnyConfigurationModel } from '@jbrowse/core/configuration';
|
|
3
|
-
import { AbstractSessionModel } from '@jbrowse/core/util';
|
|
4
3
|
import PluginManager from '@jbrowse/core/PluginManager';
|
|
5
|
-
|
|
6
|
-
export type TreeNode = {
|
|
7
|
-
name: string;
|
|
8
|
-
id: string;
|
|
9
|
-
conf?: AnyConfigurationModel;
|
|
10
|
-
checked?: boolean;
|
|
11
|
-
isOpenByDefault?: boolean;
|
|
12
|
-
children: TreeNode[];
|
|
13
|
-
};
|
|
14
|
-
export declare function generateHierarchy(model: HierarchicalTrackSelectorModel, trackConfigurations: AnyConfigurationModel[], collapsed: {
|
|
15
|
-
get: (arg: string) => boolean | undefined;
|
|
16
|
-
}, extra?: string): TreeNode[];
|
|
4
|
+
import { TreeNode } from './generateHierarchy';
|
|
17
5
|
/**
|
|
18
6
|
* #stateModel HierarchicalTrackSelectorWidget
|
|
19
7
|
*/
|
|
@@ -26,10 +14,22 @@ export default function stateTreeFactory(pluginManager: PluginManager): import("
|
|
|
26
14
|
* #property
|
|
27
15
|
*/
|
|
28
16
|
type: import("mobx-state-tree").ISimpleType<"HierarchicalTrackSelectorWidget">;
|
|
17
|
+
/**
|
|
18
|
+
* #property
|
|
19
|
+
*/
|
|
20
|
+
initialized: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<boolean>>;
|
|
29
21
|
/**
|
|
30
22
|
* #property
|
|
31
23
|
*/
|
|
32
24
|
collapsed: import("mobx-state-tree").IMapType<import("mobx-state-tree").ISimpleType<boolean>>;
|
|
25
|
+
/**
|
|
26
|
+
* #property
|
|
27
|
+
*/
|
|
28
|
+
sortTrackNames: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<boolean>>;
|
|
29
|
+
/**
|
|
30
|
+
* #property
|
|
31
|
+
*/
|
|
32
|
+
sortCategories: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<boolean>>;
|
|
33
33
|
/**
|
|
34
34
|
* #property
|
|
35
35
|
*/
|
|
@@ -42,6 +42,14 @@ export default function stateTreeFactory(pluginManager: PluginManager): import("
|
|
|
42
42
|
} & import("mobx-state-tree").IStateTreeNode<import("@jbrowse/core/configuration").AnyConfigurationSchemaType>)[];
|
|
43
43
|
filterText: string;
|
|
44
44
|
} & {
|
|
45
|
+
/**
|
|
46
|
+
* #action
|
|
47
|
+
*/
|
|
48
|
+
setSortTrackNames(val: boolean): void;
|
|
49
|
+
/**
|
|
50
|
+
* #action
|
|
51
|
+
*/
|
|
52
|
+
setSortCategories(val: boolean): void;
|
|
45
53
|
/**
|
|
46
54
|
* #action
|
|
47
55
|
*/
|
|
@@ -66,6 +74,14 @@ export default function stateTreeFactory(pluginManager: PluginManager): import("
|
|
|
66
74
|
* #action
|
|
67
75
|
*/
|
|
68
76
|
toggleCategory(pathName: string): void;
|
|
77
|
+
/**
|
|
78
|
+
* #action
|
|
79
|
+
*/
|
|
80
|
+
setCategoryCollapsed(pathName: string, status: boolean): void;
|
|
81
|
+
/**
|
|
82
|
+
* #action
|
|
83
|
+
*/
|
|
84
|
+
expandAllCategories(): void;
|
|
69
85
|
/**
|
|
70
86
|
* #action
|
|
71
87
|
*/
|
|
@@ -85,6 +101,14 @@ export default function stateTreeFactory(pluginManager: PluginManager): import("
|
|
|
85
101
|
*/
|
|
86
102
|
readonly assemblyNames: string[];
|
|
87
103
|
} & {
|
|
104
|
+
/**
|
|
105
|
+
* #getter
|
|
106
|
+
*/
|
|
107
|
+
readonly activeSortTrackNames: any;
|
|
108
|
+
/**
|
|
109
|
+
* #getter
|
|
110
|
+
*/
|
|
111
|
+
readonly activeSortCategories: any;
|
|
88
112
|
/**
|
|
89
113
|
* #method
|
|
90
114
|
* filter out tracks that don't match the current display types
|
|
@@ -105,6 +129,23 @@ export default function stateTreeFactory(pluginManager: PluginManager): import("
|
|
|
105
129
|
} & import("mobx-state-tree/dist/internal").NonEmptyObject & {
|
|
106
130
|
setSubschema(slotName: string, data: unknown): any;
|
|
107
131
|
} & import("mobx-state-tree").IStateTreeNode<import("@jbrowse/core/configuration").AnyConfigurationSchemaType>)[];
|
|
132
|
+
} & {
|
|
133
|
+
/**
|
|
134
|
+
* #method
|
|
135
|
+
*/
|
|
136
|
+
connectionHierarchy(connection: {
|
|
137
|
+
name: string;
|
|
138
|
+
tracks: AnyConfigurationModel[];
|
|
139
|
+
}): TreeNode[];
|
|
140
|
+
} & {
|
|
141
|
+
readonly allTracks: {
|
|
142
|
+
group: any;
|
|
143
|
+
tracks: ({
|
|
144
|
+
[x: string]: any;
|
|
145
|
+
} & import("mobx-state-tree/dist/internal").NonEmptyObject & {
|
|
146
|
+
setSubschema(slotName: string, data: unknown): any;
|
|
147
|
+
} & import("mobx-state-tree").IStateTreeNode<import("@jbrowse/core/configuration").AnyConfigurationSchemaType>)[];
|
|
148
|
+
}[];
|
|
108
149
|
} & {
|
|
109
150
|
/**
|
|
110
151
|
* #getter
|
|
@@ -112,26 +153,25 @@ export default function stateTreeFactory(pluginManager: PluginManager): import("
|
|
|
112
153
|
readonly hierarchy: {
|
|
113
154
|
name: string;
|
|
114
155
|
id: string;
|
|
115
|
-
children:
|
|
116
|
-
id: any;
|
|
156
|
+
children: {
|
|
117
157
|
name: any;
|
|
158
|
+
id: any;
|
|
118
159
|
children: TreeNode[];
|
|
119
|
-
|
|
120
|
-
expanded: boolean;
|
|
121
|
-
};
|
|
122
|
-
} | {
|
|
123
|
-
name: string;
|
|
124
|
-
id: string;
|
|
125
|
-
children: TreeNode[];
|
|
126
|
-
})[];
|
|
160
|
+
}[];
|
|
127
161
|
};
|
|
162
|
+
} & {
|
|
128
163
|
/**
|
|
129
|
-
* #
|
|
164
|
+
* #action
|
|
130
165
|
*/
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
166
|
+
collapseSubCategories(): void;
|
|
167
|
+
/**
|
|
168
|
+
* #action
|
|
169
|
+
*/
|
|
170
|
+
collapseTopLevelCategories(): void;
|
|
171
|
+
} & {
|
|
172
|
+
afterCreate(): void;
|
|
173
|
+
} & {
|
|
174
|
+
readonly hasAnySubcategories: boolean;
|
|
135
175
|
}, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>;
|
|
136
176
|
export type HierarchicalTrackSelectorStateModel = ReturnType<typeof stateTreeFactory>;
|
|
137
177
|
export type HierarchicalTrackSelectorModel = Instance<HierarchicalTrackSelectorStateModel>;
|