@apollo-annotation/jbrowse-plugin-apollo 0.3.8 → 0.3.9
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/index.esm.js +10932 -10932
- package/dist/index.esm.js.map +1 -1
- package/dist/jbrowse-plugin-apollo.cjs.development.js +10845 -10846
- package/dist/jbrowse-plugin-apollo.cjs.development.js.map +1 -1
- package/dist/jbrowse-plugin-apollo.cjs.production.min.js +1 -1
- package/dist/jbrowse-plugin-apollo.cjs.production.min.js.map +1 -1
- package/dist/jbrowse-plugin-apollo.umd.development.js +18619 -21342
- package/dist/jbrowse-plugin-apollo.umd.development.js.map +1 -1
- package/dist/jbrowse-plugin-apollo.umd.production.min.js +1 -1
- package/dist/jbrowse-plugin-apollo.umd.production.min.js.map +1 -1
- package/package.json +7 -7
- package/src/ApolloInternetAccount/model.ts +81 -63
- package/src/ApolloRefNameAliasAdapter/ApolloRefNameAliasAdapter.ts +4 -4
- package/src/ApolloSequenceAdapter/ApolloSequenceAdapter.ts +9 -7
- package/src/BackendDrivers/CollaborationServerDriver.ts +49 -18
- package/src/BackendDrivers/DesktopFileDriver.ts +2 -2
- package/src/ChangeManager.ts +3 -1
- package/src/FeatureDetailsWidget/BasicInformation.tsx +6 -4
- package/src/FeatureDetailsWidget/NumberTextField.tsx +5 -2
- package/src/FeatureDetailsWidget/TranscriptWidgetEditLocation.tsx +39 -203
- package/src/LinearApolloDisplay/components/CheckResultWarnings.tsx +92 -0
- package/src/LinearApolloDisplay/components/LinearApolloDisplay.tsx +6 -102
- package/src/LinearApolloDisplay/glyphs/GeneGlyph.ts +31 -230
- package/src/LinearApolloDisplay/glyphs/util.ts +19 -0
- package/src/LinearApolloReferenceSequenceDisplay/drawSequenceOverlay.ts +181 -0
- package/src/LinearApolloReferenceSequenceDisplay/drawSequenceTrack.ts +218 -0
- package/src/LinearApolloReferenceSequenceDisplay/stateModel/rendering.ts +62 -386
- package/src/LinearApolloSixFrameDisplay/components/LinearApolloSixFrameDisplay.tsx +6 -0
- package/src/LinearApolloSixFrameDisplay/glyphs/GeneGlyph.ts +122 -70
- package/src/components/AddAssembly.tsx +33 -37
- package/src/components/AddFeature.tsx +21 -18
- package/src/components/AddRefSeqAliases.tsx +56 -42
- package/src/components/CopyFeature.tsx +1 -1
- package/src/components/CreateApolloAnnotation.tsx +22 -10
- package/src/components/DeleteAssembly.tsx +2 -9
- package/src/components/DownloadGFF3.tsx +2 -2
- package/src/components/ManageChecks.tsx +2 -9
- package/src/components/ManageUsers.tsx +23 -22
- package/src/components/OntologyTermAutocomplete.tsx +1 -8
- package/src/components/ViewChangeLog.tsx +25 -50
- package/src/components/ViewCheckResults.tsx +1 -7
- package/src/config.ts +3 -3
- package/src/index.ts +17 -16
- package/src/makeDisplayComponent.tsx +9 -13
- package/src/session/ClientDataStore.ts +32 -14
- package/src/session/session.ts +19 -27
- package/src/util/glyphUtils.ts +178 -1
- package/src/util/loadAssemblyIntoClient.ts +3 -2
|
@@ -149,66 +149,18 @@ export const TranscriptWidgetEditLocation = observer(
|
|
|
149
149
|
cdsMax = sortedCDSLocations[sortedCDSLocations.length - 1].max
|
|
150
150
|
}
|
|
151
151
|
|
|
152
|
-
|
|
152
|
+
const updateCDSLocation = (
|
|
153
153
|
oldLocation: number,
|
|
154
154
|
newLocation: number,
|
|
155
155
|
feature: AnnotationFeature,
|
|
156
156
|
isMin: boolean,
|
|
157
|
-
|
|
157
|
+
onComplete?: () => void,
|
|
158
|
+
): boolean => {
|
|
158
159
|
if (!feature.children) {
|
|
159
160
|
throw new Error('Transcript should have child features')
|
|
160
161
|
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
feature,
|
|
164
|
-
featureTypeOntology,
|
|
165
|
-
oldLocation,
|
|
166
|
-
isMin,
|
|
167
|
-
)
|
|
168
|
-
if (!overlappingExon) {
|
|
169
|
-
notify('No matching exon found', 'error')
|
|
170
|
-
return
|
|
171
|
-
}
|
|
172
|
-
const oldExonLocation = isMin ? overlappingExon.min : overlappingExon.max
|
|
173
|
-
const { prevExon, nextExon } = getNeighboringExonParts(
|
|
174
|
-
feature,
|
|
175
|
-
featureTypeOntology,
|
|
176
|
-
oldExonLocation,
|
|
177
|
-
isMin,
|
|
178
|
-
)
|
|
179
|
-
|
|
180
|
-
// Start location should be less than end location
|
|
181
|
-
if (isMin && newLocation >= overlappingExon.max) {
|
|
182
|
-
notify(
|
|
183
|
-
'Start location should be less than overlapping exon end location',
|
|
184
|
-
'error',
|
|
185
|
-
)
|
|
186
|
-
return
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
// End location should be greater than start location
|
|
190
|
-
if (!isMin && newLocation <= overlappingExon.min) {
|
|
191
|
-
notify(
|
|
192
|
-
'End location should be greater than overlapping exon start location',
|
|
193
|
-
'error',
|
|
194
|
-
)
|
|
195
|
-
return
|
|
196
|
-
}
|
|
197
|
-
// Changed location should be greater than end location of previous exon - give 2bp buffer
|
|
198
|
-
if (prevExon && prevExon.max + 2 > newLocation) {
|
|
199
|
-
notify(
|
|
200
|
-
'Start location should be greater than previous exon end location',
|
|
201
|
-
'error',
|
|
202
|
-
)
|
|
203
|
-
return
|
|
204
|
-
}
|
|
205
|
-
// Changed location should be less than start location of next exon
|
|
206
|
-
if (nextExon && nextExon.min - 2 < newLocation) {
|
|
207
|
-
notify(
|
|
208
|
-
'End location should be less than next exon start location',
|
|
209
|
-
'error',
|
|
210
|
-
)
|
|
211
|
-
return
|
|
162
|
+
if (oldLocation === newLocation) {
|
|
163
|
+
return true
|
|
212
164
|
}
|
|
213
165
|
|
|
214
166
|
const cdsFeature = getMatchingCDSFeature(
|
|
@@ -217,10 +169,14 @@ export const TranscriptWidgetEditLocation = observer(
|
|
|
217
169
|
oldLocation,
|
|
218
170
|
isMin,
|
|
219
171
|
)
|
|
220
|
-
|
|
221
172
|
if (!cdsFeature) {
|
|
222
173
|
notify('No matching CDS feature found', 'error')
|
|
223
|
-
return
|
|
174
|
+
return false
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (isMin && newLocation >= cdsFeature.max) {
|
|
178
|
+
notify('Start location should be less than CDS end location', 'error')
|
|
179
|
+
return false
|
|
224
180
|
}
|
|
225
181
|
|
|
226
182
|
if (!isMin && newLocation <= cdsFeature.min) {
|
|
@@ -228,145 +184,23 @@ export const TranscriptWidgetEditLocation = observer(
|
|
|
228
184
|
'End location should be greater than CDS start location',
|
|
229
185
|
'error',
|
|
230
186
|
)
|
|
231
|
-
return
|
|
232
|
-
}
|
|
233
|
-
if (isMin && newLocation >= cdsFeature.max) {
|
|
234
|
-
notify('Start location should be less than CDS end location', 'error')
|
|
235
|
-
return
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
const overlappingExonFeature = getExonFeature(
|
|
239
|
-
feature,
|
|
240
|
-
overlappingExon.min,
|
|
241
|
-
overlappingExon.max,
|
|
242
|
-
featureTypeOntology,
|
|
243
|
-
)
|
|
244
|
-
|
|
245
|
-
if (!overlappingExonFeature) {
|
|
246
|
-
notify('No matching exon feature found', 'error')
|
|
247
|
-
return
|
|
187
|
+
return false
|
|
248
188
|
}
|
|
249
189
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
typeName: 'LocationStartChange',
|
|
253
|
-
changedIds: [],
|
|
254
|
-
changes: [],
|
|
255
|
-
assembly,
|
|
256
|
-
})
|
|
257
|
-
|
|
258
|
-
if (newLocation < overlappingExon.min) {
|
|
259
|
-
if (prevExon) {
|
|
260
|
-
// update exon start location
|
|
261
|
-
appendStartLocationChange(
|
|
262
|
-
overlappingExonFeature,
|
|
263
|
-
startChange,
|
|
264
|
-
newLocation,
|
|
265
|
-
)
|
|
266
|
-
// update CDS start location
|
|
267
|
-
appendStartLocationChange(cdsFeature, startChange, newLocation)
|
|
268
|
-
} else {
|
|
269
|
-
const transcriptStart = feature.min
|
|
270
|
-
const gene = feature.parent
|
|
271
|
-
if (newLocation < transcriptStart) {
|
|
272
|
-
if (gene && newLocation < gene.min) {
|
|
273
|
-
// update gene start location
|
|
274
|
-
appendStartLocationChange(gene, startChange, newLocation)
|
|
275
|
-
}
|
|
276
|
-
// update transcript start location
|
|
277
|
-
appendStartLocationChange(feature, startChange, newLocation)
|
|
278
|
-
// update exon start location
|
|
279
|
-
appendStartLocationChange(
|
|
280
|
-
overlappingExonFeature,
|
|
281
|
-
startChange,
|
|
282
|
-
newLocation,
|
|
283
|
-
)
|
|
284
|
-
// update CDS start location
|
|
285
|
-
appendStartLocationChange(cdsFeature, startChange, newLocation)
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
} else {
|
|
289
|
-
// update CDS start location
|
|
290
|
-
appendStartLocationChange(cdsFeature, startChange, newLocation)
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
void changeManager.submit(startChange).catch(() => {
|
|
294
|
-
notify('Error updating feature CDS start position', 'error')
|
|
295
|
-
})
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
if (!isMin && newLocation !== cdsFeature.max) {
|
|
299
|
-
const endChange: LocationEndChange = new LocationEndChange({
|
|
300
|
-
typeName: 'LocationEndChange',
|
|
301
|
-
changedIds: [],
|
|
302
|
-
changes: [],
|
|
303
|
-
assembly,
|
|
304
|
-
})
|
|
305
|
-
|
|
306
|
-
if (newLocation > overlappingExon.max) {
|
|
307
|
-
if (nextExon) {
|
|
308
|
-
// update exon end location
|
|
309
|
-
appendEndLocationChange(
|
|
310
|
-
overlappingExonFeature,
|
|
311
|
-
endChange,
|
|
312
|
-
newLocation,
|
|
313
|
-
)
|
|
314
|
-
// update CDS end location
|
|
315
|
-
appendEndLocationChange(cdsFeature, endChange, newLocation)
|
|
316
|
-
} else {
|
|
317
|
-
const transcriptEnd = feature.max
|
|
318
|
-
const gene = feature.parent
|
|
319
|
-
if (newLocation > transcriptEnd) {
|
|
320
|
-
if (gene && newLocation > gene.max) {
|
|
321
|
-
// update gene end location
|
|
322
|
-
appendEndLocationChange(gene, endChange, newLocation)
|
|
323
|
-
}
|
|
324
|
-
// update transcript end location
|
|
325
|
-
appendEndLocationChange(feature, endChange, newLocation)
|
|
326
|
-
// update exon end location
|
|
327
|
-
appendEndLocationChange(
|
|
328
|
-
overlappingExonFeature,
|
|
329
|
-
endChange,
|
|
330
|
-
newLocation,
|
|
331
|
-
)
|
|
332
|
-
// update CDS end location
|
|
333
|
-
appendEndLocationChange(cdsFeature, endChange, newLocation)
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
} else {
|
|
337
|
-
// update CDS end location
|
|
338
|
-
appendEndLocationChange(cdsFeature, endChange, newLocation)
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
void changeManager.submit(endChange).catch(() => {
|
|
342
|
-
notify('Error updating feature CDS end position', 'error')
|
|
343
|
-
})
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
const updateCDSLocation = (
|
|
348
|
-
oldLocation: number,
|
|
349
|
-
newLocation: number,
|
|
350
|
-
feature: AnnotationFeature,
|
|
351
|
-
isMin: boolean,
|
|
352
|
-
onComplete?: () => void,
|
|
353
|
-
) => {
|
|
354
|
-
if (!feature.children) {
|
|
355
|
-
throw new Error('Transcript should have child features')
|
|
356
|
-
}
|
|
357
|
-
if (oldLocation === newLocation) {
|
|
358
|
-
return
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
const cdsFeature = getMatchingCDSFeature(
|
|
190
|
+
// overlapping exon of new CDS location
|
|
191
|
+
const overlappingExon = getOverlappingExonForCDS(
|
|
362
192
|
feature,
|
|
363
193
|
featureTypeOntology,
|
|
364
|
-
|
|
194
|
+
newLocation,
|
|
365
195
|
isMin,
|
|
366
196
|
)
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
197
|
+
|
|
198
|
+
if (!overlappingExon) {
|
|
199
|
+
notify(
|
|
200
|
+
'There should be an overlapping exon for the new CDS location',
|
|
201
|
+
'error',
|
|
202
|
+
)
|
|
203
|
+
return false
|
|
370
204
|
}
|
|
371
205
|
|
|
372
206
|
const change = isMin
|
|
@@ -397,6 +231,7 @@ export const TranscriptWidgetEditLocation = observer(
|
|
|
397
231
|
.catch(() => {
|
|
398
232
|
notify('Error updating feature CDS position', 'error')
|
|
399
233
|
})
|
|
234
|
+
return true
|
|
400
235
|
}
|
|
401
236
|
|
|
402
237
|
function handleExonLocationChange(
|
|
@@ -404,7 +239,7 @@ export const TranscriptWidgetEditLocation = observer(
|
|
|
404
239
|
newLocation: number,
|
|
405
240
|
feature: AnnotationFeature,
|
|
406
241
|
isMin: boolean,
|
|
407
|
-
) {
|
|
242
|
+
): boolean {
|
|
408
243
|
if (!feature.children) {
|
|
409
244
|
throw new Error('Transcript should have child features')
|
|
410
245
|
}
|
|
@@ -417,28 +252,28 @@ export const TranscriptWidgetEditLocation = observer(
|
|
|
417
252
|
|
|
418
253
|
if (!matchingExon) {
|
|
419
254
|
notify('No matching exon found', 'error')
|
|
420
|
-
return
|
|
255
|
+
return false
|
|
421
256
|
}
|
|
422
257
|
|
|
423
258
|
// Start location should be less than end location
|
|
424
259
|
if (isMin && newLocation >= matchingExon.max) {
|
|
425
260
|
notify(`Start location should be less than end location`, 'error')
|
|
426
|
-
return
|
|
261
|
+
return false
|
|
427
262
|
}
|
|
428
263
|
// End location should be greater than start location
|
|
429
264
|
if (!isMin && newLocation <= matchingExon.min) {
|
|
430
265
|
notify(`End location should be greater than start location`, 'error')
|
|
431
|
-
return
|
|
266
|
+
return false
|
|
432
267
|
}
|
|
433
268
|
// Changed location should be greater than end location of previous exon - give 2bp buffer
|
|
434
269
|
if (prevExon && prevExon.max + 2 > newLocation) {
|
|
435
270
|
notify(`Error while changing start location`, 'error')
|
|
436
|
-
return
|
|
271
|
+
return false
|
|
437
272
|
}
|
|
438
273
|
// Changed location should be less than start location of next exon - give 2bp buffer
|
|
439
274
|
if (nextExon && nextExon.min - 2 < newLocation) {
|
|
440
275
|
notify(`Error while changing end location`, 'error')
|
|
441
|
-
return
|
|
276
|
+
return false
|
|
442
277
|
}
|
|
443
278
|
|
|
444
279
|
const exonFeature = getExonFeature(
|
|
@@ -449,7 +284,7 @@ export const TranscriptWidgetEditLocation = observer(
|
|
|
449
284
|
)
|
|
450
285
|
if (!exonFeature) {
|
|
451
286
|
notify('No matching exon feature found', 'error')
|
|
452
|
-
return
|
|
287
|
+
return false
|
|
453
288
|
}
|
|
454
289
|
|
|
455
290
|
const cdsFeature = getFirstCDSFeature(feature, featureTypeOntology)
|
|
@@ -577,6 +412,7 @@ export const TranscriptWidgetEditLocation = observer(
|
|
|
577
412
|
notify('Error updating feature exon end position', 'error')
|
|
578
413
|
})
|
|
579
414
|
}
|
|
415
|
+
return true
|
|
580
416
|
}
|
|
581
417
|
|
|
582
418
|
const appendEndLocationChange = (
|
|
@@ -1170,7 +1006,7 @@ export const TranscriptWidgetEditLocation = observer(
|
|
|
1170
1006
|
variant="outlined"
|
|
1171
1007
|
value={cdsMin + 1}
|
|
1172
1008
|
onChangeCommitted={(newLocation: number) => {
|
|
1173
|
-
|
|
1009
|
+
return updateCDSLocation(
|
|
1174
1010
|
cdsMin,
|
|
1175
1011
|
newLocation - 1,
|
|
1176
1012
|
feature,
|
|
@@ -1187,7 +1023,7 @@ export const TranscriptWidgetEditLocation = observer(
|
|
|
1187
1023
|
variant="outlined"
|
|
1188
1024
|
value={cdsMax}
|
|
1189
1025
|
onChangeCommitted={(newLocation: number) => {
|
|
1190
|
-
|
|
1026
|
+
return updateCDSLocation(
|
|
1191
1027
|
cdsMax,
|
|
1192
1028
|
newLocation,
|
|
1193
1029
|
feature,
|
|
@@ -1208,7 +1044,7 @@ export const TranscriptWidgetEditLocation = observer(
|
|
|
1208
1044
|
variant="outlined"
|
|
1209
1045
|
value={cdsMax}
|
|
1210
1046
|
onChangeCommitted={(newLocation: number) => {
|
|
1211
|
-
|
|
1047
|
+
return updateCDSLocation(
|
|
1212
1048
|
cdsMax,
|
|
1213
1049
|
newLocation,
|
|
1214
1050
|
feature,
|
|
@@ -1225,7 +1061,7 @@ export const TranscriptWidgetEditLocation = observer(
|
|
|
1225
1061
|
variant="outlined"
|
|
1226
1062
|
value={cdsMin + 1}
|
|
1227
1063
|
onChangeCommitted={(newLocation: number) => {
|
|
1228
|
-
|
|
1064
|
+
return updateCDSLocation(
|
|
1229
1065
|
cdsMin,
|
|
1230
1066
|
newLocation - 1,
|
|
1231
1067
|
feature,
|
|
@@ -1270,7 +1106,7 @@ export const TranscriptWidgetEditLocation = observer(
|
|
|
1270
1106
|
variant="outlined"
|
|
1271
1107
|
value={loc.min + 1}
|
|
1272
1108
|
onChangeCommitted={(newLocation: number) => {
|
|
1273
|
-
handleExonLocationChange(
|
|
1109
|
+
return handleExonLocationChange(
|
|
1274
1110
|
loc.min,
|
|
1275
1111
|
newLocation - 1,
|
|
1276
1112
|
feature,
|
|
@@ -1286,7 +1122,7 @@ export const TranscriptWidgetEditLocation = observer(
|
|
|
1286
1122
|
variant="outlined"
|
|
1287
1123
|
value={loc.max}
|
|
1288
1124
|
onChangeCommitted={(newLocation: number) => {
|
|
1289
|
-
handleExonLocationChange(
|
|
1125
|
+
return handleExonLocationChange(
|
|
1290
1126
|
loc.max,
|
|
1291
1127
|
newLocation,
|
|
1292
1128
|
feature,
|
|
@@ -1306,7 +1142,7 @@ export const TranscriptWidgetEditLocation = observer(
|
|
|
1306
1142
|
variant="outlined"
|
|
1307
1143
|
value={loc.max}
|
|
1308
1144
|
onChangeCommitted={(newLocation: number) => {
|
|
1309
|
-
handleExonLocationChange(
|
|
1145
|
+
return handleExonLocationChange(
|
|
1310
1146
|
loc.max,
|
|
1311
1147
|
newLocation,
|
|
1312
1148
|
feature,
|
|
@@ -1322,7 +1158,7 @@ export const TranscriptWidgetEditLocation = observer(
|
|
|
1322
1158
|
variant="outlined"
|
|
1323
1159
|
value={loc.min + 1}
|
|
1324
1160
|
onChangeCommitted={(newLocation: number) => {
|
|
1325
|
-
handleExonLocationChange(
|
|
1161
|
+
return handleExonLocationChange(
|
|
1326
1162
|
loc.min,
|
|
1327
1163
|
newLocation - 1,
|
|
1328
1164
|
feature,
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { type CheckResultI } from '@apollo-annotation/mst'
|
|
2
|
+
import { type AbstractSessionModel, doesIntersect2 } from '@jbrowse/core/util'
|
|
3
|
+
import ErrorIcon from '@mui/icons-material/Error'
|
|
4
|
+
import { Avatar, Badge, Box, Tooltip } from '@mui/material'
|
|
5
|
+
import { observer } from 'mobx-react'
|
|
6
|
+
import React from 'react'
|
|
7
|
+
|
|
8
|
+
import { clusterResultByMessage, useStyles } from '../../util/displayUtils'
|
|
9
|
+
import { getLeftPx } from '../glyphs/util'
|
|
10
|
+
import { type LinearApolloDisplay as LinearApolloDisplayI } from '../stateModel'
|
|
11
|
+
|
|
12
|
+
export const CheckResultWarnings = observer(function CheckResultWarnings({
|
|
13
|
+
display,
|
|
14
|
+
}: {
|
|
15
|
+
display: LinearApolloDisplayI
|
|
16
|
+
}) {
|
|
17
|
+
const { classes } = useStyles()
|
|
18
|
+
const { apolloDragging, apolloRowHeight, lgv, session, showCheckResults } =
|
|
19
|
+
display
|
|
20
|
+
const { assemblyManager } = session as unknown as AbstractSessionModel
|
|
21
|
+
if (!showCheckResults) {
|
|
22
|
+
return null
|
|
23
|
+
}
|
|
24
|
+
return lgv.dynamicBlocks.contentBlocks.map((block) => {
|
|
25
|
+
const widthBp = lgv.bpPerPx * apolloRowHeight
|
|
26
|
+
const assembly = assemblyManager.get(block.assemblyName)
|
|
27
|
+
if (!assembly) {
|
|
28
|
+
return null
|
|
29
|
+
}
|
|
30
|
+
const filteredCheckResults = [
|
|
31
|
+
...session.apolloDataStore.checkResults.values(),
|
|
32
|
+
].filter(
|
|
33
|
+
(checkResult) =>
|
|
34
|
+
assembly.isValidRefName(checkResult.refSeq) &&
|
|
35
|
+
assembly.getCanonicalRefName(checkResult.refSeq) === block.refName &&
|
|
36
|
+
doesIntersect2(
|
|
37
|
+
block.start,
|
|
38
|
+
block.end,
|
|
39
|
+
checkResult.start,
|
|
40
|
+
checkResult.end,
|
|
41
|
+
),
|
|
42
|
+
)
|
|
43
|
+
const checkResults = clusterResultByMessage<CheckResultI>(
|
|
44
|
+
filteredCheckResults,
|
|
45
|
+
widthBp,
|
|
46
|
+
true,
|
|
47
|
+
)
|
|
48
|
+
return checkResults.map((checkResult) => {
|
|
49
|
+
const left = Math.round(getLeftPx(display, checkResult.range, block))
|
|
50
|
+
|
|
51
|
+
const [feature] = checkResult.featureIds
|
|
52
|
+
if (!feature) {
|
|
53
|
+
return null
|
|
54
|
+
}
|
|
55
|
+
let row = 0
|
|
56
|
+
const featureLayout = display.getFeatureLayoutPosition(feature)
|
|
57
|
+
if (featureLayout) {
|
|
58
|
+
row = featureLayout.layoutRow + featureLayout.featureRow
|
|
59
|
+
}
|
|
60
|
+
const top = row * apolloRowHeight
|
|
61
|
+
const height = apolloRowHeight
|
|
62
|
+
return (
|
|
63
|
+
<Tooltip key={checkResult._id} title={checkResult.message}>
|
|
64
|
+
<Box
|
|
65
|
+
className={classes.box}
|
|
66
|
+
style={{
|
|
67
|
+
top,
|
|
68
|
+
left,
|
|
69
|
+
height,
|
|
70
|
+
width: height,
|
|
71
|
+
pointerEvents: apolloDragging ? 'none' : 'auto',
|
|
72
|
+
}}
|
|
73
|
+
>
|
|
74
|
+
<Badge
|
|
75
|
+
className={classes.badge}
|
|
76
|
+
badgeContent={checkResult.count}
|
|
77
|
+
color="primary"
|
|
78
|
+
overlap="circular"
|
|
79
|
+
anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}
|
|
80
|
+
invisible={checkResult.count <= 1}
|
|
81
|
+
>
|
|
82
|
+
<Avatar className={classes.avatar}>
|
|
83
|
+
<ErrorIcon data-testid={`ErrorIcon-${checkResult.start}`} />
|
|
84
|
+
</Avatar>
|
|
85
|
+
</Badge>
|
|
86
|
+
</Box>
|
|
87
|
+
</Tooltip>
|
|
88
|
+
)
|
|
89
|
+
})
|
|
90
|
+
return null
|
|
91
|
+
})
|
|
92
|
+
})
|
|
@@ -1,35 +1,19 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/unbound-method */
|
|
2
2
|
/* eslint-disable @typescript-eslint/no-misused-promises */
|
|
3
3
|
/* eslint-disable @typescript-eslint/no-unnecessary-condition */
|
|
4
|
-
import { type CheckResultI } from '@apollo-annotation/mst'
|
|
5
4
|
import { Menu, type MenuItem } from '@jbrowse/core/ui'
|
|
6
|
-
import {
|
|
7
|
-
type AbstractSessionModel,
|
|
8
|
-
doesIntersect2,
|
|
9
|
-
getContainingView,
|
|
10
|
-
} from '@jbrowse/core/util'
|
|
5
|
+
import { getContainingView } from '@jbrowse/core/util'
|
|
11
6
|
import { type LinearGenomeViewModel } from '@jbrowse/plugin-linear-genome-view'
|
|
12
|
-
import ErrorIcon from '@mui/icons-material/Error'
|
|
13
7
|
import LockIcon from '@mui/icons-material/Lock'
|
|
14
|
-
import {
|
|
15
|
-
Alert,
|
|
16
|
-
Avatar,
|
|
17
|
-
Badge,
|
|
18
|
-
Box,
|
|
19
|
-
CircularProgress,
|
|
20
|
-
Tooltip,
|
|
21
|
-
useTheme,
|
|
22
|
-
} from '@mui/material'
|
|
8
|
+
import { Alert, CircularProgress, Tooltip, useTheme } from '@mui/material'
|
|
23
9
|
import { observer } from 'mobx-react'
|
|
24
10
|
import React, { useEffect, useState } from 'react'
|
|
25
11
|
|
|
26
|
-
import {
|
|
27
|
-
type Coord,
|
|
28
|
-
clusterResultByMessage,
|
|
29
|
-
useStyles,
|
|
30
|
-
} from '../../util/displayUtils'
|
|
12
|
+
import { type Coord, useStyles } from '../../util/displayUtils'
|
|
31
13
|
import { type LinearApolloDisplay as LinearApolloDisplayI } from '../stateModel'
|
|
32
14
|
|
|
15
|
+
import { CheckResultWarnings } from './CheckResultWarnings'
|
|
16
|
+
|
|
33
17
|
interface LinearApolloDisplayProps {
|
|
34
18
|
model: LinearApolloDisplayI
|
|
35
19
|
}
|
|
@@ -43,8 +27,6 @@ export const LinearApolloDisplay = observer(function LinearApolloDisplay(
|
|
|
43
27
|
const { model } = props
|
|
44
28
|
const {
|
|
45
29
|
loading,
|
|
46
|
-
apolloDragging,
|
|
47
|
-
apolloRowHeight,
|
|
48
30
|
contextMenuItems: getContextMenuItems,
|
|
49
31
|
cursor,
|
|
50
32
|
featuresHeight,
|
|
@@ -59,7 +41,6 @@ export const LinearApolloDisplay = observer(function LinearApolloDisplay(
|
|
|
59
41
|
setCollaboratorCanvas,
|
|
60
42
|
setOverlayCanvas,
|
|
61
43
|
setTheme,
|
|
62
|
-
showCheckResults,
|
|
63
44
|
} = model
|
|
64
45
|
const { classes } = useStyles()
|
|
65
46
|
const lgv = getContainingView(model) as unknown as LinearGenomeViewModel
|
|
@@ -73,7 +54,6 @@ export const LinearApolloDisplay = observer(function LinearApolloDisplay(
|
|
|
73
54
|
if (!isShown) {
|
|
74
55
|
return null
|
|
75
56
|
}
|
|
76
|
-
const { assemblyManager } = session as unknown as AbstractSessionModel
|
|
77
57
|
return (
|
|
78
58
|
<>
|
|
79
59
|
<div
|
|
@@ -153,83 +133,7 @@ export const LinearApolloDisplay = observer(function LinearApolloDisplay(
|
|
|
153
133
|
style={{ cursor: cursor ?? 'default' }}
|
|
154
134
|
data-testid="overlayCanvas"
|
|
155
135
|
/>
|
|
156
|
-
{
|
|
157
|
-
const widthBp = lgv.bpPerPx * apolloRowHeight
|
|
158
|
-
const assembly = assemblyManager.get(region.assemblyName)
|
|
159
|
-
if (showCheckResults) {
|
|
160
|
-
const filteredCheckResults = [
|
|
161
|
-
...session.apolloDataStore.checkResults.values(),
|
|
162
|
-
].filter(
|
|
163
|
-
(checkResult) =>
|
|
164
|
-
assembly?.isValidRefName(checkResult.refSeq) &&
|
|
165
|
-
assembly.getCanonicalRefName(checkResult.refSeq) ===
|
|
166
|
-
region.refName &&
|
|
167
|
-
doesIntersect2(
|
|
168
|
-
region.start,
|
|
169
|
-
region.end,
|
|
170
|
-
checkResult.start,
|
|
171
|
-
checkResult.end,
|
|
172
|
-
),
|
|
173
|
-
)
|
|
174
|
-
const checkResults = clusterResultByMessage<CheckResultI>(
|
|
175
|
-
filteredCheckResults,
|
|
176
|
-
widthBp,
|
|
177
|
-
true,
|
|
178
|
-
)
|
|
179
|
-
return checkResults.map((checkResult) => {
|
|
180
|
-
const left =
|
|
181
|
-
(lgv.bpToPx({
|
|
182
|
-
refName: region.refName,
|
|
183
|
-
coord: checkResult.start,
|
|
184
|
-
regionNumber: idx,
|
|
185
|
-
})?.offsetPx ?? 0) - lgv.offsetPx
|
|
186
|
-
const [feature] = checkResult.featureIds
|
|
187
|
-
if (!feature) {
|
|
188
|
-
return null
|
|
189
|
-
}
|
|
190
|
-
let row = 0
|
|
191
|
-
const featureLayout = model.getFeatureLayoutPosition(feature)
|
|
192
|
-
if (featureLayout) {
|
|
193
|
-
row = featureLayout.layoutRow + featureLayout.featureRow
|
|
194
|
-
}
|
|
195
|
-
const top = row * apolloRowHeight
|
|
196
|
-
const height = apolloRowHeight
|
|
197
|
-
return (
|
|
198
|
-
<Tooltip key={checkResult._id} title={checkResult.message}>
|
|
199
|
-
<Box
|
|
200
|
-
className={classes.box}
|
|
201
|
-
style={{
|
|
202
|
-
top,
|
|
203
|
-
left,
|
|
204
|
-
height,
|
|
205
|
-
width: height,
|
|
206
|
-
pointerEvents: apolloDragging ? 'none' : 'auto',
|
|
207
|
-
}}
|
|
208
|
-
>
|
|
209
|
-
<Badge
|
|
210
|
-
className={classes.badge}
|
|
211
|
-
badgeContent={checkResult.count}
|
|
212
|
-
color="primary"
|
|
213
|
-
overlap="circular"
|
|
214
|
-
anchorOrigin={{
|
|
215
|
-
vertical: 'bottom',
|
|
216
|
-
horizontal: 'right',
|
|
217
|
-
}}
|
|
218
|
-
invisible={checkResult.count <= 1}
|
|
219
|
-
>
|
|
220
|
-
<Avatar className={classes.avatar}>
|
|
221
|
-
<ErrorIcon
|
|
222
|
-
data-testid={`ErrorIcon-${checkResult.start}`}
|
|
223
|
-
/>
|
|
224
|
-
</Avatar>
|
|
225
|
-
</Badge>
|
|
226
|
-
</Box>
|
|
227
|
-
</Tooltip>
|
|
228
|
-
)
|
|
229
|
-
})
|
|
230
|
-
}
|
|
231
|
-
return null
|
|
232
|
-
})}
|
|
136
|
+
<CheckResultWarnings display={model} />
|
|
233
137
|
<Menu
|
|
234
138
|
open={contextMenuItems.length > 0}
|
|
235
139
|
onMenuItemClick={(_, callback) => {
|