@jbrowse/plugin-data-management 4.1.12 → 4.1.14
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/HierarchicalTrackSelectorWidget/components/ClearableSearchField.js +1 -1
- package/esm/HierarchicalTrackSelectorWidget/components/faceted/FacetFilter.js +6 -10
- package/esm/HierarchicalTrackSelectorWidget/components/faceted/FacetFilters.js +10 -17
- package/esm/HierarchicalTrackSelectorWidget/components/faceted/FacetedDataGrid.d.ts +2 -1
- package/esm/HierarchicalTrackSelectorWidget/components/faceted/FacetedDataGrid.js +18 -9
- package/esm/HierarchicalTrackSelectorWidget/components/faceted/FacetedHeader.d.ts +3 -2
- package/esm/HierarchicalTrackSelectorWidget/components/faceted/FacetedHeader.js +5 -3
- package/esm/HierarchicalTrackSelectorWidget/components/faceted/FacetedSelector.d.ts +0 -6
- package/esm/HierarchicalTrackSelectorWidget/components/faceted/FacetedSelector.js +9 -13
- package/esm/HierarchicalTrackSelectorWidget/facetedModel.d.ts +20 -4
- package/esm/HierarchicalTrackSelectorWidget/facetedModel.js +22 -11
- package/esm/HierarchicalTrackSelectorWidget/facetedUtil.d.ts +1 -1
- package/esm/HierarchicalTrackSelectorWidget/facetedUtil.js +17 -5
- package/esm/HierarchicalTrackSelectorWidget/model.d.ts +20 -4
- package/esm/HierarchicalTrackSelectorWidget/util.js +4 -2
- package/package.json +5 -5
|
@@ -16,7 +16,7 @@ export default function ClearableSearchField({ value, onChange, label, className
|
|
|
16
16
|
startTransition(() => {
|
|
17
17
|
onChange(newValue);
|
|
18
18
|
});
|
|
19
|
-
},
|
|
19
|
+
}, slotProps: {
|
|
20
20
|
input: {
|
|
21
21
|
endAdornment: (_jsx(InputAdornment, { position: "end", children: _jsx(IconButton, { onClick: () => {
|
|
22
22
|
setLocalValue('');
|
|
@@ -17,14 +17,10 @@ const useStyles = makeStyles()(theme => ({
|
|
|
17
17
|
},
|
|
18
18
|
}));
|
|
19
19
|
function ClearButton({ onClick }) {
|
|
20
|
-
return (_jsx(Tooltip, { title: "Clear selection on this facet filter", children: _jsx(IconButton, { onClick: ()
|
|
21
|
-
onClick();
|
|
22
|
-
}, size: "small", children: _jsx(ClearIcon, {}) }) }));
|
|
20
|
+
return (_jsx(Tooltip, { title: "Clear selection on this facet filter", children: _jsx(IconButton, { onClick: onClick, size: "small", children: _jsx(ClearIcon, {}) }) }));
|
|
23
21
|
}
|
|
24
22
|
function ExpandButton({ visible, onClick, }) {
|
|
25
|
-
return (_jsx(Tooltip, { title: "Minimize/expand this facet filter", children: _jsx(IconButton, { onClick: ()
|
|
26
|
-
onClick();
|
|
27
|
-
}, size: "small", children: visible ? _jsx(MinimizeIcon, {}) : _jsx(AddIcon, {}) }) }));
|
|
23
|
+
return (_jsx(Tooltip, { title: "Minimize/expand this facet filter", children: _jsx(IconButton, { onClick: onClick, size: "small", children: visible ? _jsx(MinimizeIcon, {}) : _jsx(AddIcon, {}) }) }));
|
|
28
24
|
}
|
|
29
25
|
const FacetFilter = observer(function FacetFilter({ column, vals, model, }) {
|
|
30
26
|
const { classes } = useStyles();
|
|
@@ -37,11 +33,11 @@ const FacetFilter = observer(function FacetFilter({ column, vals, model, }) {
|
|
|
37
33
|
} }), _jsx(ExpandButton, { visible: visible, onClick: () => {
|
|
38
34
|
setVisible(!visible);
|
|
39
35
|
} })] }), visible ? (_jsx(Select, { multiple: true, native: true, className: classes.select, value: filters.get(column.field) || [], onChange: event => {
|
|
40
|
-
|
|
41
|
-
.
|
|
42
|
-
|
|
36
|
+
const options = event.target
|
|
37
|
+
.options;
|
|
38
|
+
faceted.setFilter(column.field, [...options].filter(opt => opt.selected).map(opt => opt.value));
|
|
43
39
|
}, children: vals
|
|
44
|
-
.
|
|
40
|
+
.toSorted((a, b) => a[0].localeCompare(b[0]))
|
|
45
41
|
.map(([name, count]) => (_jsxs("option", { value: name, children: [coarseStripHTML(name), " (", count, ")"] }, name))) })) : null] }));
|
|
46
42
|
});
|
|
47
43
|
export default FacetFilter;
|
|
@@ -6,17 +6,15 @@ const FacetFilters = observer(function FacetFilters({ rows, columns, model, }) {
|
|
|
6
6
|
const { faceted } = model;
|
|
7
7
|
const { filters } = faceted;
|
|
8
8
|
const facets = columns.slice(1);
|
|
9
|
-
const facetFieldToCategoryCountMap = new Map(
|
|
10
|
-
const filterKeys = faceted.filters.keys();
|
|
11
|
-
const facetKeys = facets.map(f => f.field);
|
|
9
|
+
const facetFieldToCategoryCountMap = new Map(facets.map(f => [f.field, new Map()]));
|
|
12
10
|
const facetKeysPrioritizingUserSelections = new Set();
|
|
13
|
-
for (const entry of
|
|
11
|
+
for (const entry of filters.keys()) {
|
|
14
12
|
if (filters.get(entry)?.length) {
|
|
15
13
|
facetKeysPrioritizingUserSelections.add(entry);
|
|
16
14
|
}
|
|
17
15
|
}
|
|
18
|
-
for (const
|
|
19
|
-
facetKeysPrioritizingUserSelections.add(
|
|
16
|
+
for (const f of facets) {
|
|
17
|
+
facetKeysPrioritizingUserSelections.add(f.field);
|
|
20
18
|
}
|
|
21
19
|
let currentRows = rows;
|
|
22
20
|
for (const facetKey of facetKeysPrioritizingUserSelections) {
|
|
@@ -24,21 +22,16 @@ const FacetFilters = observer(function FacetFilters({ rows, columns, model, }) {
|
|
|
24
22
|
if (categoryCountMap) {
|
|
25
23
|
for (const row of currentRows) {
|
|
26
24
|
const key = getRowStr(facetKey, row);
|
|
27
|
-
const currentCount = categoryCountMap.get(key);
|
|
28
25
|
if (key) {
|
|
29
|
-
|
|
30
|
-
categoryCountMap.set(key, 1);
|
|
31
|
-
}
|
|
32
|
-
else {
|
|
33
|
-
categoryCountMap.set(key, currentCount + 1);
|
|
34
|
-
}
|
|
26
|
+
categoryCountMap.set(key, (categoryCountMap.get(key) ?? 0) + 1);
|
|
35
27
|
}
|
|
36
28
|
}
|
|
37
29
|
}
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
30
|
+
const filterValues = filters.get(facetKey);
|
|
31
|
+
if (filterValues?.length) {
|
|
32
|
+
const filterSet = new Set(filterValues);
|
|
33
|
+
currentRows = currentRows.filter(row => filterSet.has(getRowStr(facetKey, row)));
|
|
34
|
+
}
|
|
42
35
|
}
|
|
43
36
|
return (_jsx("div", { children: facets.map(c => (_jsx(FacetFilter, { vals: [...facetFieldToCategoryCountMap.get(c.field)], column: c, model: model }, c.field))) }));
|
|
44
37
|
});
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import type { HierarchicalTrackSelectorModel } from '../../model.ts';
|
|
2
|
+
import type { AnyConfigurationModel } from '@jbrowse/core/configuration';
|
|
2
3
|
import type { GridColDef, GridRowId } from '@mui/x-data-grid';
|
|
3
4
|
declare const FacetedDataGrid: ({ model, columns, shownTrackIds, selection, }: {
|
|
4
5
|
model: HierarchicalTrackSelectorModel;
|
|
5
6
|
columns: GridColDef[];
|
|
6
7
|
shownTrackIds: Set<GridRowId>;
|
|
7
|
-
selection:
|
|
8
|
+
selection: AnyConfigurationModel[];
|
|
8
9
|
}) => import("react/jsx-runtime").JSX.Element;
|
|
9
10
|
export default FacetedDataGrid;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { useMemo, useState, useTransition } from 'react';
|
|
2
|
+
import { useEffect, useMemo, useState, useTransition } from 'react';
|
|
3
3
|
import { notEmpty } from '@jbrowse/core/util';
|
|
4
4
|
import { DataGrid } from '@mui/x-data-grid';
|
|
5
5
|
import { transaction } from 'mobx';
|
|
@@ -10,6 +10,12 @@ const FacetedDataGrid = observer(function FacetedDataGrid({ model, columns, show
|
|
|
10
10
|
const { rows, useShoppingCart, showOptions, filteredRows, filteredNonMetadataKeys, filteredMetadataKeys, visible, } = faceted;
|
|
11
11
|
const [, startTransition] = useTransition();
|
|
12
12
|
const [widths, setWidths] = useState(() => computeInitialWidths(rows, filteredNonMetadataKeys, filteredMetadataKeys, visible));
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
setWidths(prev => ({
|
|
15
|
+
...computeInitialWidths(rows, filteredNonMetadataKeys, filteredMetadataKeys, visible),
|
|
16
|
+
...prev,
|
|
17
|
+
}));
|
|
18
|
+
}, [rows, filteredNonMetadataKeys, filteredMetadataKeys, visible]);
|
|
13
19
|
const rowSelectionModel = useMemo(() => ({
|
|
14
20
|
type: 'include',
|
|
15
21
|
ids: new Set(useShoppingCart ? selection.map(s => s.trackId) : [...shownTrackIds]),
|
|
@@ -31,14 +37,17 @@ const FacetedDataGrid = observer(function FacetedDataGrid({ model, columns, show
|
|
|
31
37
|
const a1 = shownTrackIds;
|
|
32
38
|
const a2 = userSelectedIds.ids;
|
|
33
39
|
transaction(() => {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
for (const t of a1) {
|
|
41
|
+
if (!a2.has(t)) {
|
|
42
|
+
view.hideTrack(t);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
for (const t of a2) {
|
|
46
|
+
if (!a1.has(t)) {
|
|
47
|
+
view.showTrack(t);
|
|
48
|
+
model.addToRecentlyUsed(t);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
42
51
|
});
|
|
43
52
|
}
|
|
44
53
|
else {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { HierarchicalTrackSelectorModel } from '../../model.ts';
|
|
2
|
-
|
|
2
|
+
declare const FacetedHeader: ({ model, }: {
|
|
3
3
|
model: HierarchicalTrackSelectorModel;
|
|
4
|
-
})
|
|
4
|
+
}) => import("react/jsx-runtime").JSX.Element;
|
|
5
|
+
export default FacetedHeader;
|
|
@@ -3,13 +3,14 @@ import { useState } from 'react';
|
|
|
3
3
|
import { Menu } from '@jbrowse/core/ui';
|
|
4
4
|
import MoreVert from '@mui/icons-material/MoreVert';
|
|
5
5
|
import { Grid, IconButton } from '@mui/material';
|
|
6
|
+
import { observer } from 'mobx-react';
|
|
6
7
|
import ClearableSearchField from "../ClearableSearchField.js";
|
|
7
8
|
import ShoppingCart from "../ShoppingCart.js";
|
|
8
|
-
|
|
9
|
+
const FacetedHeader = observer(function FacetedHeader({ model, }) {
|
|
9
10
|
const { faceted } = model;
|
|
10
11
|
const { filterText, showOptions, showFilters, showSparse, useShoppingCart } = faceted;
|
|
11
12
|
const [anchorEl, setAnchorEl] = useState(null);
|
|
12
|
-
return (_jsxs(_Fragment, { children: [_jsxs(Grid, { container: true,
|
|
13
|
+
return (_jsxs(_Fragment, { children: [_jsxs(Grid, { container: true, alignItems: "center", children: [_jsx(ClearableSearchField, { label: "Search...", value: filterText, onChange: value => {
|
|
13
14
|
faceted.setFilterText(value);
|
|
14
15
|
} }), _jsx(IconButton, { onClick: event => {
|
|
15
16
|
setAnchorEl(event.currentTarget);
|
|
@@ -52,4 +53,5 @@ export default function FacetedHeader({ model, }) {
|
|
|
52
53
|
type: 'checkbox',
|
|
53
54
|
},
|
|
54
55
|
] })] }));
|
|
55
|
-
}
|
|
56
|
+
});
|
|
57
|
+
export default FacetedHeader;
|
|
@@ -1,10 +1,4 @@
|
|
|
1
1
|
import type { HierarchicalTrackSelectorModel } from '../../model.ts';
|
|
2
|
-
import type { AnyConfigurationModel } from '@jbrowse/core/configuration';
|
|
3
|
-
export interface InfoArgs {
|
|
4
|
-
target: HTMLElement;
|
|
5
|
-
id: string;
|
|
6
|
-
conf: AnyConfigurationModel;
|
|
7
|
-
}
|
|
8
2
|
declare const FacetedSelector: ({ model, }: {
|
|
9
3
|
model: HierarchicalTrackSelectorModel;
|
|
10
4
|
}) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -21,7 +21,7 @@ const useStyles = makeStyles()({
|
|
|
21
21
|
});
|
|
22
22
|
function HighlightText({ text, query, className, }) {
|
|
23
23
|
if (!query || !text) {
|
|
24
|
-
return _jsx(
|
|
24
|
+
return _jsx(SanitizedHTML, { html: text, className: className });
|
|
25
25
|
}
|
|
26
26
|
const lowerText = text.toLowerCase();
|
|
27
27
|
const lowerQuery = query.toLowerCase();
|
|
@@ -42,10 +42,14 @@ function HighlightText({ text, query, className, }) {
|
|
|
42
42
|
return _jsx("span", { className: className, children: parts });
|
|
43
43
|
}
|
|
44
44
|
const frac = 0.75;
|
|
45
|
+
function HighlightCell({ value, filterText, className, }) {
|
|
46
|
+
return value ? (_jsx(HighlightText, { className: className, text: value, query: filterText })) : ('');
|
|
47
|
+
}
|
|
45
48
|
const FacetedSelector = observer(function FacetedSelector({ model, }) {
|
|
46
49
|
const { classes } = useStyles();
|
|
47
50
|
const { selection, shownTrackIds, faceted } = model;
|
|
48
51
|
const { rows, panelWidth, showFilters, filterText, filteredNonMetadataKeys, filteredMetadataKeys, } = faceted;
|
|
52
|
+
const nonMetadataFieldSet = new Set(['name', ...filteredNonMetadataKeys]);
|
|
49
53
|
const columns = [
|
|
50
54
|
{
|
|
51
55
|
field: 'name',
|
|
@@ -53,29 +57,21 @@ const FacetedSelector = observer(function FacetedSelector({ model, }) {
|
|
|
53
57
|
renderCell: params => {
|
|
54
58
|
const { value, row } = params;
|
|
55
59
|
const { id, conf } = row;
|
|
56
|
-
return (_jsxs("div", { className: classes.cell, children: [_jsx(
|
|
60
|
+
return (_jsxs("div", { className: classes.cell, children: [_jsx(HighlightText, { text: value, query: filterText }), _jsx(TrackSelectorTrackMenu, { id: id, conf: conf, model: model })] }));
|
|
57
61
|
},
|
|
58
62
|
},
|
|
59
63
|
...filteredNonMetadataKeys.map(e => {
|
|
60
64
|
return {
|
|
61
65
|
field: e,
|
|
62
|
-
renderCell: params => {
|
|
63
|
-
const val = params.value;
|
|
64
|
-
return val ? (_jsx(HighlightText, { className: classes.cell, text: val, query: filterText })) : ('');
|
|
65
|
-
},
|
|
66
|
+
renderCell: (params) => (_jsx(HighlightCell, { value: params.value, filterText: filterText, className: classes.cell })),
|
|
66
67
|
};
|
|
67
68
|
}),
|
|
68
69
|
...filteredMetadataKeys.map(e => {
|
|
69
70
|
return {
|
|
70
71
|
field: `metadata.${e}`,
|
|
71
|
-
headerName:
|
|
72
|
-
? `${e} (from metadata)`
|
|
73
|
-
: e,
|
|
72
|
+
headerName: nonMetadataFieldSet.has(e) ? `${e} (from metadata)` : e,
|
|
74
73
|
valueGetter: (_, row) => `${row.metadata[e] ?? ''}`,
|
|
75
|
-
renderCell: params => {
|
|
76
|
-
const val = params.value;
|
|
77
|
-
return val ? (_jsx(HighlightText, { className: classes.cell, text: val, query: filterText })) : ('');
|
|
78
|
-
},
|
|
74
|
+
renderCell: (params) => (_jsx(HighlightCell, { value: params.value, filterText: filterText, className: classes.cell })),
|
|
79
75
|
};
|
|
80
76
|
}),
|
|
81
77
|
];
|
|
@@ -26,6 +26,22 @@ export declare function facetedStateTreeF(): import("@jbrowse/mobx-state-tree").
|
|
|
26
26
|
[x: string]: any;
|
|
27
27
|
} & import("@jbrowse/mobx-state-tree/dist/internal").NonEmptyObject & any & import("@jbrowse/mobx-state-tree").IStateTreeNode<import("@jbrowse/core/configuration").AnyConfigurationSchemaType>);
|
|
28
28
|
} & import("@jbrowse/mobx-state-tree").IStateTreeNode<import("@jbrowse/core/configuration").AnyConfigurationSchemaType>)[];
|
|
29
|
+
} & {
|
|
30
|
+
readonly allRows: {
|
|
31
|
+
readonly id: string;
|
|
32
|
+
readonly conf: {
|
|
33
|
+
[x: string]: any;
|
|
34
|
+
} & import("@jbrowse/mobx-state-tree/dist/internal").NonEmptyObject & {
|
|
35
|
+
setSubschema(slotName: string, data: Record<string, unknown>): Record<string, unknown> | ({
|
|
36
|
+
[x: string]: any;
|
|
37
|
+
} & import("@jbrowse/mobx-state-tree/dist/internal").NonEmptyObject & any & import("@jbrowse/mobx-state-tree").IStateTreeNode<import("@jbrowse/core/configuration").AnyConfigurationSchemaType>);
|
|
38
|
+
} & import("@jbrowse/mobx-state-tree").IStateTreeNode<import("@jbrowse/core/configuration").AnyConfigurationSchemaType>;
|
|
39
|
+
readonly name: string;
|
|
40
|
+
readonly category: any;
|
|
41
|
+
readonly adapter: string;
|
|
42
|
+
readonly description: string | undefined;
|
|
43
|
+
readonly metadata: Record<string, unknown>;
|
|
44
|
+
}[];
|
|
29
45
|
} & {
|
|
30
46
|
readonly rows: {
|
|
31
47
|
readonly id: string;
|
|
@@ -37,9 +53,9 @@ export declare function facetedStateTreeF(): import("@jbrowse/mobx-state-tree").
|
|
|
37
53
|
} & import("@jbrowse/mobx-state-tree/dist/internal").NonEmptyObject & any & import("@jbrowse/mobx-state-tree").IStateTreeNode<import("@jbrowse/core/configuration").AnyConfigurationSchemaType>);
|
|
38
54
|
} & import("@jbrowse/mobx-state-tree").IStateTreeNode<import("@jbrowse/core/configuration").AnyConfigurationSchemaType>;
|
|
39
55
|
readonly name: string;
|
|
40
|
-
readonly category:
|
|
56
|
+
readonly category: any;
|
|
41
57
|
readonly adapter: string;
|
|
42
|
-
readonly description: string;
|
|
58
|
+
readonly description: string | undefined;
|
|
43
59
|
readonly metadata: Record<string, unknown>;
|
|
44
60
|
}[];
|
|
45
61
|
} & {
|
|
@@ -57,9 +73,9 @@ export declare function facetedStateTreeF(): import("@jbrowse/mobx-state-tree").
|
|
|
57
73
|
} & import("@jbrowse/mobx-state-tree/dist/internal").NonEmptyObject & any & import("@jbrowse/mobx-state-tree").IStateTreeNode<import("@jbrowse/core/configuration").AnyConfigurationSchemaType>);
|
|
58
74
|
} & import("@jbrowse/mobx-state-tree").IStateTreeNode<import("@jbrowse/core/configuration").AnyConfigurationSchemaType>;
|
|
59
75
|
readonly name: string;
|
|
60
|
-
readonly category:
|
|
76
|
+
readonly category: any;
|
|
61
77
|
readonly adapter: string;
|
|
62
|
-
readonly description: string;
|
|
78
|
+
readonly description: string | undefined;
|
|
63
79
|
readonly metadata: Record<string, unknown>;
|
|
64
80
|
}[];
|
|
65
81
|
} & {
|
|
@@ -5,7 +5,6 @@ import { addDisposer, getParent, types } from '@jbrowse/mobx-state-tree';
|
|
|
5
5
|
import { autorun, observable } from 'mobx';
|
|
6
6
|
import { getRowStr } from "./components/faceted/util.js";
|
|
7
7
|
import { findNonSparseKeys, getRootKeys } from "./facetedUtil.js";
|
|
8
|
-
import { matches, matchesMetadata } from "./util.js";
|
|
9
8
|
const nonMetadataKeys = ['category', 'adapter', 'description'];
|
|
10
9
|
export function facetedStateTreeF() {
|
|
11
10
|
return types
|
|
@@ -54,36 +53,48 @@ export function facetedStateTreeF() {
|
|
|
54
53
|
},
|
|
55
54
|
}))
|
|
56
55
|
.views(self => ({
|
|
57
|
-
get
|
|
56
|
+
get allRows() {
|
|
58
57
|
const session = getSession(self);
|
|
59
|
-
|
|
60
|
-
return allTrackConfigurations
|
|
61
|
-
.filter(conf => matches(filterText, conf, session) ||
|
|
62
|
-
matchesMetadata(filterText, conf))
|
|
63
|
-
.map(track => ({
|
|
58
|
+
return self.allTrackConfigurations.map(track => ({
|
|
64
59
|
id: track.trackId,
|
|
65
60
|
conf: track,
|
|
66
61
|
name: getTrackName(track, session),
|
|
67
62
|
category: readConfObject(track, 'category')?.join(', '),
|
|
68
63
|
adapter: readConfObject(track, 'adapter')?.type,
|
|
69
64
|
description: readConfObject(track, 'description'),
|
|
70
|
-
metadata: (track
|
|
65
|
+
metadata: (readConfObject(track, 'metadata') || {}),
|
|
71
66
|
}));
|
|
72
67
|
},
|
|
68
|
+
}))
|
|
69
|
+
.views(self => ({
|
|
70
|
+
get rows() {
|
|
71
|
+
const queryLower = self.filterText.toLowerCase();
|
|
72
|
+
if (!queryLower) {
|
|
73
|
+
return self.allRows;
|
|
74
|
+
}
|
|
75
|
+
return self.allRows.filter(row => row.name.toLowerCase().includes(queryLower) ||
|
|
76
|
+
row.category?.toLowerCase().includes(queryLower) ||
|
|
77
|
+
row.description?.toLowerCase().includes(queryLower) ||
|
|
78
|
+
Object.values(row.metadata).some(v => v !== null &&
|
|
79
|
+
v !== undefined &&
|
|
80
|
+
`${v}`.toLowerCase().includes(queryLower)));
|
|
81
|
+
},
|
|
73
82
|
}))
|
|
74
83
|
.views(self => ({
|
|
75
84
|
get filteredNonMetadataKeys() {
|
|
76
85
|
return self.showSparse
|
|
77
86
|
? nonMetadataKeys
|
|
78
|
-
: findNonSparseKeys(nonMetadataKeys, self.
|
|
87
|
+
: findNonSparseKeys(nonMetadataKeys, self.allRows, (r, f) => r[f]);
|
|
79
88
|
},
|
|
80
89
|
get metadataKeys() {
|
|
81
|
-
return [
|
|
90
|
+
return [
|
|
91
|
+
...new Set(self.allRows.flatMap(row => getRootKeys(row.metadata))),
|
|
92
|
+
];
|
|
82
93
|
},
|
|
83
94
|
get filteredMetadataKeys() {
|
|
84
95
|
return self.showSparse
|
|
85
96
|
? this.metadataKeys
|
|
86
|
-
: findNonSparseKeys(this.metadataKeys, self.
|
|
97
|
+
: findNonSparseKeys(this.metadataKeys, self.allRows, (r, f) => r.metadata[f]);
|
|
87
98
|
},
|
|
88
99
|
get fields() {
|
|
89
100
|
return [
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare function findNonSparseKeys(keys: readonly string[], rows:
|
|
1
|
+
export declare function findNonSparseKeys<T>(keys: readonly string[], rows: T[], cb: (row: T, f: string) => unknown, threshold?: number): string[];
|
|
2
2
|
export declare function getRootKeys(obj: Record<string, unknown>): string[];
|
|
@@ -1,8 +1,20 @@
|
|
|
1
|
-
export function findNonSparseKeys(keys, rows, cb) {
|
|
2
|
-
return keys.filter(key =>
|
|
1
|
+
export function findNonSparseKeys(keys, rows, cb, threshold = 5) {
|
|
2
|
+
return keys.filter(key => {
|
|
3
|
+
let count = 0;
|
|
4
|
+
for (const row of rows) {
|
|
5
|
+
if (cb(row, key)) {
|
|
6
|
+
count++;
|
|
7
|
+
if (count > threshold) {
|
|
8
|
+
return true;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
return false;
|
|
13
|
+
});
|
|
3
14
|
}
|
|
4
15
|
export function getRootKeys(obj) {
|
|
5
|
-
return Object.
|
|
6
|
-
|
|
7
|
-
|
|
16
|
+
return Object.keys(obj).filter(key => {
|
|
17
|
+
const val = obj[key];
|
|
18
|
+
return val !== null && val !== undefined && typeof val !== 'object';
|
|
19
|
+
});
|
|
8
20
|
}
|
|
@@ -37,6 +37,22 @@ export default function stateTreeFactory(pluginManager: PluginManager): import("
|
|
|
37
37
|
[x: string]: any;
|
|
38
38
|
} & import("@jbrowse/mobx-state-tree/dist/internal").NonEmptyObject & any & import("@jbrowse/mobx-state-tree").IStateTreeNode<import("@jbrowse/core/configuration").AnyConfigurationSchemaType>);
|
|
39
39
|
} & import("@jbrowse/mobx-state-tree").IStateTreeNode<import("@jbrowse/core/configuration").AnyConfigurationSchemaType>)[];
|
|
40
|
+
} & {
|
|
41
|
+
readonly allRows: {
|
|
42
|
+
readonly id: string;
|
|
43
|
+
readonly conf: {
|
|
44
|
+
[x: string]: any;
|
|
45
|
+
} & import("@jbrowse/mobx-state-tree/dist/internal").NonEmptyObject & {
|
|
46
|
+
setSubschema(slotName: string, data: Record<string, unknown>): Record<string, unknown> | ({
|
|
47
|
+
[x: string]: any;
|
|
48
|
+
} & import("@jbrowse/mobx-state-tree/dist/internal").NonEmptyObject & any & import("@jbrowse/mobx-state-tree").IStateTreeNode<import("@jbrowse/core/configuration").AnyConfigurationSchemaType>);
|
|
49
|
+
} & import("@jbrowse/mobx-state-tree").IStateTreeNode<import("@jbrowse/core/configuration").AnyConfigurationSchemaType>;
|
|
50
|
+
readonly name: string;
|
|
51
|
+
readonly category: any;
|
|
52
|
+
readonly adapter: string;
|
|
53
|
+
readonly description: string | undefined;
|
|
54
|
+
readonly metadata: Record<string, unknown>;
|
|
55
|
+
}[];
|
|
40
56
|
} & {
|
|
41
57
|
readonly rows: {
|
|
42
58
|
readonly id: string;
|
|
@@ -48,9 +64,9 @@ export default function stateTreeFactory(pluginManager: PluginManager): import("
|
|
|
48
64
|
} & import("@jbrowse/mobx-state-tree/dist/internal").NonEmptyObject & any & import("@jbrowse/mobx-state-tree").IStateTreeNode<import("@jbrowse/core/configuration").AnyConfigurationSchemaType>);
|
|
49
65
|
} & import("@jbrowse/mobx-state-tree").IStateTreeNode<import("@jbrowse/core/configuration").AnyConfigurationSchemaType>;
|
|
50
66
|
readonly name: string;
|
|
51
|
-
readonly category:
|
|
67
|
+
readonly category: any;
|
|
52
68
|
readonly adapter: string;
|
|
53
|
-
readonly description: string;
|
|
69
|
+
readonly description: string | undefined;
|
|
54
70
|
readonly metadata: Record<string, unknown>;
|
|
55
71
|
}[];
|
|
56
72
|
} & {
|
|
@@ -68,9 +84,9 @@ export default function stateTreeFactory(pluginManager: PluginManager): import("
|
|
|
68
84
|
} & import("@jbrowse/mobx-state-tree/dist/internal").NonEmptyObject & any & import("@jbrowse/mobx-state-tree").IStateTreeNode<import("@jbrowse/core/configuration").AnyConfigurationSchemaType>);
|
|
69
85
|
} & import("@jbrowse/mobx-state-tree").IStateTreeNode<import("@jbrowse/core/configuration").AnyConfigurationSchemaType>;
|
|
70
86
|
readonly name: string;
|
|
71
|
-
readonly category:
|
|
87
|
+
readonly category: any;
|
|
72
88
|
readonly adapter: string;
|
|
73
|
-
readonly description: string;
|
|
89
|
+
readonly description: string | undefined;
|
|
74
90
|
readonly metadata: Record<string, unknown>;
|
|
75
91
|
}[];
|
|
76
92
|
} & {
|
|
@@ -22,9 +22,11 @@ export function matches(query, conf, session) {
|
|
|
22
22
|
export function matchesMetadata(query, conf) {
|
|
23
23
|
const queryLower = query.toLowerCase();
|
|
24
24
|
const description = (readConfObject(conf, 'description') || '');
|
|
25
|
-
const metadata = (conf
|
|
25
|
+
const metadata = (readConfObject(conf, 'metadata') || {});
|
|
26
26
|
return (description.toLowerCase().includes(queryLower) ||
|
|
27
|
-
Object.values(metadata).some(v =>
|
|
27
|
+
Object.values(metadata).some(v => v !== null &&
|
|
28
|
+
v !== undefined &&
|
|
29
|
+
`${v}`.toLowerCase().includes(queryLower)));
|
|
28
30
|
}
|
|
29
31
|
export function findSubCategories(obj, paths, depth = 0) {
|
|
30
32
|
let hasSubs = false;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jbrowse/plugin-data-management",
|
|
3
|
-
"version": "4.1.
|
|
3
|
+
"version": "4.1.14",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "JBrowse 2 linear genome view",
|
|
6
6
|
"keywords": [
|
|
@@ -25,13 +25,13 @@
|
|
|
25
25
|
"@jbrowse/mobx-state-tree": "^5.5.0",
|
|
26
26
|
"@mui/icons-material": "^7.3.8",
|
|
27
27
|
"@mui/material": "^7.3.8",
|
|
28
|
-
"@mui/x-data-grid": "^8.27.
|
|
28
|
+
"@mui/x-data-grid": "^8.27.3",
|
|
29
29
|
"deepmerge": "^4.3.1",
|
|
30
30
|
"mobx": "^6.15.0",
|
|
31
31
|
"mobx-react": "^9.2.1",
|
|
32
|
-
"@jbrowse/
|
|
33
|
-
"@jbrowse/plugin-config": "^4.1.
|
|
34
|
-
"@jbrowse/core": "^4.1.
|
|
32
|
+
"@jbrowse/core": "^4.1.14",
|
|
33
|
+
"@jbrowse/plugin-config": "^4.1.14",
|
|
34
|
+
"@jbrowse/product-core": "^4.1.14"
|
|
35
35
|
},
|
|
36
36
|
"peerDependencies": {
|
|
37
37
|
"react": ">=18.0.0"
|