@jbrowse/plugin-grid-bookmark 2.6.1 → 2.6.2
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.js +0 -1
- package/dist/GridBookmarkWidget/components/ClearBookmarks.js +0 -1
- package/dist/GridBookmarkWidget/components/DeleteBookmark.js +0 -1
- package/dist/GridBookmarkWidget/components/DownloadBookmarks.js +0 -1
- package/dist/GridBookmarkWidget/components/GridBookmarkWidget.js +0 -1
- package/dist/GridBookmarkWidget/components/ImportBookmarks.js +0 -1
- package/dist/GridBookmarkWidget/index.js +0 -1
- package/dist/GridBookmarkWidget/model.js +0 -1
- package/dist/GridBookmarkWidget/types.js +0 -1
- package/dist/GridBookmarkWidget/utils.js +0 -1
- package/dist/index.js +0 -1
- package/esm/GridBookmarkWidget/components/AssemblySelector.js +0 -1
- package/esm/GridBookmarkWidget/components/ClearBookmarks.js +0 -1
- package/esm/GridBookmarkWidget/components/DeleteBookmark.js +0 -1
- package/esm/GridBookmarkWidget/components/DownloadBookmarks.js +0 -1
- package/esm/GridBookmarkWidget/components/GridBookmarkWidget.js +0 -1
- package/esm/GridBookmarkWidget/components/ImportBookmarks.js +0 -1
- package/esm/GridBookmarkWidget/index.js +0 -1
- package/esm/GridBookmarkWidget/model.js +0 -1
- package/esm/GridBookmarkWidget/types.js +0 -1
- package/esm/GridBookmarkWidget/utils.js +0 -1
- package/esm/index.js +0 -1
- package/package.json +3 -4
- package/dist/GridBookmarkWidget/components/AssemblySelector.js.map +0 -1
- package/dist/GridBookmarkWidget/components/ClearBookmarks.js.map +0 -1
- package/dist/GridBookmarkWidget/components/DeleteBookmark.js.map +0 -1
- package/dist/GridBookmarkWidget/components/DownloadBookmarks.js.map +0 -1
- package/dist/GridBookmarkWidget/components/GridBookmarkWidget.js.map +0 -1
- package/dist/GridBookmarkWidget/components/ImportBookmarks.js.map +0 -1
- package/dist/GridBookmarkWidget/index.js.map +0 -1
- package/dist/GridBookmarkWidget/model.js.map +0 -1
- package/dist/GridBookmarkWidget/types.js.map +0 -1
- package/dist/GridBookmarkWidget/utils.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/esm/GridBookmarkWidget/components/AssemblySelector.js.map +0 -1
- package/esm/GridBookmarkWidget/components/ClearBookmarks.js.map +0 -1
- package/esm/GridBookmarkWidget/components/DeleteBookmark.js.map +0 -1
- package/esm/GridBookmarkWidget/components/DownloadBookmarks.js.map +0 -1
- package/esm/GridBookmarkWidget/components/GridBookmarkWidget.js.map +0 -1
- package/esm/GridBookmarkWidget/components/ImportBookmarks.js.map +0 -1
- package/esm/GridBookmarkWidget/index.js.map +0 -1
- package/esm/GridBookmarkWidget/model.js.map +0 -1
- package/esm/GridBookmarkWidget/types.js.map +0 -1
- package/esm/GridBookmarkWidget/utils.js.map +0 -1
- package/esm/index.js.map +0 -1
- package/src/GridBookmarkWidget/components/AssemblySelector.tsx +0 -60
- package/src/GridBookmarkWidget/components/ClearBookmarks.tsx +0 -60
- package/src/GridBookmarkWidget/components/DeleteBookmark.tsx +0 -58
- package/src/GridBookmarkWidget/components/DownloadBookmarks.tsx +0 -80
- package/src/GridBookmarkWidget/components/GridBookmarkWidget.test.tsx +0 -161
- package/src/GridBookmarkWidget/components/GridBookmarkWidget.tsx +0 -136
- package/src/GridBookmarkWidget/components/ImportBookmarks.tsx +0 -131
- package/src/GridBookmarkWidget/index.ts +0 -19
- package/src/GridBookmarkWidget/model.ts +0 -66
- package/src/GridBookmarkWidget/types.ts +0 -5
- package/src/GridBookmarkWidget/utils.ts +0 -90
- package/src/__snapshots__/index.test.ts.snap +0 -3
- package/src/index.test.ts +0 -26
- package/src/index.ts +0 -133
|
@@ -1,161 +0,0 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
|
-
import { saveAs } from 'file-saver'
|
|
3
|
-
import { render, cleanup, fireEvent, within } from '@testing-library/react'
|
|
4
|
-
|
|
5
|
-
import { createTestSession } from '@jbrowse/web/src/rootModel'
|
|
6
|
-
|
|
7
|
-
import GridBookmarkWidget from './GridBookmarkWidget'
|
|
8
|
-
import { GridBookmarkModel } from '../model'
|
|
9
|
-
jest.mock('@jbrowse/web/src/makeWorkerInstance', () => () => {})
|
|
10
|
-
|
|
11
|
-
jest.mock('file-saver', () => {
|
|
12
|
-
return {
|
|
13
|
-
...jest.requireActual('file-saver'),
|
|
14
|
-
saveAs: jest.fn(),
|
|
15
|
-
}
|
|
16
|
-
})
|
|
17
|
-
|
|
18
|
-
describe('<GridBookmarkWidget />', () => {
|
|
19
|
-
beforeEach(() => {
|
|
20
|
-
// @ts-expect-error
|
|
21
|
-
saveAs.mockReset()
|
|
22
|
-
})
|
|
23
|
-
|
|
24
|
-
afterEach(cleanup)
|
|
25
|
-
|
|
26
|
-
it('renders empty with no bookmarks', async () => {
|
|
27
|
-
const session = createTestSession()
|
|
28
|
-
const model = session.addWidget(
|
|
29
|
-
'GridBookmarkWidget',
|
|
30
|
-
'gridBookmarkWidget',
|
|
31
|
-
) as GridBookmarkModel
|
|
32
|
-
|
|
33
|
-
const { findByText } = render(<GridBookmarkWidget model={model} />)
|
|
34
|
-
|
|
35
|
-
expect(await findByText('No rows')).toBeTruthy()
|
|
36
|
-
})
|
|
37
|
-
|
|
38
|
-
it('renders bookmarks correctly', async () => {
|
|
39
|
-
const session = createTestSession()
|
|
40
|
-
const model = session.addWidget(
|
|
41
|
-
'GridBookmarkWidget',
|
|
42
|
-
'gridBookmarkWidget',
|
|
43
|
-
) as GridBookmarkModel
|
|
44
|
-
|
|
45
|
-
model.addBookmark({
|
|
46
|
-
refName: 'chr1',
|
|
47
|
-
start: 1,
|
|
48
|
-
end: 12,
|
|
49
|
-
assemblyName: 'hg19',
|
|
50
|
-
})
|
|
51
|
-
|
|
52
|
-
const { findByText } = render(<GridBookmarkWidget model={model} />)
|
|
53
|
-
|
|
54
|
-
expect(await findByText('chr1:2..12')).toBeTruthy()
|
|
55
|
-
})
|
|
56
|
-
|
|
57
|
-
it('deletes individual bookmarks correctly', async () => {
|
|
58
|
-
const session = createTestSession()
|
|
59
|
-
const model = session.addWidget(
|
|
60
|
-
'GridBookmarkWidget',
|
|
61
|
-
'gridBookmarkWidget',
|
|
62
|
-
) as GridBookmarkModel
|
|
63
|
-
|
|
64
|
-
model.addBookmark({
|
|
65
|
-
refName: 'chr1',
|
|
66
|
-
start: 1,
|
|
67
|
-
end: 12,
|
|
68
|
-
assemblyName: 'hg19',
|
|
69
|
-
})
|
|
70
|
-
|
|
71
|
-
const { findByText, findByTestId } = render(
|
|
72
|
-
<GridBookmarkWidget model={model} />,
|
|
73
|
-
)
|
|
74
|
-
|
|
75
|
-
fireEvent.click(await findByTestId('deleteBookmark'))
|
|
76
|
-
fireEvent.click(await findByText('Confirm'))
|
|
77
|
-
|
|
78
|
-
expect(await findByText('No rows')).toBeTruthy()
|
|
79
|
-
})
|
|
80
|
-
|
|
81
|
-
it('clears all bookmarks correctly', async () => {
|
|
82
|
-
const session = createTestSession()
|
|
83
|
-
const model = session.addWidget(
|
|
84
|
-
'GridBookmarkWidget',
|
|
85
|
-
'gridBookmarkWidget',
|
|
86
|
-
) as GridBookmarkModel
|
|
87
|
-
|
|
88
|
-
model.addBookmark({
|
|
89
|
-
refName: 'chr1',
|
|
90
|
-
start: 1,
|
|
91
|
-
end: 12,
|
|
92
|
-
assemblyName: 'hg19',
|
|
93
|
-
})
|
|
94
|
-
|
|
95
|
-
const { findByText } = render(<GridBookmarkWidget model={model} />)
|
|
96
|
-
|
|
97
|
-
fireEvent.click(await findByText('Clear'))
|
|
98
|
-
fireEvent.click(await findByText('Confirm'))
|
|
99
|
-
|
|
100
|
-
expect(await findByText('No rows')).toBeTruthy()
|
|
101
|
-
})
|
|
102
|
-
|
|
103
|
-
it('downloads a BED file correctly', async () => {
|
|
104
|
-
const session = createTestSession()
|
|
105
|
-
const model = session.addWidget(
|
|
106
|
-
'GridBookmarkWidget',
|
|
107
|
-
'gridBookmarkWidget',
|
|
108
|
-
) as GridBookmarkModel
|
|
109
|
-
|
|
110
|
-
model.addBookmark({
|
|
111
|
-
refName: 'chr1',
|
|
112
|
-
start: 1,
|
|
113
|
-
end: 12,
|
|
114
|
-
assemblyName: 'hg19',
|
|
115
|
-
})
|
|
116
|
-
|
|
117
|
-
const { findByText, findByTestId } = render(
|
|
118
|
-
<GridBookmarkWidget model={model} />,
|
|
119
|
-
)
|
|
120
|
-
|
|
121
|
-
fireEvent.click(await findByText('Download'))
|
|
122
|
-
fireEvent.click(await findByTestId('dialogDownload'))
|
|
123
|
-
|
|
124
|
-
const blob = new Blob([''], {
|
|
125
|
-
type: 'text/x-bed;charset=utf-8',
|
|
126
|
-
})
|
|
127
|
-
|
|
128
|
-
expect(saveAs).toHaveBeenCalledWith(blob, 'jbrowse_bookmarks_hg19.bed')
|
|
129
|
-
})
|
|
130
|
-
|
|
131
|
-
it('downloads a TSV file correctly', async () => {
|
|
132
|
-
const session = createTestSession()
|
|
133
|
-
const model = session.addWidget(
|
|
134
|
-
'GridBookmarkWidget',
|
|
135
|
-
'gridBookmarkWidget',
|
|
136
|
-
) as GridBookmarkModel
|
|
137
|
-
|
|
138
|
-
model.addBookmark({
|
|
139
|
-
refName: 'chr1',
|
|
140
|
-
start: 1,
|
|
141
|
-
end: 12,
|
|
142
|
-
assemblyName: 'hg19',
|
|
143
|
-
})
|
|
144
|
-
|
|
145
|
-
const { findByText, findByTestId, getByRole } = render(
|
|
146
|
-
<GridBookmarkWidget model={model} />,
|
|
147
|
-
)
|
|
148
|
-
|
|
149
|
-
fireEvent.click(await findByText('Download'))
|
|
150
|
-
fireEvent.mouseDown(await findByText('BED'))
|
|
151
|
-
const listbox = within(getByRole('listbox'))
|
|
152
|
-
fireEvent.click(listbox.getByText('TSV'))
|
|
153
|
-
fireEvent.click(await findByTestId('dialogDownload'))
|
|
154
|
-
|
|
155
|
-
const blob = new Blob([''], {
|
|
156
|
-
type: 'text/tab-separated-values;charset=utf-8',
|
|
157
|
-
})
|
|
158
|
-
|
|
159
|
-
expect(saveAs).toHaveBeenCalledWith(blob, 'jbrowse_bookmarks.tsv')
|
|
160
|
-
})
|
|
161
|
-
})
|
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
import React, { useState } from 'react'
|
|
2
|
-
import { observer } from 'mobx-react'
|
|
3
|
-
import { Link, IconButton, Typography } from '@mui/material'
|
|
4
|
-
import { makeStyles } from 'tss-react/mui'
|
|
5
|
-
import { DataGrid } from '@mui/x-data-grid'
|
|
6
|
-
import {
|
|
7
|
-
getSession,
|
|
8
|
-
assembleLocString,
|
|
9
|
-
measureGridWidth,
|
|
10
|
-
} from '@jbrowse/core/util'
|
|
11
|
-
|
|
12
|
-
// icons
|
|
13
|
-
import DeleteIcon from '@mui/icons-material/Delete'
|
|
14
|
-
|
|
15
|
-
// locals
|
|
16
|
-
import AssemblySelector from './AssemblySelector'
|
|
17
|
-
import DeleteBookmarkDialog from './DeleteBookmark'
|
|
18
|
-
import DownloadBookmarks from './DownloadBookmarks'
|
|
19
|
-
import ImportBookmarks from './ImportBookmarks'
|
|
20
|
-
import ClearBookmarks from './ClearBookmarks'
|
|
21
|
-
import { GridBookmarkModel } from '../model'
|
|
22
|
-
import { navToBookmark } from '../utils'
|
|
23
|
-
|
|
24
|
-
const useStyles = makeStyles()(theme => ({
|
|
25
|
-
link: {
|
|
26
|
-
cursor: 'pointer',
|
|
27
|
-
},
|
|
28
|
-
margin: {
|
|
29
|
-
margin: theme.spacing(2),
|
|
30
|
-
},
|
|
31
|
-
}))
|
|
32
|
-
|
|
33
|
-
const BookmarkGrid = observer(({ model }: { model: GridBookmarkModel }) => {
|
|
34
|
-
const { classes } = useStyles()
|
|
35
|
-
const [dialogRowNumber, setDialogRowNumber] = useState<number>()
|
|
36
|
-
const { bookmarkedRegions, selectedAssembly } = model
|
|
37
|
-
const { views } = getSession(model)
|
|
38
|
-
|
|
39
|
-
const bookmarkRows = bookmarkedRegions
|
|
40
|
-
.filter(
|
|
41
|
-
r => selectedAssembly === 'all' || r.assemblyName === selectedAssembly,
|
|
42
|
-
)
|
|
43
|
-
.map((region, index) => {
|
|
44
|
-
const { assemblyName, ...rest } = region
|
|
45
|
-
return {
|
|
46
|
-
...region,
|
|
47
|
-
id: index,
|
|
48
|
-
delete: index,
|
|
49
|
-
locString: assembleLocString(
|
|
50
|
-
selectedAssembly === 'all' ? region : rest,
|
|
51
|
-
),
|
|
52
|
-
}
|
|
53
|
-
})
|
|
54
|
-
|
|
55
|
-
return (
|
|
56
|
-
<>
|
|
57
|
-
<DataGrid
|
|
58
|
-
density="compact"
|
|
59
|
-
rows={bookmarkRows}
|
|
60
|
-
columns={[
|
|
61
|
-
{
|
|
62
|
-
field: 'locString',
|
|
63
|
-
headerName: 'bookmark link',
|
|
64
|
-
width: measureGridWidth(bookmarkRows.map(row => row.locString)),
|
|
65
|
-
renderCell: params => (
|
|
66
|
-
<Link
|
|
67
|
-
className={classes.link}
|
|
68
|
-
href="#"
|
|
69
|
-
onClick={async event => {
|
|
70
|
-
event.preventDefault()
|
|
71
|
-
await navToBookmark(params.value, views, model)
|
|
72
|
-
}}
|
|
73
|
-
>
|
|
74
|
-
{params.value}
|
|
75
|
-
</Link>
|
|
76
|
-
),
|
|
77
|
-
},
|
|
78
|
-
{
|
|
79
|
-
field: 'label',
|
|
80
|
-
width: measureGridWidth(bookmarkRows.map(row => row.label)),
|
|
81
|
-
editable: true,
|
|
82
|
-
},
|
|
83
|
-
{
|
|
84
|
-
field: 'delete',
|
|
85
|
-
width: 100,
|
|
86
|
-
renderCell: params => (
|
|
87
|
-
<IconButton
|
|
88
|
-
data-testid="deleteBookmark"
|
|
89
|
-
aria-label="delete"
|
|
90
|
-
onClick={() => {
|
|
91
|
-
if (params.value != null) {
|
|
92
|
-
setDialogRowNumber(+params.value)
|
|
93
|
-
}
|
|
94
|
-
}}
|
|
95
|
-
>
|
|
96
|
-
<DeleteIcon />
|
|
97
|
-
</IconButton>
|
|
98
|
-
),
|
|
99
|
-
},
|
|
100
|
-
]}
|
|
101
|
-
onCellEditStop={({ id, value }) =>
|
|
102
|
-
model.updateBookmarkLabel(id as number, value)
|
|
103
|
-
}
|
|
104
|
-
disableRowSelectionOnClick
|
|
105
|
-
/>
|
|
106
|
-
|
|
107
|
-
<DeleteBookmarkDialog
|
|
108
|
-
rowNumber={dialogRowNumber}
|
|
109
|
-
model={model}
|
|
110
|
-
onClose={() => setDialogRowNumber(undefined)}
|
|
111
|
-
/>
|
|
112
|
-
</>
|
|
113
|
-
)
|
|
114
|
-
})
|
|
115
|
-
|
|
116
|
-
function GridBookmarkWidget({ model }: { model: GridBookmarkModel }) {
|
|
117
|
-
const { selectedAssembly } = model
|
|
118
|
-
const { classes } = useStyles()
|
|
119
|
-
|
|
120
|
-
return (
|
|
121
|
-
<>
|
|
122
|
-
<AssemblySelector model={model} />
|
|
123
|
-
<DownloadBookmarks model={model} />
|
|
124
|
-
<ImportBookmarks model={model} assemblyName={selectedAssembly} />
|
|
125
|
-
<ClearBookmarks model={model} />
|
|
126
|
-
|
|
127
|
-
<Typography className={classes.margin}>
|
|
128
|
-
Note: you can double click the <code>label</code> field to add your own
|
|
129
|
-
custom notes
|
|
130
|
-
</Typography>
|
|
131
|
-
<BookmarkGrid model={model} />
|
|
132
|
-
</>
|
|
133
|
-
)
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
export default observer(GridBookmarkWidget)
|
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
import React, { useState } from 'react'
|
|
2
|
-
import { observer } from 'mobx-react'
|
|
3
|
-
import { getSession } from '@jbrowse/core/util'
|
|
4
|
-
import AssemblySelector from '@jbrowse/core/ui/AssemblySelector'
|
|
5
|
-
import { FileLocation } from '@jbrowse/core/util/types'
|
|
6
|
-
import { FileSelector } from '@jbrowse/core/ui'
|
|
7
|
-
import { openLocation } from '@jbrowse/core/util/io'
|
|
8
|
-
import { Button, DialogContent, DialogActions, Typography } from '@mui/material'
|
|
9
|
-
import { Dialog } from '@jbrowse/core/ui'
|
|
10
|
-
import { makeStyles } from 'tss-react/mui'
|
|
11
|
-
|
|
12
|
-
// icons
|
|
13
|
-
import ImportIcon from '@mui/icons-material/Publish'
|
|
14
|
-
|
|
15
|
-
// locals
|
|
16
|
-
import { GridBookmarkModel } from '../model'
|
|
17
|
-
|
|
18
|
-
const useStyles = makeStyles()(() => ({
|
|
19
|
-
dialogContainer: {
|
|
20
|
-
margin: 15,
|
|
21
|
-
},
|
|
22
|
-
flexItem: {
|
|
23
|
-
margin: 5,
|
|
24
|
-
},
|
|
25
|
-
}))
|
|
26
|
-
|
|
27
|
-
function ImportBookmarks({
|
|
28
|
-
model,
|
|
29
|
-
assemblyName,
|
|
30
|
-
}: {
|
|
31
|
-
model: GridBookmarkModel
|
|
32
|
-
assemblyName: string
|
|
33
|
-
}) {
|
|
34
|
-
const { classes } = useStyles()
|
|
35
|
-
const session = getSession(model)
|
|
36
|
-
const { assemblyNames } = session
|
|
37
|
-
const [dialogOpen, setDialogOpen] = useState(false)
|
|
38
|
-
const [location, setLocation] = useState<FileLocation>()
|
|
39
|
-
const [error, setError] = useState<unknown>()
|
|
40
|
-
const [selectedAsm, setSelectedAsm] = useState(
|
|
41
|
-
assemblyName || assemblyNames[0],
|
|
42
|
-
)
|
|
43
|
-
|
|
44
|
-
return (
|
|
45
|
-
<>
|
|
46
|
-
<Button startIcon={<ImportIcon />} onClick={() => setDialogOpen(true)}>
|
|
47
|
-
Import
|
|
48
|
-
</Button>
|
|
49
|
-
<Dialog
|
|
50
|
-
open={dialogOpen}
|
|
51
|
-
onClose={() => setDialogOpen(false)}
|
|
52
|
-
maxWidth="xl"
|
|
53
|
-
title="Import bookmarks"
|
|
54
|
-
>
|
|
55
|
-
<DialogContent>
|
|
56
|
-
<Typography>
|
|
57
|
-
Choose a BED format file to import. The first 4 columns will be used
|
|
58
|
-
</Typography>
|
|
59
|
-
|
|
60
|
-
<FileSelector
|
|
61
|
-
location={location}
|
|
62
|
-
setLocation={setLocation}
|
|
63
|
-
name="File"
|
|
64
|
-
/>
|
|
65
|
-
<Typography>Select assembly that your data belongs to</Typography>
|
|
66
|
-
<AssemblySelector
|
|
67
|
-
onChange={val => setSelectedAsm(val)}
|
|
68
|
-
session={session}
|
|
69
|
-
selected={selectedAsm}
|
|
70
|
-
/>
|
|
71
|
-
{error ? (
|
|
72
|
-
<Typography color="error" variant="h6">{`${error}`}</Typography>
|
|
73
|
-
) : null}
|
|
74
|
-
</DialogContent>
|
|
75
|
-
<DialogActions>
|
|
76
|
-
<Button
|
|
77
|
-
variant="contained"
|
|
78
|
-
color="secondary"
|
|
79
|
-
onClick={() => setDialogOpen(false)}
|
|
80
|
-
>
|
|
81
|
-
Cancel
|
|
82
|
-
</Button>
|
|
83
|
-
<Button
|
|
84
|
-
className={classes.flexItem}
|
|
85
|
-
data-testid="dialogImport"
|
|
86
|
-
variant="contained"
|
|
87
|
-
color="primary"
|
|
88
|
-
disabled={!location}
|
|
89
|
-
startIcon={<ImportIcon />}
|
|
90
|
-
onClick={async () => {
|
|
91
|
-
try {
|
|
92
|
-
if (!location) {
|
|
93
|
-
return
|
|
94
|
-
}
|
|
95
|
-
const data = await openLocation(location).readFile('utf8')
|
|
96
|
-
const regions = data
|
|
97
|
-
.split(/\n|\r\n|\r/)
|
|
98
|
-
.filter(f => !!f.trim())
|
|
99
|
-
.filter(
|
|
100
|
-
f =>
|
|
101
|
-
!f.startsWith('#') &&
|
|
102
|
-
!f.startsWith('track') &&
|
|
103
|
-
!f.startsWith('browser'),
|
|
104
|
-
)
|
|
105
|
-
.map(line => {
|
|
106
|
-
const [refName, start, end, name] = line.split('\t')
|
|
107
|
-
return {
|
|
108
|
-
assemblyName: selectedAsm,
|
|
109
|
-
refName,
|
|
110
|
-
start: +start,
|
|
111
|
-
end: +end,
|
|
112
|
-
label: name === '.' ? undefined : name,
|
|
113
|
-
}
|
|
114
|
-
})
|
|
115
|
-
model.importBookmarks(regions)
|
|
116
|
-
setDialogOpen(false)
|
|
117
|
-
} catch (e) {
|
|
118
|
-
console.error(e)
|
|
119
|
-
setError(e)
|
|
120
|
-
}
|
|
121
|
-
}}
|
|
122
|
-
>
|
|
123
|
-
Import
|
|
124
|
-
</Button>
|
|
125
|
-
</DialogActions>
|
|
126
|
-
</Dialog>
|
|
127
|
-
</>
|
|
128
|
-
)
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
export default observer(ImportBookmarks)
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { lazy } from 'react'
|
|
2
|
-
import { ConfigurationSchema } from '@jbrowse/core/configuration'
|
|
3
|
-
import { WidgetType } from '@jbrowse/core/pluggableElementTypes'
|
|
4
|
-
import stateModelFactory from './model'
|
|
5
|
-
import PluginManager from '@jbrowse/core/PluginManager'
|
|
6
|
-
|
|
7
|
-
const configSchema = ConfigurationSchema('GridBookmarkWidget', {})
|
|
8
|
-
|
|
9
|
-
export default (pluginManager: PluginManager) => {
|
|
10
|
-
pluginManager.addWidgetType(() => {
|
|
11
|
-
return new WidgetType({
|
|
12
|
-
name: 'GridBookmarkWidget',
|
|
13
|
-
heading: 'Bookmarked regions',
|
|
14
|
-
configSchema,
|
|
15
|
-
stateModel: stateModelFactory(pluginManager),
|
|
16
|
-
ReactComponent: lazy(() => import('./components/GridBookmarkWidget')),
|
|
17
|
-
})
|
|
18
|
-
})
|
|
19
|
-
}
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import { types, cast, Instance } from 'mobx-state-tree'
|
|
2
|
-
import PluginManager from '@jbrowse/core/PluginManager'
|
|
3
|
-
import { Region } from '@jbrowse/core/util/types'
|
|
4
|
-
import { Region as RegionModel, ElementId } from '@jbrowse/core/util/types/mst'
|
|
5
|
-
|
|
6
|
-
const LabeledRegionModel = types
|
|
7
|
-
.compose(
|
|
8
|
-
RegionModel,
|
|
9
|
-
types.model('Label', { label: types.optional(types.string, '') }),
|
|
10
|
-
)
|
|
11
|
-
.actions(self => ({
|
|
12
|
-
setLabel(label: string) {
|
|
13
|
-
self.label = label
|
|
14
|
-
},
|
|
15
|
-
}))
|
|
16
|
-
|
|
17
|
-
export default function f(pluginManager: PluginManager) {
|
|
18
|
-
return types
|
|
19
|
-
.model('GridBookmarkModel', {
|
|
20
|
-
id: ElementId,
|
|
21
|
-
type: types.literal('GridBookmarkWidget'),
|
|
22
|
-
view: types.safeReference(
|
|
23
|
-
pluginManager.pluggableMstType('view', 'stateModel'),
|
|
24
|
-
),
|
|
25
|
-
bookmarkedRegions: types.array(LabeledRegionModel),
|
|
26
|
-
modelSelectedAssembly: '',
|
|
27
|
-
})
|
|
28
|
-
.actions(self => ({
|
|
29
|
-
importBookmarks(regions: Region[]) {
|
|
30
|
-
self.bookmarkedRegions = cast([...self.bookmarkedRegions, ...regions])
|
|
31
|
-
},
|
|
32
|
-
addBookmark(region: Region) {
|
|
33
|
-
self.bookmarkedRegions.push(region)
|
|
34
|
-
},
|
|
35
|
-
removeBookmark(index: number) {
|
|
36
|
-
self.bookmarkedRegions.splice(index, 1)
|
|
37
|
-
},
|
|
38
|
-
clearAllBookmarks() {
|
|
39
|
-
self.bookmarkedRegions.clear()
|
|
40
|
-
},
|
|
41
|
-
updateBookmarkLabel(index: number, label: string) {
|
|
42
|
-
self.bookmarkedRegions[index]?.setLabel(label)
|
|
43
|
-
},
|
|
44
|
-
setSelectedAssembly(assembly: string) {
|
|
45
|
-
self.modelSelectedAssembly = assembly
|
|
46
|
-
},
|
|
47
|
-
}))
|
|
48
|
-
.views(self => ({
|
|
49
|
-
get selectedAssembly() {
|
|
50
|
-
return (
|
|
51
|
-
self.modelSelectedAssembly ||
|
|
52
|
-
(self.bookmarkedRegions.length
|
|
53
|
-
? self.bookmarkedRegions[0].assemblyName
|
|
54
|
-
: '')
|
|
55
|
-
)
|
|
56
|
-
},
|
|
57
|
-
get assemblies() {
|
|
58
|
-
return [
|
|
59
|
-
...new Set(self.bookmarkedRegions.map(region => region.assemblyName)),
|
|
60
|
-
]
|
|
61
|
-
},
|
|
62
|
-
}))
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
export type GridBookmarkStateModel = ReturnType<typeof f>
|
|
66
|
-
export type GridBookmarkModel = Instance<GridBookmarkStateModel>
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
import { saveAs } from 'file-saver'
|
|
2
|
-
import { getSession, assembleLocString } from '@jbrowse/core/util'
|
|
3
|
-
import { LinearGenomeViewModel } from '@jbrowse/plugin-linear-genome-view'
|
|
4
|
-
import { AbstractViewModel } from '@jbrowse/core/util/types'
|
|
5
|
-
|
|
6
|
-
// locals
|
|
7
|
-
import { GridBookmarkModel } from './model'
|
|
8
|
-
import { LabeledRegion } from './types'
|
|
9
|
-
|
|
10
|
-
type LGV = LinearGenomeViewModel
|
|
11
|
-
|
|
12
|
-
type MaybeLGV = LGV | undefined
|
|
13
|
-
|
|
14
|
-
export async function navToBookmark(
|
|
15
|
-
locString: string,
|
|
16
|
-
views: AbstractViewModel[],
|
|
17
|
-
model: GridBookmarkModel,
|
|
18
|
-
) {
|
|
19
|
-
const session = getSession(model)
|
|
20
|
-
try {
|
|
21
|
-
// search for exact match to an lgv that this bookmark widget launched, or
|
|
22
|
-
// any lgv that looks like it is relevant to what we are browsing
|
|
23
|
-
const { selectedAssembly } = model
|
|
24
|
-
const newViewId = `${model.id}_${selectedAssembly}`
|
|
25
|
-
let view = (views.find(
|
|
26
|
-
v => v.type === 'LinearGenomeView' && v.id === newViewId,
|
|
27
|
-
) ||
|
|
28
|
-
views.find(
|
|
29
|
-
v =>
|
|
30
|
-
v.type === 'LinearGenomeView' &&
|
|
31
|
-
// @ts-expect-error
|
|
32
|
-
v.assemblyNames[0] === selectedAssembly,
|
|
33
|
-
)) as MaybeLGV
|
|
34
|
-
|
|
35
|
-
if (!view) {
|
|
36
|
-
view = session.addView('LinearGenomeView', {
|
|
37
|
-
id: newViewId,
|
|
38
|
-
}) as LGV
|
|
39
|
-
}
|
|
40
|
-
await view.navToLocString(locString, selectedAssembly)
|
|
41
|
-
} catch (e) {
|
|
42
|
-
console.error(e)
|
|
43
|
-
session.notify(`${e}`, 'error')
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export function downloadBookmarkFile(
|
|
48
|
-
bookmarkedRegions: LabeledRegion[],
|
|
49
|
-
fileFormat: string,
|
|
50
|
-
model: GridBookmarkModel,
|
|
51
|
-
) {
|
|
52
|
-
const { selectedAssembly } = model
|
|
53
|
-
const fileHeader =
|
|
54
|
-
fileFormat === 'TSV'
|
|
55
|
-
? 'chrom\tstart\tend\tlabel\tassembly_name\tcoord_range\n'
|
|
56
|
-
: ''
|
|
57
|
-
|
|
58
|
-
const fileContents = bookmarkedRegions
|
|
59
|
-
.map(b => {
|
|
60
|
-
const { label } = b
|
|
61
|
-
const labelVal = label === '' ? '.' : label
|
|
62
|
-
const locString = assembleLocString(b)
|
|
63
|
-
|
|
64
|
-
if (fileFormat === 'BED') {
|
|
65
|
-
if (b.assemblyName === selectedAssembly || selectedAssembly === 'all') {
|
|
66
|
-
return `${b.refName}\t${b.start}\t${b.end}\t${labelVal}\n`
|
|
67
|
-
}
|
|
68
|
-
return ''
|
|
69
|
-
} else {
|
|
70
|
-
return `${b.refName}\t${b.start + 1}\t${b.end}\t${labelVal}\t${
|
|
71
|
-
b.assemblyName
|
|
72
|
-
}\t${locString}\n`
|
|
73
|
-
}
|
|
74
|
-
})
|
|
75
|
-
.reduce((a, b) => a + b, fileHeader)
|
|
76
|
-
|
|
77
|
-
const blob = new Blob([fileContents || ''], {
|
|
78
|
-
type:
|
|
79
|
-
fileFormat === 'BED'
|
|
80
|
-
? 'text/x-bed;charset=utf-8'
|
|
81
|
-
: 'text/tab-separated-values;charset=utf-8',
|
|
82
|
-
})
|
|
83
|
-
|
|
84
|
-
const fileName =
|
|
85
|
-
fileFormat === 'BED'
|
|
86
|
-
? `jbrowse_bookmarks_${selectedAssembly}.bed`
|
|
87
|
-
: 'jbrowse_bookmarks.tsv'
|
|
88
|
-
|
|
89
|
-
saveAs(blob, fileName)
|
|
90
|
-
}
|
package/src/index.test.ts
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import PluginManager from '@jbrowse/core/PluginManager'
|
|
2
|
-
import Config from '@jbrowse/plugin-config'
|
|
3
|
-
import { getSnapshot } from 'mobx-state-tree'
|
|
4
|
-
import ThisPlugin from '.'
|
|
5
|
-
|
|
6
|
-
let pluginManager: PluginManager
|
|
7
|
-
|
|
8
|
-
beforeAll(() => {
|
|
9
|
-
pluginManager = new PluginManager([new ThisPlugin(), new Config()])
|
|
10
|
-
pluginManager.createPluggableElements()
|
|
11
|
-
pluginManager.configure()
|
|
12
|
-
})
|
|
13
|
-
|
|
14
|
-
test("won't add if already added", () => {
|
|
15
|
-
expect(() => pluginManager.addPlugin(new ThisPlugin())).toThrow(
|
|
16
|
-
/JBrowse already configured, cannot add plugins/,
|
|
17
|
-
)
|
|
18
|
-
})
|
|
19
|
-
|
|
20
|
-
test('adds grid bookmark widget', () => {
|
|
21
|
-
const GridBookmarkWidget = pluginManager.getWidgetType('GridBookmarkWidget')
|
|
22
|
-
const config = GridBookmarkWidget.configSchema.create({
|
|
23
|
-
type: 'GridBookmarkWidget',
|
|
24
|
-
})
|
|
25
|
-
expect(getSnapshot(config)).toMatchSnapshot()
|
|
26
|
-
})
|