@apollo-annotation/jbrowse-plugin-apollo 0.3.7 → 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 +11212 -10483
- package/dist/index.esm.js.map +1 -1
- package/dist/jbrowse-plugin-apollo.cjs.development.js +11251 -10509
- 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 +7726 -9014
- 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 +18 -18
- package/src/ApolloInternetAccount/model.ts +123 -70
- package/src/ApolloRefNameAliasAdapter/ApolloRefNameAliasAdapter.ts +4 -4
- package/src/ApolloSequenceAdapter/ApolloSequenceAdapter.ts +9 -7
- package/src/BackendDrivers/CollaborationServerDriver.ts +72 -20
- package/src/BackendDrivers/DesktopFileDriver.ts +2 -2
- package/src/ChangeManager.ts +36 -14
- package/src/FeatureDetailsWidget/ApolloTranscriptDetailsWidget.tsx +64 -5
- package/src/FeatureDetailsWidget/BasicInformation.tsx +6 -4
- package/src/FeatureDetailsWidget/NumberTextField.tsx +5 -2
- package/src/FeatureDetailsWidget/TranscriptSequence.tsx +70 -73
- package/src/FeatureDetailsWidget/TranscriptWidgetEditLocation.tsx +72 -234
- package/src/LinearApolloDisplay/components/CheckResultWarnings.tsx +92 -0
- package/src/LinearApolloDisplay/components/LinearApolloDisplay.tsx +23 -131
- package/src/LinearApolloDisplay/glyphs/BoxGlyph.ts +50 -194
- package/src/LinearApolloDisplay/glyphs/GeneGlyph.ts +279 -217
- package/src/LinearApolloDisplay/glyphs/GenericChildGlyph.ts +53 -34
- package/src/LinearApolloDisplay/glyphs/Glyph.ts +7 -9
- package/src/LinearApolloDisplay/glyphs/util.ts +19 -0
- package/src/LinearApolloDisplay/stateModel/base.ts +34 -43
- package/src/LinearApolloDisplay/stateModel/layouts.ts +3 -2
- package/src/LinearApolloDisplay/stateModel/mouseEvents.ts +32 -261
- package/src/LinearApolloDisplay/stateModel/rendering.ts +43 -343
- package/src/LinearApolloReferenceSequenceDisplay/components/LinearApolloReferenceSequenceDisplay.tsx +87 -0
- package/src/LinearApolloReferenceSequenceDisplay/components/index.ts +1 -0
- package/src/LinearApolloReferenceSequenceDisplay/configSchema.ts +7 -0
- package/src/LinearApolloReferenceSequenceDisplay/drawSequenceOverlay.ts +181 -0
- package/src/LinearApolloReferenceSequenceDisplay/drawSequenceTrack.ts +218 -0
- package/src/LinearApolloReferenceSequenceDisplay/index.ts +3 -0
- package/src/LinearApolloReferenceSequenceDisplay/stateModel/base.ts +227 -0
- package/src/LinearApolloReferenceSequenceDisplay/stateModel/index.ts +25 -0
- package/src/LinearApolloReferenceSequenceDisplay/stateModel/rendering.ts +157 -0
- package/src/LinearApolloSixFrameDisplay/components/LinearApolloSixFrameDisplay.tsx +101 -38
- package/src/LinearApolloSixFrameDisplay/glyphs/GeneGlyph.ts +334 -262
- package/src/LinearApolloSixFrameDisplay/glyphs/Glyph.ts +12 -8
- package/src/LinearApolloSixFrameDisplay/stateModel/base.ts +42 -4
- package/src/LinearApolloSixFrameDisplay/stateModel/layouts.ts +4 -8
- package/src/LinearApolloSixFrameDisplay/stateModel/mouseEvents.ts +73 -97
- package/src/LinearApolloSixFrameDisplay/stateModel/rendering.ts +49 -61
- package/src/TabularEditor/HybridGrid/Feature.tsx +16 -14
- package/src/TabularEditor/HybridGrid/HybridGrid.tsx +7 -5
- package/src/components/AddAssembly.tsx +34 -38
- package/src/components/AddAssemblyAliases.tsx +1 -1
- package/src/components/AddChildFeature.tsx +5 -2
- package/src/components/AddFeature.tsx +30 -21
- package/src/components/AddRefSeqAliases.tsx +64 -50
- package/src/components/CopyFeature.tsx +4 -2
- package/src/components/CreateApolloAnnotation.tsx +22 -9
- package/src/components/DeleteAssembly.tsx +3 -10
- package/src/components/DownloadGFF3.tsx +2 -2
- package/src/components/EditZoomThresholdDialog.tsx +69 -0
- package/src/components/FilterFeatures.tsx +7 -7
- package/src/components/FilterTranscripts.tsx +6 -6
- package/src/components/ImportFeatures.tsx +1 -1
- package/src/components/ManageChecks.tsx +3 -10
- package/src/components/ManageUsers.tsx +23 -22
- package/src/components/MergeTranscripts.tsx +12 -15
- package/src/components/OntologyTermAutocomplete.tsx +1 -8
- package/src/components/OntologyTermMultiSelect.tsx +11 -11
- package/src/components/OpenLocalFile.tsx +11 -7
- package/src/components/ViewChangeLog.tsx +25 -50
- package/src/components/ViewCheckResults.tsx +2 -8
- package/src/components/index.ts +1 -0
- package/src/config.ts +6 -0
- package/src/index.ts +53 -115
- package/src/makeDisplayComponent.tsx +9 -14
- package/src/menus/index.ts +1 -0
- package/src/{ApolloInternetAccount/addMenuItems.ts → menus/topLevelMenu.ts} +56 -47
- package/src/menus/topLevelMenuAdmin.ts +154 -0
- package/src/session/ClientDataStore.ts +32 -14
- package/src/session/session.ts +159 -121
- package/src/util/annotationFeatureUtils.ts +15 -21
- package/src/util/displayUtils.ts +149 -0
- package/src/util/glyphUtils.ts +329 -0
- package/src/util/loadAssemblyIntoClient.ts +3 -2
- package/src/util/mouseEventsUtils.ts +32 -0
|
@@ -25,7 +25,7 @@ import RemoveIcon from '@mui/icons-material/Remove'
|
|
|
25
25
|
import {
|
|
26
26
|
Accordion,
|
|
27
27
|
AccordionDetails,
|
|
28
|
-
|
|
28
|
+
Grid,
|
|
29
29
|
Tooltip,
|
|
30
30
|
Typography,
|
|
31
31
|
} from '@mui/material'
|
|
@@ -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 = (
|
|
@@ -821,6 +657,7 @@ export const TranscriptWidgetEditLocation = observer(
|
|
|
821
657
|
}
|
|
822
658
|
}
|
|
823
659
|
}
|
|
660
|
+
spliceSite = spliceSite.toUpperCase()
|
|
824
661
|
return [
|
|
825
662
|
{
|
|
826
663
|
spliceSite,
|
|
@@ -846,6 +683,7 @@ export const TranscriptWidgetEditLocation = observer(
|
|
|
846
683
|
}
|
|
847
684
|
}
|
|
848
685
|
}
|
|
686
|
+
spliceSite = spliceSite.toUpperCase()
|
|
849
687
|
return [
|
|
850
688
|
{
|
|
851
689
|
spliceSite,
|
|
@@ -1154,21 +992,21 @@ export const TranscriptWidgetEditLocation = observer(
|
|
|
1154
992
|
</div>
|
|
1155
993
|
</AccordionDetails>
|
|
1156
994
|
</Accordion>
|
|
1157
|
-
<
|
|
995
|
+
<Grid
|
|
1158
996
|
container
|
|
1159
997
|
justifyContent="center"
|
|
1160
998
|
alignItems="center"
|
|
1161
999
|
style={{ textAlign: 'center', marginTop: 10 }}
|
|
1162
1000
|
>
|
|
1163
|
-
<
|
|
1001
|
+
<Grid size={1} />
|
|
1164
1002
|
{strand === 1 ? (
|
|
1165
|
-
<
|
|
1003
|
+
<Grid size={4}>
|
|
1166
1004
|
<StyledTextField
|
|
1167
1005
|
margin="dense"
|
|
1168
1006
|
variant="outlined"
|
|
1169
1007
|
value={cdsMin + 1}
|
|
1170
1008
|
onChangeCommitted={(newLocation: number) => {
|
|
1171
|
-
|
|
1009
|
+
return updateCDSLocation(
|
|
1172
1010
|
cdsMin,
|
|
1173
1011
|
newLocation - 1,
|
|
1174
1012
|
feature,
|
|
@@ -1177,15 +1015,15 @@ export const TranscriptWidgetEditLocation = observer(
|
|
|
1177
1015
|
}}
|
|
1178
1016
|
style={{ border: '1px solid black', borderRadius: 5 }}
|
|
1179
1017
|
/>
|
|
1180
|
-
</
|
|
1018
|
+
</Grid>
|
|
1181
1019
|
) : (
|
|
1182
|
-
<
|
|
1020
|
+
<Grid size={4}>
|
|
1183
1021
|
<StyledTextField
|
|
1184
1022
|
margin="dense"
|
|
1185
1023
|
variant="outlined"
|
|
1186
1024
|
value={cdsMax}
|
|
1187
1025
|
onChangeCommitted={(newLocation: number) => {
|
|
1188
|
-
|
|
1026
|
+
return updateCDSLocation(
|
|
1189
1027
|
cdsMax,
|
|
1190
1028
|
newLocation,
|
|
1191
1029
|
feature,
|
|
@@ -1194,19 +1032,19 @@ export const TranscriptWidgetEditLocation = observer(
|
|
|
1194
1032
|
}}
|
|
1195
1033
|
style={{ border: '1px solid black', borderRadius: 5 }}
|
|
1196
1034
|
/>
|
|
1197
|
-
</
|
|
1035
|
+
</Grid>
|
|
1198
1036
|
)}
|
|
1199
|
-
<
|
|
1037
|
+
<Grid size={2}>
|
|
1200
1038
|
<Typography component={'span'}>CDS</Typography>
|
|
1201
|
-
</
|
|
1039
|
+
</Grid>
|
|
1202
1040
|
{strand === 1 ? (
|
|
1203
|
-
<
|
|
1041
|
+
<Grid size={4}>
|
|
1204
1042
|
<StyledTextField
|
|
1205
1043
|
margin="dense"
|
|
1206
1044
|
variant="outlined"
|
|
1207
1045
|
value={cdsMax}
|
|
1208
1046
|
onChangeCommitted={(newLocation: number) => {
|
|
1209
|
-
|
|
1047
|
+
return updateCDSLocation(
|
|
1210
1048
|
cdsMax,
|
|
1211
1049
|
newLocation,
|
|
1212
1050
|
feature,
|
|
@@ -1215,15 +1053,15 @@ export const TranscriptWidgetEditLocation = observer(
|
|
|
1215
1053
|
}}
|
|
1216
1054
|
style={{ border: '1px solid black', borderRadius: 5 }}
|
|
1217
1055
|
/>
|
|
1218
|
-
</
|
|
1056
|
+
</Grid>
|
|
1219
1057
|
) : (
|
|
1220
|
-
<
|
|
1058
|
+
<Grid size={4}>
|
|
1221
1059
|
<StyledTextField
|
|
1222
1060
|
margin="dense"
|
|
1223
1061
|
variant="outlined"
|
|
1224
1062
|
value={cdsMin + 1}
|
|
1225
1063
|
onChangeCommitted={(newLocation: number) => {
|
|
1226
|
-
|
|
1064
|
+
return updateCDSLocation(
|
|
1227
1065
|
cdsMin,
|
|
1228
1066
|
newLocation - 1,
|
|
1229
1067
|
feature,
|
|
@@ -1232,10 +1070,10 @@ export const TranscriptWidgetEditLocation = observer(
|
|
|
1232
1070
|
}}
|
|
1233
1071
|
style={{ border: '1px solid black', borderRadius: 5 }}
|
|
1234
1072
|
/>
|
|
1235
|
-
</
|
|
1073
|
+
</Grid>
|
|
1236
1074
|
)}
|
|
1237
|
-
<
|
|
1238
|
-
</
|
|
1075
|
+
<Grid size={1} />
|
|
1076
|
+
</Grid>
|
|
1239
1077
|
</div>
|
|
1240
1078
|
)}
|
|
1241
1079
|
<div style={{ marginTop: 5 }}>
|
|
@@ -1243,13 +1081,13 @@ export const TranscriptWidgetEditLocation = observer(
|
|
|
1243
1081
|
return (
|
|
1244
1082
|
<div key={index}>
|
|
1245
1083
|
{loc.type === 'exon' && (
|
|
1246
|
-
<
|
|
1084
|
+
<Grid
|
|
1247
1085
|
container
|
|
1248
1086
|
justifyContent="center"
|
|
1249
1087
|
alignItems="center"
|
|
1250
1088
|
style={{ textAlign: 'center' }}
|
|
1251
1089
|
>
|
|
1252
|
-
<
|
|
1090
|
+
<Grid size={1}>
|
|
1253
1091
|
{index !== 0 &&
|
|
1254
1092
|
getFivePrimeSpliceSite(loc, index).map((site, idx) => (
|
|
1255
1093
|
<Typography
|
|
@@ -1260,15 +1098,15 @@ export const TranscriptWidgetEditLocation = observer(
|
|
|
1260
1098
|
{site.spliceSite}
|
|
1261
1099
|
</Typography>
|
|
1262
1100
|
))}
|
|
1263
|
-
</
|
|
1101
|
+
</Grid>
|
|
1264
1102
|
{strand === 1 ? (
|
|
1265
|
-
<
|
|
1103
|
+
<Grid size={4} style={{ padding: 0 }}>
|
|
1266
1104
|
<StyledTextField
|
|
1267
1105
|
margin="dense"
|
|
1268
1106
|
variant="outlined"
|
|
1269
1107
|
value={loc.min + 1}
|
|
1270
1108
|
onChangeCommitted={(newLocation: number) => {
|
|
1271
|
-
handleExonLocationChange(
|
|
1109
|
+
return handleExonLocationChange(
|
|
1272
1110
|
loc.min,
|
|
1273
1111
|
newLocation - 1,
|
|
1274
1112
|
feature,
|
|
@@ -1276,15 +1114,15 @@ export const TranscriptWidgetEditLocation = observer(
|
|
|
1276
1114
|
)
|
|
1277
1115
|
}}
|
|
1278
1116
|
/>
|
|
1279
|
-
</
|
|
1117
|
+
</Grid>
|
|
1280
1118
|
) : (
|
|
1281
|
-
<
|
|
1119
|
+
<Grid size={4} style={{ padding: 0 }}>
|
|
1282
1120
|
<StyledTextField
|
|
1283
1121
|
margin="dense"
|
|
1284
1122
|
variant="outlined"
|
|
1285
1123
|
value={loc.max}
|
|
1286
1124
|
onChangeCommitted={(newLocation: number) => {
|
|
1287
|
-
handleExonLocationChange(
|
|
1125
|
+
return handleExonLocationChange(
|
|
1288
1126
|
loc.max,
|
|
1289
1127
|
newLocation,
|
|
1290
1128
|
feature,
|
|
@@ -1292,19 +1130,19 @@ export const TranscriptWidgetEditLocation = observer(
|
|
|
1292
1130
|
)
|
|
1293
1131
|
}}
|
|
1294
1132
|
/>
|
|
1295
|
-
</
|
|
1133
|
+
</Grid>
|
|
1296
1134
|
)}
|
|
1297
|
-
<
|
|
1135
|
+
<Grid size={2}>
|
|
1298
1136
|
<Strand strand={feature.strand} />
|
|
1299
|
-
</
|
|
1137
|
+
</Grid>
|
|
1300
1138
|
{strand === 1 ? (
|
|
1301
|
-
<
|
|
1139
|
+
<Grid size={4} style={{ padding: 0 }}>
|
|
1302
1140
|
<StyledTextField
|
|
1303
1141
|
margin="dense"
|
|
1304
1142
|
variant="outlined"
|
|
1305
1143
|
value={loc.max}
|
|
1306
1144
|
onChangeCommitted={(newLocation: number) => {
|
|
1307
|
-
handleExonLocationChange(
|
|
1145
|
+
return handleExonLocationChange(
|
|
1308
1146
|
loc.max,
|
|
1309
1147
|
newLocation,
|
|
1310
1148
|
feature,
|
|
@@ -1312,15 +1150,15 @@ export const TranscriptWidgetEditLocation = observer(
|
|
|
1312
1150
|
)
|
|
1313
1151
|
}}
|
|
1314
1152
|
/>
|
|
1315
|
-
</
|
|
1153
|
+
</Grid>
|
|
1316
1154
|
) : (
|
|
1317
|
-
<
|
|
1155
|
+
<Grid size={4} style={{ padding: 0 }}>
|
|
1318
1156
|
<StyledTextField
|
|
1319
1157
|
margin="dense"
|
|
1320
1158
|
variant="outlined"
|
|
1321
1159
|
value={loc.min + 1}
|
|
1322
1160
|
onChangeCommitted={(newLocation: number) => {
|
|
1323
|
-
handleExonLocationChange(
|
|
1161
|
+
return handleExonLocationChange(
|
|
1324
1162
|
loc.min,
|
|
1325
1163
|
newLocation - 1,
|
|
1326
1164
|
feature,
|
|
@@ -1328,9 +1166,9 @@ export const TranscriptWidgetEditLocation = observer(
|
|
|
1328
1166
|
)
|
|
1329
1167
|
}}
|
|
1330
1168
|
/>
|
|
1331
|
-
</
|
|
1169
|
+
</Grid>
|
|
1332
1170
|
)}
|
|
1333
|
-
<
|
|
1171
|
+
<Grid size={1}>
|
|
1334
1172
|
{index !== transcriptExonParts.length - 1 &&
|
|
1335
1173
|
getThreePrimeSpliceSite(loc, index).map((site, idx) => (
|
|
1336
1174
|
<Typography
|
|
@@ -1341,8 +1179,8 @@ export const TranscriptWidgetEditLocation = observer(
|
|
|
1341
1179
|
{site.spliceSite}
|
|
1342
1180
|
</Typography>
|
|
1343
1181
|
))}
|
|
1344
|
-
</
|
|
1345
|
-
</
|
|
1182
|
+
</Grid>
|
|
1183
|
+
</Grid>
|
|
1346
1184
|
)}
|
|
1347
1185
|
</div>
|
|
1348
1186
|
)
|
|
@@ -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
|
+
})
|