@jbrowse/plugin-linear-genome-view 1.4.4 → 1.5.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/BaseLinearDisplay/models/BaseLinearDisplayModel.d.ts +16 -9
- package/dist/BaseLinearDisplay/models/serverSideRenderedBlock.d.ts +2 -2
- package/dist/LinearBareDisplay/model.d.ts +8 -8
- package/dist/LinearBasicDisplay/model.d.ts +11 -8
- package/dist/LinearGenomeView/components/RefNameAutocomplete.d.ts +0 -10
- package/dist/LinearGenomeView/components/ScaleBar.d.ts +22 -2
- package/dist/LinearGenomeView/components/util.d.ts +2 -0
- package/dist/LinearGenomeView/index.d.ts +13 -2
- package/dist/index.d.ts +26 -26
- package/dist/plugin-linear-genome-view.cjs.development.js +272 -268
- package/dist/plugin-linear-genome-view.cjs.development.js.map +1 -1
- package/dist/plugin-linear-genome-view.cjs.production.min.js +1 -1
- package/dist/plugin-linear-genome-view.cjs.production.min.js.map +1 -1
- package/dist/plugin-linear-genome-view.esm.js +272 -269
- package/dist/plugin-linear-genome-view.esm.js.map +1 -1
- package/package.json +2 -2
- package/src/BaseLinearDisplay/components/BaseLinearDisplay.tsx +3 -0
- package/src/BaseLinearDisplay/models/BaseLinearDisplayModel.tsx +3 -7
- package/src/BaseLinearDisplay/models/serverSideRenderedBlock.ts +15 -13
- package/src/LinearBasicDisplay/model.ts +25 -3
- package/src/LinearGenomeView/components/ExportSvgDialog.tsx +6 -6
- package/src/LinearGenomeView/components/Header.tsx +40 -74
- package/src/LinearGenomeView/components/ImportForm.tsx +124 -134
- package/src/LinearGenomeView/components/LinearGenomeView.test.js +6 -6
- package/src/LinearGenomeView/components/RefNameAutocomplete.tsx +20 -25
- package/src/LinearGenomeView/components/SequenceDialog.tsx +1 -1
- package/src/LinearGenomeView/components/__snapshots__/LinearGenomeView.test.js.snap +0 -176
- package/src/LinearGenomeView/components/util.ts +8 -0
- package/src/LinearGenomeView/index.tsx +14 -13
- package/src/index.ts +3 -1
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import React, { useState } from 'react'
|
|
2
2
|
import { observer } from 'mobx-react'
|
|
3
3
|
import { getSession } from '@jbrowse/core/util'
|
|
4
|
-
|
|
4
|
+
import BaseResult, {
|
|
5
|
+
RefSequenceResult,
|
|
6
|
+
} from '@jbrowse/core/TextSearch/BaseResults'
|
|
5
7
|
import AssemblySelector from '@jbrowse/core/ui/AssemblySelector'
|
|
6
8
|
import {
|
|
7
9
|
Button,
|
|
@@ -15,6 +17,7 @@ import {
|
|
|
15
17
|
import RefNameAutocomplete from './RefNameAutocomplete'
|
|
16
18
|
import SearchResultsDialog from './SearchResultsDialog'
|
|
17
19
|
import { LinearGenomeViewModel } from '..'
|
|
20
|
+
import { dedupe } from './util'
|
|
18
21
|
|
|
19
22
|
const useStyles = makeStyles(theme => ({
|
|
20
23
|
importFormContainer: {
|
|
@@ -55,10 +58,19 @@ const ImportForm = observer(({ model }: { model: LGV }) => {
|
|
|
55
58
|
: 'No configured assemblies'
|
|
56
59
|
const regions = assembly?.regions || []
|
|
57
60
|
const err = assemblyError || error
|
|
58
|
-
|
|
59
|
-
const [
|
|
60
|
-
|
|
61
|
-
|
|
61
|
+
|
|
62
|
+
const [myOption, setOption] = useState<BaseResult | undefined>()
|
|
63
|
+
|
|
64
|
+
// use this instead of useState initializer because the useState initializer
|
|
65
|
+
// won't update in response to an observable
|
|
66
|
+
const option =
|
|
67
|
+
myOption ||
|
|
68
|
+
new RefSequenceResult({
|
|
69
|
+
refName: regions[0]?.refName,
|
|
70
|
+
label: regions[0]?.refName,
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
const selectedRegion = option?.getLocation()
|
|
62
74
|
|
|
63
75
|
async function fetchResults(queryString: string) {
|
|
64
76
|
if (!textSearchManager) {
|
|
@@ -73,153 +85,131 @@ const ImportForm = observer(({ model }: { model: LGV }) => {
|
|
|
73
85
|
rankSearchResults,
|
|
74
86
|
)
|
|
75
87
|
|
|
76
|
-
return results
|
|
77
|
-
(elem, index, self) =>
|
|
78
|
-
index === self.findIndex(t => t.getId() === elem.getId()),
|
|
79
|
-
)
|
|
88
|
+
return dedupe(results)
|
|
80
89
|
}
|
|
90
|
+
|
|
81
91
|
/**
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
* if
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
* textSearchManager
|
|
88
|
-
* 3) if we get any hits by requerying the textSearchManager, then we either
|
|
89
|
-
* navigate to single hit's location or pop open the the dialog with all the results
|
|
90
|
-
* 4) if there were no hits from requerying, then we use (1) the chosen options'
|
|
91
|
-
* trackId and locStr to navigate and show that track
|
|
92
|
-
* 5) error handling
|
|
93
|
-
* @param input - selectedRegion/result label
|
|
92
|
+
* gets a string as input, or use stored option results from previous query,
|
|
93
|
+
* then re-query and
|
|
94
|
+
* 1) if it has multiple results: pop a dialog
|
|
95
|
+
* 2) if it's a single result navigate to it
|
|
96
|
+
* 3) else assume it's a locstring and navigate to it
|
|
94
97
|
*/
|
|
95
98
|
async function handleSelectedRegion(input: string) {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
} else {
|
|
105
|
-
const results = await fetchResults(input)
|
|
106
|
-
if (results && results.length > 1) {
|
|
107
|
-
model.setSearchResults(results, input.toLowerCase())
|
|
99
|
+
if (!option) {
|
|
100
|
+
return
|
|
101
|
+
}
|
|
102
|
+
let trackId = option.getTrackId()
|
|
103
|
+
let location = input || option.getLocation() || ''
|
|
104
|
+
try {
|
|
105
|
+
if (assembly?.refNames?.includes(location)) {
|
|
106
|
+
model.navToLocString(location, selectedAsm)
|
|
108
107
|
} else {
|
|
109
|
-
|
|
108
|
+
const results = await fetchResults(input)
|
|
109
|
+
if (results && results.length > 1) {
|
|
110
|
+
model.setSearchResults(results, input.toLowerCase())
|
|
111
|
+
return
|
|
112
|
+
} else if (results?.length === 1) {
|
|
110
113
|
location = results[0].getLocation()
|
|
111
114
|
trackId = results[0].getTrackId()
|
|
112
115
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
} catch (e) {
|
|
118
|
-
if (`${e}` === `Error: Unknown reference sequence "${input}"`) {
|
|
119
|
-
model.setSearchResults(results, input.toLocaleLowerCase())
|
|
120
|
-
} else {
|
|
121
|
-
console.warn(e)
|
|
122
|
-
session.notify(`${e}`, 'warning')
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
try {
|
|
126
|
-
if (trackId) {
|
|
127
|
-
model.showTrack(trackId)
|
|
128
|
-
}
|
|
129
|
-
} catch (e) {
|
|
130
|
-
console.warn(
|
|
131
|
-
`'${e}' occurred while attempting to show track: ${trackId}`,
|
|
132
|
-
)
|
|
116
|
+
|
|
117
|
+
model.navToLocString(location, selectedAsm)
|
|
118
|
+
if (trackId) {
|
|
119
|
+
model.showTrack(trackId)
|
|
133
120
|
}
|
|
134
121
|
}
|
|
122
|
+
} catch (e) {
|
|
123
|
+
console.error(e)
|
|
124
|
+
session.notify(`${e}`, 'warning')
|
|
135
125
|
}
|
|
136
126
|
}
|
|
137
127
|
|
|
128
|
+
// implementation notes:
|
|
129
|
+
// having this wrapped in a form allows intuitive use of enter key to submit
|
|
138
130
|
return (
|
|
139
131
|
<div>
|
|
140
132
|
{err ? <ErrorDisplay error={err} /> : null}
|
|
141
133
|
<Container className={classes.importFormContainer}>
|
|
142
|
-
<
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
>
|
|
219
|
-
Show all regions in assembly
|
|
220
|
-
</Button>
|
|
134
|
+
<form
|
|
135
|
+
onSubmit={event => {
|
|
136
|
+
event.preventDefault()
|
|
137
|
+
}}
|
|
138
|
+
>
|
|
139
|
+
<Grid
|
|
140
|
+
container
|
|
141
|
+
spacing={1}
|
|
142
|
+
justifyContent="center"
|
|
143
|
+
alignItems="center"
|
|
144
|
+
>
|
|
145
|
+
<Grid item>
|
|
146
|
+
<AssemblySelector
|
|
147
|
+
onChange={val => {
|
|
148
|
+
setError(undefined)
|
|
149
|
+
setSelectedAsm(val)
|
|
150
|
+
}}
|
|
151
|
+
session={session}
|
|
152
|
+
selected={selectedAsm}
|
|
153
|
+
/>
|
|
154
|
+
</Grid>
|
|
155
|
+
<Grid item>
|
|
156
|
+
{selectedAsm ? (
|
|
157
|
+
err ? (
|
|
158
|
+
<Typography color="error">X</Typography>
|
|
159
|
+
) : selectedRegion && model.volatileWidth ? (
|
|
160
|
+
<RefNameAutocomplete
|
|
161
|
+
model={model}
|
|
162
|
+
assemblyName={message ? undefined : selectedAsm}
|
|
163
|
+
value={selectedRegion}
|
|
164
|
+
onSelect={option => {
|
|
165
|
+
setOption(option)
|
|
166
|
+
}}
|
|
167
|
+
TextFieldProps={{
|
|
168
|
+
margin: 'normal',
|
|
169
|
+
variant: 'outlined',
|
|
170
|
+
helperText: 'Enter a sequence or location',
|
|
171
|
+
}}
|
|
172
|
+
/>
|
|
173
|
+
) : (
|
|
174
|
+
<CircularProgress
|
|
175
|
+
role="progressbar"
|
|
176
|
+
size={20}
|
|
177
|
+
disableShrink
|
|
178
|
+
/>
|
|
179
|
+
)
|
|
180
|
+
) : null}
|
|
181
|
+
</Grid>
|
|
182
|
+
<Grid item>
|
|
183
|
+
<Button
|
|
184
|
+
type="submit"
|
|
185
|
+
disabled={!selectedRegion}
|
|
186
|
+
className={classes.button}
|
|
187
|
+
onClick={() => {
|
|
188
|
+
model.setError(undefined)
|
|
189
|
+
if (selectedRegion) {
|
|
190
|
+
handleSelectedRegion(selectedRegion)
|
|
191
|
+
}
|
|
192
|
+
}}
|
|
193
|
+
variant="contained"
|
|
194
|
+
color="primary"
|
|
195
|
+
>
|
|
196
|
+
Open
|
|
197
|
+
</Button>
|
|
198
|
+
<Button
|
|
199
|
+
disabled={!selectedRegion}
|
|
200
|
+
className={classes.button}
|
|
201
|
+
onClick={() => {
|
|
202
|
+
model.setError(undefined)
|
|
203
|
+
model.showAllRegionsInAssembly(selectedAsm)
|
|
204
|
+
}}
|
|
205
|
+
variant="contained"
|
|
206
|
+
color="secondary"
|
|
207
|
+
>
|
|
208
|
+
Show all regions in assembly
|
|
209
|
+
</Button>
|
|
210
|
+
</Grid>
|
|
221
211
|
</Grid>
|
|
222
|
-
</
|
|
212
|
+
</form>
|
|
223
213
|
</Container>
|
|
224
214
|
{isSearchDialogDisplayed ? (
|
|
225
215
|
<SearchResultsDialog
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
|
-
import { render } from '@testing-library/react'
|
|
2
|
+
import { fireEvent, render, waitFor } from '@testing-library/react'
|
|
3
3
|
import { createTestSession } from '@jbrowse/web/src/rootModel'
|
|
4
4
|
import sizeMe from 'react-sizeme'
|
|
5
5
|
import 'requestidlecallback-polyfill'
|
|
@@ -34,12 +34,12 @@ describe('<LinearGenomeView />', () => {
|
|
|
34
34
|
session.addView('LinearGenomeView', { id: 'lgv' })
|
|
35
35
|
const model = session.views[0]
|
|
36
36
|
model.setWidth(800)
|
|
37
|
-
const {
|
|
38
|
-
const openButton = await findByText('Open')
|
|
39
|
-
expect(container.firstChild).toMatchSnapshot()
|
|
37
|
+
const { findByText } = render(<LinearGenomeView model={model} />)
|
|
40
38
|
expect(model.displayedRegions.length).toEqual(0)
|
|
41
|
-
|
|
42
|
-
|
|
39
|
+
fireEvent.click(await findByText('Open'))
|
|
40
|
+
await waitFor(() => {
|
|
41
|
+
expect(model.displayedRegions.length).toEqual(1)
|
|
42
|
+
})
|
|
43
43
|
})
|
|
44
44
|
it('renders one track, one region', async () => {
|
|
45
45
|
const session = createTestSession()
|
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Based on:
|
|
3
|
-
* https://material-ui.com/components/autocomplete/#Virtualize.tsx
|
|
4
|
-
* Asynchronous Requests for autocomplete:
|
|
5
|
-
* https://material-ui.com/components/autocomplete/
|
|
6
|
-
*/
|
|
7
1
|
import React, { useMemo, useEffect, useState } from 'react'
|
|
8
2
|
import { observer } from 'mobx-react'
|
|
9
3
|
|
|
@@ -29,10 +23,6 @@ import Autocomplete from '@material-ui/lab/Autocomplete'
|
|
|
29
23
|
// locals
|
|
30
24
|
import { LinearGenomeViewModel } from '..'
|
|
31
25
|
|
|
32
|
-
/**
|
|
33
|
-
* Option interface used to format results to display in dropdown
|
|
34
|
-
* of the materila ui interface
|
|
35
|
-
*/
|
|
36
26
|
export interface Option {
|
|
37
27
|
group?: string
|
|
38
28
|
result: BaseResult
|
|
@@ -64,8 +54,8 @@ async function fetchResults(
|
|
|
64
54
|
}
|
|
65
55
|
|
|
66
56
|
// the logic of this method is to only apply a filter to RefSequenceResults
|
|
67
|
-
// because they do not have a matchedObject. the trix search results
|
|
68
|
-
//
|
|
57
|
+
// because they do not have a matchedObject. the trix search results already
|
|
58
|
+
// filter so don't need re-filtering
|
|
69
59
|
function filterOptions(options: Option[], searchQuery: string) {
|
|
70
60
|
return options.filter(option => {
|
|
71
61
|
const { result } = option
|
|
@@ -115,6 +105,7 @@ function RefNameAutocomplete({
|
|
|
115
105
|
const [open, setOpen] = useState(false)
|
|
116
106
|
const [loaded, setLoaded] = useState(true)
|
|
117
107
|
const [currentSearch, setCurrentSearch] = useState('')
|
|
108
|
+
const [inputValue, setInputValue] = useState('')
|
|
118
109
|
const [searchOptions, setSearchOptions] = useState([] as Option[])
|
|
119
110
|
const debouncedSearch = useDebounce(currentSearch, 300)
|
|
120
111
|
const { coarseVisibleLocStrings, hasDisplayedRegions } = model
|
|
@@ -146,10 +137,12 @@ function RefNameAutocomplete({
|
|
|
146
137
|
|
|
147
138
|
setLoaded(false)
|
|
148
139
|
const results = await fetchResults(model, debouncedSearch, assemblyName)
|
|
149
|
-
if (
|
|
150
|
-
|
|
140
|
+
if (active) {
|
|
141
|
+
if (results && results.length >= 0) {
|
|
142
|
+
setSearchOptions(results.map(result => ({ result })))
|
|
143
|
+
}
|
|
144
|
+
setLoaded(true)
|
|
151
145
|
}
|
|
152
|
-
setLoaded(true)
|
|
153
146
|
} catch (e) {
|
|
154
147
|
console.error(e)
|
|
155
148
|
if (active) {
|
|
@@ -169,9 +162,7 @@ function RefNameAutocomplete({
|
|
|
169
162
|
const width = Math.min(Math.max(measureText(inputBoxVal, 16) + 25, 200), 550)
|
|
170
163
|
|
|
171
164
|
// notes on implementation:
|
|
172
|
-
// selectOnFocus helps highlight the field when clicked
|
|
173
|
-
// blurOnSelect helps it so that when the user-re-clicks on the textfield,
|
|
174
|
-
// that selectOnFocus re-activates
|
|
165
|
+
// The selectOnFocus setting helps highlight the field when clicked
|
|
175
166
|
return (
|
|
176
167
|
<Autocomplete
|
|
177
168
|
id={`refNameAutocomplete-${model.id}`}
|
|
@@ -183,10 +174,11 @@ function RefNameAutocomplete({
|
|
|
183
174
|
freeSolo
|
|
184
175
|
includeInputInList
|
|
185
176
|
selectOnFocus
|
|
186
|
-
blurOnSelect
|
|
187
177
|
style={{ ...style, width }}
|
|
188
178
|
value={inputBoxVal}
|
|
189
179
|
loading={!loaded}
|
|
180
|
+
inputValue={inputValue}
|
|
181
|
+
onInputChange={(event, newInputValue) => setInputValue(newInputValue)}
|
|
190
182
|
loadingText="loading results"
|
|
191
183
|
open={open}
|
|
192
184
|
onOpen={() => setOpen(true)}
|
|
@@ -202,16 +194,14 @@ function RefNameAutocomplete({
|
|
|
202
194
|
if (!selectedOption || !assemblyName) {
|
|
203
195
|
return
|
|
204
196
|
}
|
|
197
|
+
|
|
205
198
|
if (typeof selectedOption === 'string') {
|
|
206
199
|
// handles string inputs on keyPress enter
|
|
207
|
-
|
|
208
|
-
label: selectedOption,
|
|
209
|
-
})
|
|
210
|
-
onSelect(newResult)
|
|
200
|
+
onSelect(new BaseResult({ label: selectedOption }))
|
|
211
201
|
} else {
|
|
212
|
-
|
|
213
|
-
onSelect(result)
|
|
202
|
+
onSelect(selectedOption.result)
|
|
214
203
|
}
|
|
204
|
+
setInputValue(inputBoxVal)
|
|
215
205
|
}}
|
|
216
206
|
options={searchOptions.length === 0 ? options : searchOptions}
|
|
217
207
|
getOptionDisabled={option => option?.group === 'limitOption'}
|
|
@@ -238,6 +228,11 @@ function RefNameAutocomplete({
|
|
|
238
228
|
const { helperText, InputProps = {} } = TextFieldProps
|
|
239
229
|
return (
|
|
240
230
|
<TextField
|
|
231
|
+
onBlur={() => {
|
|
232
|
+
// this is used to restore a refName or the non-user-typed input
|
|
233
|
+
// to the box on blurring
|
|
234
|
+
setInputValue(inputBoxVal)
|
|
235
|
+
}}
|
|
241
236
|
{...params}
|
|
242
237
|
{...TextFieldProps}
|
|
243
238
|
helperText={helperText}
|
|
@@ -101,7 +101,7 @@ function SequenceDialog({
|
|
|
101
101
|
}) {
|
|
102
102
|
const classes = useStyles()
|
|
103
103
|
const session = getSession(model)
|
|
104
|
-
const [error, setError] = useState<
|
|
104
|
+
const [error, setError] = useState<unknown>()
|
|
105
105
|
const [sequence, setSequence] = useState<string>()
|
|
106
106
|
const loading = Boolean(sequence === undefined)
|
|
107
107
|
const { leftOffset, rightOffset } = model
|
|
@@ -563,182 +563,6 @@ exports[`<LinearGenomeView /> renders one track, one region 1`] = `
|
|
|
563
563
|
</div>
|
|
564
564
|
`;
|
|
565
565
|
|
|
566
|
-
exports[`<LinearGenomeView /> renders setup wizard 1`] = `
|
|
567
|
-
<div>
|
|
568
|
-
<div
|
|
569
|
-
class="MuiContainer-root makeStyles-importFormContainer MuiContainer-maxWidthLg"
|
|
570
|
-
>
|
|
571
|
-
<div
|
|
572
|
-
class="MuiGrid-root MuiGrid-container MuiGrid-spacing-xs-1 MuiGrid-align-items-xs-center MuiGrid-justify-content-xs-center"
|
|
573
|
-
>
|
|
574
|
-
<div
|
|
575
|
-
class="MuiGrid-root MuiGrid-item"
|
|
576
|
-
>
|
|
577
|
-
<div
|
|
578
|
-
class="MuiFormControl-root MuiTextField-root makeStyles-importFormEntry MuiFormControl-marginNormal"
|
|
579
|
-
>
|
|
580
|
-
<label
|
|
581
|
-
class="MuiFormLabel-root MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-shrink MuiInputLabel-outlined MuiFormLabel-filled"
|
|
582
|
-
data-shrink="true"
|
|
583
|
-
>
|
|
584
|
-
Assembly
|
|
585
|
-
</label>
|
|
586
|
-
<div
|
|
587
|
-
class="MuiInputBase-root MuiOutlinedInput-root MuiInputBase-formControl"
|
|
588
|
-
>
|
|
589
|
-
<div
|
|
590
|
-
aria-haspopup="listbox"
|
|
591
|
-
class="MuiSelect-root MuiSelect-select MuiSelect-selectMenu MuiSelect-outlined MuiInputBase-input MuiOutlinedInput-input"
|
|
592
|
-
role="button"
|
|
593
|
-
tabindex="0"
|
|
594
|
-
>
|
|
595
|
-
volMyt1
|
|
596
|
-
</div>
|
|
597
|
-
<input
|
|
598
|
-
aria-hidden="true"
|
|
599
|
-
class="MuiSelect-nativeInput"
|
|
600
|
-
data-testid="assembly-selector"
|
|
601
|
-
tabindex="-1"
|
|
602
|
-
value="volMyt1"
|
|
603
|
-
/>
|
|
604
|
-
<svg
|
|
605
|
-
aria-hidden="true"
|
|
606
|
-
class="MuiSvgIcon-root MuiSelect-icon MuiSelect-iconOutlined"
|
|
607
|
-
focusable="false"
|
|
608
|
-
viewBox="0 0 24 24"
|
|
609
|
-
>
|
|
610
|
-
<path
|
|
611
|
-
d="M7 10l5 5 5-5z"
|
|
612
|
-
/>
|
|
613
|
-
</svg>
|
|
614
|
-
<fieldset
|
|
615
|
-
aria-hidden="true"
|
|
616
|
-
class="PrivateNotchedOutline-root MuiOutlinedInput-notchedOutline"
|
|
617
|
-
>
|
|
618
|
-
<legend
|
|
619
|
-
class="PrivateNotchedOutline-legendLabelled PrivateNotchedOutline-legendNotched"
|
|
620
|
-
>
|
|
621
|
-
<span>
|
|
622
|
-
Assembly
|
|
623
|
-
</span>
|
|
624
|
-
</legend>
|
|
625
|
-
</fieldset>
|
|
626
|
-
</div>
|
|
627
|
-
<p
|
|
628
|
-
class="MuiFormHelperText-root MuiFormHelperText-contained MuiFormHelperText-filled"
|
|
629
|
-
>
|
|
630
|
-
Select assembly to view
|
|
631
|
-
</p>
|
|
632
|
-
</div>
|
|
633
|
-
</div>
|
|
634
|
-
<div
|
|
635
|
-
class="MuiGrid-root MuiGrid-item"
|
|
636
|
-
>
|
|
637
|
-
<div
|
|
638
|
-
aria-expanded="false"
|
|
639
|
-
class="MuiAutocomplete-root"
|
|
640
|
-
data-testid="autocomplete"
|
|
641
|
-
role="combobox"
|
|
642
|
-
style="width: 200px;"
|
|
643
|
-
>
|
|
644
|
-
<div
|
|
645
|
-
class="MuiFormControl-root MuiTextField-root MuiFormControl-marginNormal MuiFormControl-fullWidth"
|
|
646
|
-
>
|
|
647
|
-
<div
|
|
648
|
-
class="MuiInputBase-root MuiOutlinedInput-root MuiAutocomplete-inputRoot MuiInputBase-fullWidth MuiInputBase-formControl MuiInputBase-adornedEnd MuiOutlinedInput-adornedEnd"
|
|
649
|
-
>
|
|
650
|
-
<input
|
|
651
|
-
aria-autocomplete="list"
|
|
652
|
-
aria-describedby="refNameAutocomplete-lgv-helper-text"
|
|
653
|
-
aria-invalid="false"
|
|
654
|
-
autocapitalize="none"
|
|
655
|
-
autocomplete="off"
|
|
656
|
-
class="MuiInputBase-input MuiOutlinedInput-input MuiAutocomplete-input MuiAutocomplete-inputFocused MuiInputBase-inputAdornedEnd MuiOutlinedInput-inputAdornedEnd"
|
|
657
|
-
id="refNameAutocomplete-lgv"
|
|
658
|
-
placeholder="Search for location"
|
|
659
|
-
spellcheck="false"
|
|
660
|
-
type="text"
|
|
661
|
-
value="ctgA"
|
|
662
|
-
/>
|
|
663
|
-
<div
|
|
664
|
-
class="MuiInputAdornment-root MuiInputAdornment-positionEnd"
|
|
665
|
-
style="margin-right: 7px;"
|
|
666
|
-
>
|
|
667
|
-
<svg
|
|
668
|
-
aria-hidden="true"
|
|
669
|
-
class="MuiSvgIcon-root"
|
|
670
|
-
focusable="false"
|
|
671
|
-
viewBox="0 0 24 24"
|
|
672
|
-
>
|
|
673
|
-
<path
|
|
674
|
-
d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"
|
|
675
|
-
/>
|
|
676
|
-
</svg>
|
|
677
|
-
</div>
|
|
678
|
-
<div
|
|
679
|
-
class="MuiAutocomplete-endAdornment"
|
|
680
|
-
/>
|
|
681
|
-
<fieldset
|
|
682
|
-
aria-hidden="true"
|
|
683
|
-
class="PrivateNotchedOutline-root MuiOutlinedInput-notchedOutline"
|
|
684
|
-
style="padding-left: 8px;"
|
|
685
|
-
>
|
|
686
|
-
<legend
|
|
687
|
-
class="PrivateNotchedOutline-legend"
|
|
688
|
-
style="width: 0.01px;"
|
|
689
|
-
>
|
|
690
|
-
<span>
|
|
691
|
-
|
|
692
|
-
</span>
|
|
693
|
-
</legend>
|
|
694
|
-
</fieldset>
|
|
695
|
-
</div>
|
|
696
|
-
<p
|
|
697
|
-
class="MuiFormHelperText-root MuiFormHelperText-contained MuiFormHelperText-filled"
|
|
698
|
-
id="refNameAutocomplete-lgv-helper-text"
|
|
699
|
-
>
|
|
700
|
-
Enter a sequence or location
|
|
701
|
-
</p>
|
|
702
|
-
</div>
|
|
703
|
-
</div>
|
|
704
|
-
</div>
|
|
705
|
-
<div
|
|
706
|
-
class="MuiGrid-root MuiGrid-item"
|
|
707
|
-
>
|
|
708
|
-
<button
|
|
709
|
-
class="MuiButtonBase-root MuiButton-root MuiButton-contained makeStyles-button MuiButton-containedPrimary"
|
|
710
|
-
tabindex="0"
|
|
711
|
-
type="button"
|
|
712
|
-
>
|
|
713
|
-
<span
|
|
714
|
-
class="MuiButton-label"
|
|
715
|
-
>
|
|
716
|
-
Open
|
|
717
|
-
</span>
|
|
718
|
-
<span
|
|
719
|
-
class="MuiTouchRipple-root"
|
|
720
|
-
/>
|
|
721
|
-
</button>
|
|
722
|
-
<button
|
|
723
|
-
class="MuiButtonBase-root MuiButton-root MuiButton-contained makeStyles-button MuiButton-containedSecondary"
|
|
724
|
-
tabindex="0"
|
|
725
|
-
type="button"
|
|
726
|
-
>
|
|
727
|
-
<span
|
|
728
|
-
class="MuiButton-label"
|
|
729
|
-
>
|
|
730
|
-
Show all regions in assembly
|
|
731
|
-
</span>
|
|
732
|
-
<span
|
|
733
|
-
class="MuiTouchRipple-root"
|
|
734
|
-
/>
|
|
735
|
-
</button>
|
|
736
|
-
</div>
|
|
737
|
-
</div>
|
|
738
|
-
</div>
|
|
739
|
-
</div>
|
|
740
|
-
`;
|
|
741
|
-
|
|
742
566
|
exports[`<LinearGenomeView /> renders two tracks, two regions 1`] = `
|
|
743
567
|
<div
|
|
744
568
|
style="position: relative;"
|