@jbrowse/plugin-grid-bookmark 2.6.2 → 2.7.0
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/GridBookmarkWidget/components/AssemblySelector.d.ts +3 -4
- package/dist/GridBookmarkWidget/components/AssemblySelector.js +27 -37
- package/dist/GridBookmarkWidget/components/BookmarkGrid.d.ts +6 -0
- package/dist/GridBookmarkWidget/components/BookmarkGrid.js +120 -0
- package/dist/GridBookmarkWidget/components/{ClearBookmarks.d.ts → DeleteBookmarks.d.ts} +2 -3
- package/dist/GridBookmarkWidget/components/DeleteBookmarks.js +41 -0
- package/dist/GridBookmarkWidget/components/DeleteBookmarksDialog.d.ts +7 -0
- package/dist/GridBookmarkWidget/components/DeleteBookmarksDialog.js +29 -0
- package/dist/GridBookmarkWidget/components/EditBookmarkLabelDialog.d.ts +8 -0
- package/dist/GridBookmarkWidget/components/EditBookmarkLabelDialog.js +50 -0
- package/dist/GridBookmarkWidget/components/ExportBookmarks.d.ts +6 -0
- package/dist/GridBookmarkWidget/components/{ClearBookmarks.js → ExportBookmarks.js} +9 -19
- package/dist/GridBookmarkWidget/components/ExportBookmarksDialog.d.ts +7 -0
- package/dist/GridBookmarkWidget/components/{DownloadBookmarks.js → ExportBookmarksDialog.js} +22 -20
- package/dist/GridBookmarkWidget/components/GridBookmarkWidget.d.ts +3 -4
- package/dist/GridBookmarkWidget/components/GridBookmarkWidget.js +28 -97
- package/dist/GridBookmarkWidget/components/ImportBookmarks.d.ts +3 -5
- package/dist/GridBookmarkWidget/components/ImportBookmarks.js +8 -64
- package/dist/GridBookmarkWidget/components/ImportBookmarksDialog.d.ts +7 -0
- package/dist/GridBookmarkWidget/components/ImportBookmarksDialog.js +129 -0
- package/{esm/GridBookmarkWidget/components/ClearBookmarks.d.ts → dist/GridBookmarkWidget/components/ShareBookmarks.d.ts} +2 -3
- package/dist/GridBookmarkWidget/components/ShareBookmarks.js +37 -0
- package/dist/GridBookmarkWidget/components/ShareBookmarksDialog.d.ts +7 -0
- package/dist/GridBookmarkWidget/components/ShareBookmarksDialog.js +106 -0
- package/dist/GridBookmarkWidget/model.d.ts +178 -11
- package/dist/GridBookmarkWidget/model.js +105 -27
- package/dist/GridBookmarkWidget/sessionSharing.d.ts +6 -0
- package/dist/GridBookmarkWidget/sessionSharing.js +96 -0
- package/dist/GridBookmarkWidget/utils.d.ts +19 -3
- package/dist/GridBookmarkWidget/utils.js +132 -40
- package/dist/index.d.ts +1 -1
- package/dist/index.js +100 -75
- package/esm/GridBookmarkWidget/components/AssemblySelector.d.ts +3 -4
- package/esm/GridBookmarkWidget/components/AssemblySelector.js +28 -38
- package/esm/GridBookmarkWidget/components/BookmarkGrid.d.ts +6 -0
- package/esm/GridBookmarkWidget/components/BookmarkGrid.js +92 -0
- package/{dist/GridBookmarkWidget/components/DownloadBookmarks.d.ts → esm/GridBookmarkWidget/components/DeleteBookmarks.d.ts} +2 -3
- package/esm/GridBookmarkWidget/components/DeleteBookmarks.js +13 -0
- package/esm/GridBookmarkWidget/components/DeleteBookmarksDialog.d.ts +7 -0
- package/esm/GridBookmarkWidget/components/DeleteBookmarksDialog.js +24 -0
- package/esm/GridBookmarkWidget/components/EditBookmarkLabelDialog.d.ts +8 -0
- package/esm/GridBookmarkWidget/components/EditBookmarkLabelDialog.js +25 -0
- package/esm/GridBookmarkWidget/components/ExportBookmarks.d.ts +6 -0
- package/esm/GridBookmarkWidget/components/ExportBookmarks.js +13 -0
- package/esm/GridBookmarkWidget/components/ExportBookmarksDialog.d.ts +7 -0
- package/esm/GridBookmarkWidget/components/ExportBookmarksDialog.js +35 -0
- package/esm/GridBookmarkWidget/components/GridBookmarkWidget.d.ts +3 -4
- package/esm/GridBookmarkWidget/components/GridBookmarkWidget.js +28 -74
- package/esm/GridBookmarkWidget/components/ImportBookmarks.d.ts +3 -5
- package/esm/GridBookmarkWidget/components/ImportBookmarks.js +10 -66
- package/esm/GridBookmarkWidget/components/ImportBookmarksDialog.d.ts +7 -0
- package/esm/GridBookmarkWidget/components/ImportBookmarksDialog.js +101 -0
- package/esm/GridBookmarkWidget/components/{DownloadBookmarks.d.ts → ShareBookmarks.d.ts} +2 -3
- package/esm/GridBookmarkWidget/components/ShareBookmarks.js +12 -0
- package/esm/GridBookmarkWidget/components/ShareBookmarksDialog.d.ts +7 -0
- package/esm/GridBookmarkWidget/components/ShareBookmarksDialog.js +78 -0
- package/esm/GridBookmarkWidget/model.d.ts +178 -11
- package/esm/GridBookmarkWidget/model.js +106 -28
- package/esm/GridBookmarkWidget/sessionSharing.d.ts +6 -0
- package/esm/GridBookmarkWidget/sessionSharing.js +68 -0
- package/esm/GridBookmarkWidget/utils.d.ts +19 -3
- package/esm/GridBookmarkWidget/utils.js +105 -39
- package/esm/index.d.ts +1 -1
- package/esm/index.js +101 -76
- package/package.json +4 -3
- package/dist/GridBookmarkWidget/components/DeleteBookmark.d.ts +0 -9
- package/dist/GridBookmarkWidget/components/DeleteBookmark.js +0 -31
- package/esm/GridBookmarkWidget/components/ClearBookmarks.js +0 -23
- package/esm/GridBookmarkWidget/components/DeleteBookmark.d.ts +0 -9
- package/esm/GridBookmarkWidget/components/DeleteBookmark.js +0 -26
- package/esm/GridBookmarkWidget/components/DownloadBookmarks.js +0 -33
package/dist/index.js
CHANGED
|
@@ -19,92 +19,117 @@ class default_1 extends Plugin_1.default {
|
|
|
19
19
|
pluginManager.addToExtensionPoint('Core-extendPluggableElement', (pluggableElement) => {
|
|
20
20
|
if (pluggableElement.name === 'LinearGenomeView') {
|
|
21
21
|
const { stateModel } = pluggableElement;
|
|
22
|
-
const
|
|
22
|
+
const lgv = stateModel;
|
|
23
|
+
const newStateModel = lgv
|
|
24
|
+
.actions(self => ({
|
|
25
|
+
activateBookmarkWidget() {
|
|
26
|
+
const session = (0, util_1.getSession)(self);
|
|
27
|
+
if ((0, util_1.isSessionModelWithWidgets)(session)) {
|
|
28
|
+
let bookmarkWidget = session.widgets.get('GridBookmark');
|
|
29
|
+
if (!bookmarkWidget) {
|
|
30
|
+
bookmarkWidget = session.addWidget('GridBookmarkWidget', 'GridBookmark');
|
|
31
|
+
}
|
|
32
|
+
session.showWidget(bookmarkWidget);
|
|
33
|
+
return session.widgets.get('GridBookmark');
|
|
34
|
+
}
|
|
35
|
+
throw new Error('Could not open bookmark widget');
|
|
36
|
+
},
|
|
37
|
+
}))
|
|
38
|
+
.actions(self => ({
|
|
39
|
+
navigateNewestBookmark() {
|
|
40
|
+
const session = (0, util_1.getSession)(self);
|
|
41
|
+
const bookmarkWidget = self.activateBookmarkWidget();
|
|
42
|
+
const regions = bookmarkWidget.bookmarks;
|
|
43
|
+
if (regions === null || regions === void 0 ? void 0 : regions.length) {
|
|
44
|
+
self.navTo(regions.at(-1));
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
session.notify('There are no recent bookmarks to navigate to.', 'info');
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
bookmarkCurrentRegion() {
|
|
51
|
+
if (self.id === (0, util_1.getSession)(self).focusedViewId) {
|
|
52
|
+
const selectedRegions = self.getSelectedRegions(undefined, undefined);
|
|
53
|
+
const bookmarkWidget = self.activateBookmarkWidget();
|
|
54
|
+
bookmarkWidget.addBookmark(selectedRegions[0]);
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
}))
|
|
58
|
+
.views(self => {
|
|
23
59
|
const superMenuItems = self.menuItems;
|
|
24
60
|
const superRubberBandMenuItems = self.rubberBandMenuItems;
|
|
25
61
|
return {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
const firstRegion = selectedRegions[0];
|
|
42
|
-
const session = (0, util_1.getSession)(self);
|
|
43
|
-
if ((0, util_1.isSessionModelWithWidgets)(session)) {
|
|
44
|
-
const { widgets } = session;
|
|
45
|
-
let bookmarkWidget = widgets.get('GridBookmark');
|
|
46
|
-
if (!bookmarkWidget) {
|
|
47
|
-
this.activateBookmarkWidget();
|
|
48
|
-
bookmarkWidget = widgets.get('GridBookmark');
|
|
49
|
-
}
|
|
50
|
-
// @ts-expect-error
|
|
51
|
-
bookmarkWidget.addBookmark(firstRegion);
|
|
52
|
-
}
|
|
53
|
-
},
|
|
62
|
+
menuItems() {
|
|
63
|
+
return [
|
|
64
|
+
...superMenuItems(),
|
|
65
|
+
{ type: 'divider' },
|
|
66
|
+
{
|
|
67
|
+
label: 'Open bookmark widget',
|
|
68
|
+
icon: Bookmarks_1.default,
|
|
69
|
+
onClick: () => self.activateBookmarkWidget(),
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
label: 'Bookmark current region',
|
|
73
|
+
icon: Bookmark_1.default,
|
|
74
|
+
onClick: () => self.bookmarkCurrentRegion(),
|
|
75
|
+
},
|
|
76
|
+
];
|
|
54
77
|
},
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
78
|
+
rubberBandMenuItems() {
|
|
79
|
+
return [
|
|
80
|
+
...superRubberBandMenuItems(),
|
|
81
|
+
{
|
|
82
|
+
label: 'Bookmark region',
|
|
83
|
+
icon: Bookmark_1.default,
|
|
84
|
+
onClick: () => {
|
|
85
|
+
const { leftOffset, rightOffset } = self;
|
|
86
|
+
const selectedRegions = self.getSelectedRegions(leftOffset, rightOffset);
|
|
87
|
+
const bookmarkWidget = self.activateBookmarkWidget();
|
|
88
|
+
bookmarkWidget.addBookmark(selectedRegions[0]);
|
|
65
89
|
},
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
icon: Bookmark_1.default,
|
|
69
|
-
// @ts-expect-error
|
|
70
|
-
onClick: self.bookmarkCurrentRegion,
|
|
71
|
-
},
|
|
72
|
-
];
|
|
73
|
-
},
|
|
74
|
-
rubberBandMenuItems() {
|
|
75
|
-
return [
|
|
76
|
-
...superRubberBandMenuItems(),
|
|
77
|
-
{
|
|
78
|
-
label: 'Bookmark region',
|
|
79
|
-
icon: Bookmark_1.default,
|
|
80
|
-
onClick: () => {
|
|
81
|
-
const { leftOffset, rightOffset } = self;
|
|
82
|
-
const selectedRegions = self.getSelectedRegions(leftOffset, rightOffset);
|
|
83
|
-
const firstRegion = selectedRegions[0];
|
|
84
|
-
const session = (0, util_1.getSession)(self);
|
|
85
|
-
if ((0, util_1.isSessionModelWithWidgets)(session)) {
|
|
86
|
-
const { widgets } = session;
|
|
87
|
-
let bookmarkWidget = widgets.get('GridBookmark');
|
|
88
|
-
if (!bookmarkWidget) {
|
|
89
|
-
// @ts-expect-error
|
|
90
|
-
self.activateBookmarkWidget();
|
|
91
|
-
bookmarkWidget = widgets.get('GridBookmark');
|
|
92
|
-
}
|
|
93
|
-
// @ts-expect-error
|
|
94
|
-
bookmarkWidget.addBookmark(firstRegion);
|
|
95
|
-
}
|
|
96
|
-
},
|
|
97
|
-
},
|
|
98
|
-
];
|
|
99
|
-
},
|
|
90
|
+
},
|
|
91
|
+
];
|
|
100
92
|
},
|
|
101
93
|
};
|
|
102
|
-
})
|
|
94
|
+
})
|
|
95
|
+
.actions(self => ({
|
|
96
|
+
afterCreate() {
|
|
97
|
+
document.addEventListener('keydown', e => {
|
|
98
|
+
const activationSequence = (e.ctrlKey || e.metaKey) && e.shiftKey;
|
|
99
|
+
// ctrl+shift+d or cmd+shift+d
|
|
100
|
+
if (activationSequence && e.code === 'KeyD') {
|
|
101
|
+
e.preventDefault();
|
|
102
|
+
self.activateBookmarkWidget();
|
|
103
|
+
self.bookmarkCurrentRegion();
|
|
104
|
+
(0, util_1.getSession)(self).notify('Bookmark created.', 'success');
|
|
105
|
+
}
|
|
106
|
+
// ctrl+shift+m or cmd+shift+m
|
|
107
|
+
if (activationSequence && e.code === 'KeyM') {
|
|
108
|
+
e.preventDefault();
|
|
109
|
+
self.navigateNewestBookmark();
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
},
|
|
113
|
+
}));
|
|
103
114
|
pluggableElement.stateModel = newStateModel;
|
|
104
115
|
}
|
|
105
116
|
return pluggableElement;
|
|
106
117
|
});
|
|
107
118
|
}
|
|
108
|
-
configure(
|
|
119
|
+
configure(pluginManager) {
|
|
120
|
+
if ((0, util_1.isAbstractMenuManager)(pluginManager.rootModel)) {
|
|
121
|
+
pluginManager.rootModel.appendToMenu('Tools', {
|
|
122
|
+
label: 'Bookmarks',
|
|
123
|
+
icon: Bookmarks_1.default,
|
|
124
|
+
onClick: (session) => {
|
|
125
|
+
let bookmarkWidget = session.widgets.get('GridBookmark');
|
|
126
|
+
if (!bookmarkWidget) {
|
|
127
|
+
bookmarkWidget = session.addWidget('GridBookmarkWidget', 'GridBookmark');
|
|
128
|
+
}
|
|
129
|
+
session.showWidget(bookmarkWidget);
|
|
130
|
+
},
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
}
|
|
109
134
|
}
|
|
110
135
|
exports.default = default_1;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { GridBookmarkModel } from '../model';
|
|
3
|
-
declare
|
|
3
|
+
declare const AssemblySelector: ({ model, }: {
|
|
4
4
|
model: GridBookmarkModel;
|
|
5
|
-
})
|
|
6
|
-
|
|
7
|
-
export default _default;
|
|
5
|
+
}) => React.JSX.Element;
|
|
6
|
+
export default AssemblySelector;
|
|
@@ -1,40 +1,30 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { observer } from 'mobx-react';
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
};
|
|
32
|
-
return (React.createElement("div", { className: classes.container },
|
|
33
|
-
React.createElement(Typography, { className: classes.selectText }, "Select assembly:"),
|
|
34
|
-
React.createElement(FormControl, { className: classes.flexItem, disabled: noAssemblies },
|
|
35
|
-
React.createElement(Select, { value: determineCurrentValue(selectedAssembly), onChange: event => setSelectedAssembly(event.target.value) },
|
|
36
|
-
React.createElement(MenuItem, { value: "none" }, "none"),
|
|
37
|
-
React.createElement(MenuItem, { value: "all" }, "all"),
|
|
38
|
-
assemblies.map(assembly => (React.createElement(MenuItem, { value: assembly, key: assembly }, assembly)))))));
|
|
39
|
-
}
|
|
40
|
-
export default observer(AssemblySelector);
|
|
3
|
+
import { Checkbox, FormControl, InputLabel, ListItemText, MenuItem, OutlinedInput, Select, } from '@mui/material';
|
|
4
|
+
const AssemblySelector = observer(function ({ model, }) {
|
|
5
|
+
const { validAssemblies, selectedAssemblies } = model;
|
|
6
|
+
const noAssemblies = validAssemblies.size === 0 ? true : false;
|
|
7
|
+
const label = 'Select assemblies';
|
|
8
|
+
const id = 'select-assemblies-label';
|
|
9
|
+
const selectedSet = new Set(selectedAssemblies);
|
|
10
|
+
const isAllSelected = [...validAssemblies].every(e => selectedSet.has(e));
|
|
11
|
+
return (React.createElement(FormControl, { disabled: noAssemblies, fullWidth: true },
|
|
12
|
+
React.createElement(InputLabel, { id: id }, label),
|
|
13
|
+
React.createElement(Select, { labelId: id, multiple: true, value: selectedAssemblies, onChange: event => model.setSelectedAssemblies([...event.target.value]), input: React.createElement(OutlinedInput, { label: label }), renderValue: selected => selected.join(', ') },
|
|
14
|
+
React.createElement(MenuItem, { onClickCapture: event => {
|
|
15
|
+
// onClickCapture allows us to avoid the parent Select onChange from triggering
|
|
16
|
+
if (isAllSelected) {
|
|
17
|
+
model.setSelectedAssemblies([]);
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
model.setSelectedAssemblies(undefined);
|
|
21
|
+
}
|
|
22
|
+
event.preventDefault();
|
|
23
|
+
} },
|
|
24
|
+
React.createElement(Checkbox, { checked: isAllSelected, indeterminate: !isAllSelected && selectedAssemblies.length > 0 }),
|
|
25
|
+
React.createElement(ListItemText, { primary: "Select all" })),
|
|
26
|
+
[...validAssemblies].map(name => (React.createElement(MenuItem, { key: name, value: name },
|
|
27
|
+
React.createElement(Checkbox, { checked: selectedAssemblies.includes(name) }),
|
|
28
|
+
React.createElement(ListItemText, { primary: name })))))));
|
|
29
|
+
});
|
|
30
|
+
export default AssemblySelector;
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import React, { Suspense, lazy, useState } from 'react';
|
|
2
|
+
import { observer } from 'mobx-react';
|
|
3
|
+
import { Link } from '@mui/material';
|
|
4
|
+
import { makeStyles } from 'tss-react/mui';
|
|
5
|
+
import { DataGrid, GRID_CHECKBOX_SELECTION_COL_DEF } from '@mui/x-data-grid';
|
|
6
|
+
import { getSession, assembleLocString, measureGridWidth, measureText, } from '@jbrowse/core/util';
|
|
7
|
+
// locals
|
|
8
|
+
import { navToBookmark } from '../utils';
|
|
9
|
+
import { useResizeBar } from '@jbrowse/core/ui/useResizeBar';
|
|
10
|
+
import ResizeBar from '@jbrowse/core/ui/ResizeBar';
|
|
11
|
+
const EditBookmarkLabelDialog = lazy(() => import('./EditBookmarkLabelDialog'));
|
|
12
|
+
const useStyles = makeStyles()(() => ({
|
|
13
|
+
link: {
|
|
14
|
+
cursor: 'pointer',
|
|
15
|
+
},
|
|
16
|
+
cell: {
|
|
17
|
+
whiteSpace: 'nowrap',
|
|
18
|
+
overflow: 'hidden',
|
|
19
|
+
textOverflow: 'ellipsis',
|
|
20
|
+
},
|
|
21
|
+
}));
|
|
22
|
+
const BookmarkGrid = observer(function ({ model, }) {
|
|
23
|
+
const { classes, cx } = useStyles();
|
|
24
|
+
const [dialogRow, setDialogRow] = useState();
|
|
25
|
+
const { ref, scrollLeft } = useResizeBar();
|
|
26
|
+
const { bookmarks, bookmarksWithValidAssemblies, selectedAssemblies, selectedBookmarks, } = model;
|
|
27
|
+
const session = getSession(model);
|
|
28
|
+
const selectedSet = new Set(selectedAssemblies);
|
|
29
|
+
const rows = bookmarks
|
|
30
|
+
.filter(r => selectedSet.has(r.assemblyName))
|
|
31
|
+
.map((region, index) => {
|
|
32
|
+
const { assemblyName, ...rest } = region;
|
|
33
|
+
return {
|
|
34
|
+
...region,
|
|
35
|
+
id: index,
|
|
36
|
+
assemblyName,
|
|
37
|
+
locString: assembleLocString(rest),
|
|
38
|
+
correspondingObj: region,
|
|
39
|
+
};
|
|
40
|
+
});
|
|
41
|
+
// reset selections if bookmarked regions change
|
|
42
|
+
// needed especially if bookmarked regions are deleted, then
|
|
43
|
+
const [widths, setWidths] = useState([
|
|
44
|
+
40,
|
|
45
|
+
Math.max(measureText('Bookmark link'), measureGridWidth(rows.map(row => row.locString))),
|
|
46
|
+
Math.max(measureText('Label'), measureGridWidth(rows.map(row => row.label))),
|
|
47
|
+
Math.max(measureText('Assembly'), measureGridWidth(rows.map(row => row.assemblyName))),
|
|
48
|
+
]);
|
|
49
|
+
return (React.createElement(React.Fragment, null,
|
|
50
|
+
React.createElement("div", { ref: ref },
|
|
51
|
+
React.createElement(ResizeBar, { widths: widths, setWidths: setWidths, scrollLeft: scrollLeft }),
|
|
52
|
+
React.createElement(DataGrid, { autoHeight: true, density: "compact", rows: rows, columns: [
|
|
53
|
+
{
|
|
54
|
+
...GRID_CHECKBOX_SELECTION_COL_DEF,
|
|
55
|
+
width: widths[0],
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
field: 'locString',
|
|
59
|
+
headerName: 'Bookmark link',
|
|
60
|
+
width: widths[1],
|
|
61
|
+
renderCell: ({ value, row }) => (React.createElement(Link, { className: cx(classes.link, classes.cell), href: "#", onClick: async (event) => {
|
|
62
|
+
event.preventDefault();
|
|
63
|
+
const { views } = session;
|
|
64
|
+
await navToBookmark(value, row.assemblyName, views, model);
|
|
65
|
+
} }, value)),
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
field: 'label',
|
|
69
|
+
headerName: 'Label',
|
|
70
|
+
width: widths[2],
|
|
71
|
+
editable: true,
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
field: 'assemblyName',
|
|
75
|
+
headerName: 'Assembly',
|
|
76
|
+
width: widths[3],
|
|
77
|
+
},
|
|
78
|
+
], onCellDoubleClick: ({ row }) => setDialogRow(row), processRowUpdate: row => {
|
|
79
|
+
const target = rows[row.id];
|
|
80
|
+
model.updateBookmarkLabel(target, row.label);
|
|
81
|
+
return row;
|
|
82
|
+
}, onProcessRowUpdateError: e => session.notify(e.message, 'error'), checkboxSelection: true, onRowSelectionModelChange: newRowSelectionModel => {
|
|
83
|
+
if (bookmarksWithValidAssemblies.length > 0) {
|
|
84
|
+
model.setSelectedBookmarks(newRowSelectionModel.map(value => ({
|
|
85
|
+
...rows[value],
|
|
86
|
+
})));
|
|
87
|
+
}
|
|
88
|
+
}, rowSelectionModel: selectedBookmarks.map(r => r.id), disableRowSelectionOnClick: true })),
|
|
89
|
+
dialogRow ? (React.createElement(Suspense, { fallback: React.createElement(React.Fragment, null) },
|
|
90
|
+
React.createElement(EditBookmarkLabelDialog, { onClose: () => setDialogRow(undefined), model: model, dialogRow: dialogRow }))) : null));
|
|
91
|
+
});
|
|
92
|
+
export default BookmarkGrid;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { GridBookmarkModel } from '../model';
|
|
3
|
-
declare function
|
|
3
|
+
declare function DeleteBookmarks({ model }: {
|
|
4
4
|
model: GridBookmarkModel;
|
|
5
5
|
}): React.JSX.Element;
|
|
6
|
-
|
|
7
|
-
export default _default;
|
|
6
|
+
export default DeleteBookmarks;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React, { Suspense, lazy, useState } from 'react';
|
|
2
|
+
import { Button } from '@mui/material';
|
|
3
|
+
// icons
|
|
4
|
+
import DeleteIcon from '@mui/icons-material/Delete';
|
|
5
|
+
const DeleteBookmarksDialog = lazy(() => import('./DeleteBookmarksDialog'));
|
|
6
|
+
function DeleteBookmarks({ model }) {
|
|
7
|
+
const [open, setOpen] = useState(false);
|
|
8
|
+
return (React.createElement(React.Fragment, null,
|
|
9
|
+
React.createElement(Button, { startIcon: React.createElement(DeleteIcon, null), "aria-label": "clear bookmarks", onClick: () => setOpen(true) }, "Delete"),
|
|
10
|
+
open ? (React.createElement(Suspense, { fallback: React.createElement(React.Fragment, null) },
|
|
11
|
+
React.createElement(DeleteBookmarksDialog, { model: model, onClose: () => setOpen(false) }))) : null));
|
|
12
|
+
}
|
|
13
|
+
export default DeleteBookmarks;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { observer } from 'mobx-react';
|
|
3
|
+
import { Button, DialogContent, DialogActions, Alert } from '@mui/material';
|
|
4
|
+
import { Dialog } from '@jbrowse/core/ui';
|
|
5
|
+
const DeleteBookmarksDialog = observer(function ({ onClose, model, }) {
|
|
6
|
+
const { selectedBookmarks } = model;
|
|
7
|
+
const deleteAll = selectedBookmarks.length === 0;
|
|
8
|
+
return (React.createElement(Dialog, { open: true, onClose: onClose, title: "Delete bookmarks" },
|
|
9
|
+
React.createElement(DialogContent, null,
|
|
10
|
+
React.createElement(Alert, { severity: "warning" }, deleteAll ? (React.createElement(React.Fragment, null,
|
|
11
|
+
React.createElement("span", null, "All bookmarks will be deleted."),
|
|
12
|
+
React.createElement("br", null),
|
|
13
|
+
React.createElement("span", null, "Use the checkboxes to select individual bookmarks to delete."))) : ('Only selected bookmarks will be deleted.'))),
|
|
14
|
+
React.createElement(DialogActions, null,
|
|
15
|
+
React.createElement(Button, { variant: "contained", color: "secondary", onClick: () => onClose() }, "Cancel"),
|
|
16
|
+
React.createElement(Button, { variant: "contained", color: "primary", onClick: () => {
|
|
17
|
+
if (deleteAll) {
|
|
18
|
+
model.clearAllBookmarks();
|
|
19
|
+
}
|
|
20
|
+
model.clearSelectedBookmarks();
|
|
21
|
+
onClose();
|
|
22
|
+
} }, "Confirm"))));
|
|
23
|
+
});
|
|
24
|
+
export default DeleteBookmarksDialog;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { GridBookmarkModel, IExtendedLabeledRegionModel } from '../model';
|
|
3
|
+
declare const EditBookmarkLabelDialog: ({ model, onClose, dialogRow, }: {
|
|
4
|
+
model: GridBookmarkModel;
|
|
5
|
+
dialogRow: IExtendedLabeledRegionModel;
|
|
6
|
+
onClose: () => void;
|
|
7
|
+
}) => React.JSX.Element;
|
|
8
|
+
export default EditBookmarkLabelDialog;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import { Alert, DialogContent, DialogActions, Button, TextField, } from '@mui/material';
|
|
3
|
+
import { Dialog } from '@jbrowse/core/ui';
|
|
4
|
+
import { observer } from 'mobx-react';
|
|
5
|
+
import { assembleLocString } from '@jbrowse/core/util';
|
|
6
|
+
const EditBookmarkLabelDialog = observer(function ({ model, onClose, dialogRow, }) {
|
|
7
|
+
const [newLabel, setNewLabel] = useState(dialogRow.label || '');
|
|
8
|
+
return (React.createElement(Dialog, { open: true, onClose: onClose, title: "Edit bookmark label" },
|
|
9
|
+
React.createElement(DialogContent, null,
|
|
10
|
+
React.createElement(Alert, null,
|
|
11
|
+
"Editing label for bookmark",
|
|
12
|
+
' ',
|
|
13
|
+
React.createElement("strong", null, assembleLocString(dialogRow.correspondingObj)),
|
|
14
|
+
":"),
|
|
15
|
+
React.createElement(TextField, { fullWidth: true, inputProps: { 'data-testid': 'edit-bookmark-label-field' }, variant: "outlined", value: newLabel, onChange: e => setNewLabel(e.target.value), autoFocus: true })),
|
|
16
|
+
React.createElement(DialogActions, null,
|
|
17
|
+
React.createElement(Button, { variant: "contained", color: "primary", onClick: () => {
|
|
18
|
+
if (newLabel && dialogRow) {
|
|
19
|
+
model.updateBookmarkLabel(dialogRow, newLabel);
|
|
20
|
+
}
|
|
21
|
+
setNewLabel('');
|
|
22
|
+
onClose();
|
|
23
|
+
} }, "Confirm"))));
|
|
24
|
+
});
|
|
25
|
+
export default EditBookmarkLabelDialog;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React, { Suspense, lazy, useState } from 'react';
|
|
2
|
+
import { observer } from 'mobx-react';
|
|
3
|
+
import { Button } from '@mui/material';
|
|
4
|
+
import GetAppIcon from '@mui/icons-material/GetApp';
|
|
5
|
+
const ExportBookmarksDialog = lazy(() => import('./ExportBookmarksDialog'));
|
|
6
|
+
const ExportBookmarks = observer(function ExportBookmarks({ model, }) {
|
|
7
|
+
const [open, setOpen] = useState(false);
|
|
8
|
+
return (React.createElement(React.Fragment, null,
|
|
9
|
+
React.createElement(Button, { startIcon: React.createElement(GetAppIcon, null), onClick: () => setOpen(true), "data-testid": "export_button" }, "Export"),
|
|
10
|
+
open ? (React.createElement(Suspense, { fallback: React.createElement(React.Fragment, null) },
|
|
11
|
+
React.createElement(ExportBookmarksDialog, { onClose: () => setOpen(false), model: model }))) : null));
|
|
12
|
+
});
|
|
13
|
+
export default ExportBookmarks;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import { observer } from 'mobx-react';
|
|
3
|
+
import { Button, DialogContent, DialogActions, MenuItem, Select, Typography, Alert, } from '@mui/material';
|
|
4
|
+
import GetAppIcon from '@mui/icons-material/GetApp';
|
|
5
|
+
import { makeStyles } from 'tss-react/mui';
|
|
6
|
+
import { Dialog } from '@jbrowse/core/ui';
|
|
7
|
+
import { downloadBookmarkFile } from '../utils';
|
|
8
|
+
const useStyles = makeStyles()(() => ({
|
|
9
|
+
flexItem: {
|
|
10
|
+
margin: 5,
|
|
11
|
+
},
|
|
12
|
+
}));
|
|
13
|
+
const ExportBookmarksDialog = observer(function ExportBookmarksDialog({ model, onClose, }) {
|
|
14
|
+
const { classes } = useStyles();
|
|
15
|
+
const [fileType, setFileType] = useState('BED');
|
|
16
|
+
const { selectedBookmarks } = model;
|
|
17
|
+
const exportAll = selectedBookmarks.length === 0;
|
|
18
|
+
return (React.createElement(Dialog, { open: true, onClose: onClose, title: "Export bookmarks" },
|
|
19
|
+
React.createElement(DialogContent, { style: { display: 'flex', flexFlow: 'column', gap: '5px' } },
|
|
20
|
+
React.createElement(Alert, { severity: "info" }, exportAll ? (React.createElement(React.Fragment, null,
|
|
21
|
+
React.createElement("span", null, "All bookmarks will be exported."),
|
|
22
|
+
React.createElement("br", null),
|
|
23
|
+
React.createElement("span", null, "Use the checkboxes to select individual bookmarks to export."))) : ('Only selected bookmarks will be exported.')),
|
|
24
|
+
React.createElement("div", { style: { display: 'flex', alignItems: 'center' } },
|
|
25
|
+
React.createElement(Typography, null, "Format to download:"),
|
|
26
|
+
React.createElement(Select, { size: "small", className: classes.flexItem, "data-testid": "selectFileType", value: fileType, onChange: event => setFileType(event.target.value) },
|
|
27
|
+
React.createElement(MenuItem, { value: "BED" }, "BED"),
|
|
28
|
+
React.createElement(MenuItem, { value: "TSV" }, "TSV")))),
|
|
29
|
+
React.createElement(DialogActions, null,
|
|
30
|
+
React.createElement(Button, { className: classes.flexItem, "data-testid": "dialogDownload", variant: "contained", color: "primary", startIcon: React.createElement(GetAppIcon, null), onClick: () => {
|
|
31
|
+
downloadBookmarkFile(fileType, model);
|
|
32
|
+
onClose(false);
|
|
33
|
+
} }, "Download"))));
|
|
34
|
+
});
|
|
35
|
+
export default ExportBookmarksDialog;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { GridBookmarkModel } from '../model';
|
|
3
|
-
declare
|
|
3
|
+
declare const GridBookmarkWidget: ({ model, }: {
|
|
4
4
|
model: GridBookmarkModel;
|
|
5
|
-
})
|
|
6
|
-
|
|
7
|
-
export default _default;
|
|
5
|
+
}) => React.JSX.Element | null;
|
|
6
|
+
export default GridBookmarkWidget;
|