@apollo-annotation/jbrowse-plugin-apollo 0.3.8 → 0.3.10
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 +10914 -10799
- package/dist/index.esm.js.map +1 -1
- package/dist/jbrowse-plugin-apollo.cjs.development.js +10979 -10865
- 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 +8799 -11326
- 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/components/AuthTypeSelector.tsx +1 -1
- package/src/ApolloInternetAccount/model.ts +87 -65
- package/src/ApolloRefNameAliasAdapter/ApolloRefNameAliasAdapter.ts +4 -4
- package/src/ApolloSequenceAdapter/ApolloSequenceAdapter.ts +9 -7
- package/src/BackendDrivers/CollaborationServerDriver.ts +60 -23
- package/src/BackendDrivers/DesktopFileDriver.ts +2 -2
- package/src/ChangeManager.ts +22 -5
- package/src/FeatureDetailsWidget/BasicInformation.tsx +6 -4
- package/src/FeatureDetailsWidget/NumberTextField.tsx +5 -2
- package/src/FeatureDetailsWidget/TranscriptWidgetEditLocation.tsx +68 -212
- package/src/LinearApolloDisplay/components/CheckResultWarnings.tsx +92 -0
- package/src/LinearApolloDisplay/components/LinearApolloDisplay.tsx +6 -102
- package/src/LinearApolloDisplay/glyphs/GeneGlyph.ts +33 -232
- package/src/LinearApolloDisplay/glyphs/util.ts +36 -0
- package/src/LinearApolloReferenceSequenceDisplay/drawSequenceOverlay.ts +174 -0
- package/src/LinearApolloReferenceSequenceDisplay/drawSequenceTrack.ts +200 -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/LinearApolloSixFrameDisplay/stateModel/base.ts +33 -2
- package/src/LinearApolloSixFrameDisplay/stateModel/rendering.ts +101 -3
- package/src/components/AddAssembly.tsx +34 -38
- 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/ImportFeatures.tsx +1 -1
- package/src/components/ManageChecks.tsx +2 -9
- package/src/components/ManageUsers.tsx +23 -22
- package/src/components/OntologyTermAutocomplete.tsx +3 -10
- package/src/components/OntologyTermMultiSelect.tsx +2 -2
- 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 +33 -15
- package/src/session/session.ts +23 -27
- package/src/util/displayUtils.ts +28 -0
- package/src/util/glyphUtils.ts +196 -1
- package/src/util/loadAssemblyIntoClient.ts +3 -2
|
@@ -113,6 +113,7 @@ export const TranscriptWidgetEditLocation = observer(
|
|
|
113
113
|
const refData = currentAssembly?.getByRefName(refName)
|
|
114
114
|
const { changeManager } = session.apolloDataStore
|
|
115
115
|
const seqRef = useRef<HTMLDivElement>(null)
|
|
116
|
+
const { changeInProgress } = session
|
|
116
117
|
|
|
117
118
|
if (!refData) {
|
|
118
119
|
return null
|
|
@@ -149,66 +150,18 @@ export const TranscriptWidgetEditLocation = observer(
|
|
|
149
150
|
cdsMax = sortedCDSLocations[sortedCDSLocations.length - 1].max
|
|
150
151
|
}
|
|
151
152
|
|
|
152
|
-
|
|
153
|
+
const updateCDSLocation = (
|
|
153
154
|
oldLocation: number,
|
|
154
155
|
newLocation: number,
|
|
155
156
|
feature: AnnotationFeature,
|
|
156
157
|
isMin: boolean,
|
|
157
|
-
|
|
158
|
+
onComplete?: () => void,
|
|
159
|
+
): boolean => {
|
|
158
160
|
if (!feature.children) {
|
|
159
161
|
throw new Error('Transcript should have child features')
|
|
160
162
|
}
|
|
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
|
|
163
|
+
if (oldLocation === newLocation) {
|
|
164
|
+
return true
|
|
212
165
|
}
|
|
213
166
|
|
|
214
167
|
const cdsFeature = getMatchingCDSFeature(
|
|
@@ -217,10 +170,14 @@ export const TranscriptWidgetEditLocation = observer(
|
|
|
217
170
|
oldLocation,
|
|
218
171
|
isMin,
|
|
219
172
|
)
|
|
220
|
-
|
|
221
173
|
if (!cdsFeature) {
|
|
222
174
|
notify('No matching CDS feature found', 'error')
|
|
223
|
-
return
|
|
175
|
+
return false
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
if (isMin && newLocation >= cdsFeature.max) {
|
|
179
|
+
notify('Start location should be less than CDS end location', 'error')
|
|
180
|
+
return false
|
|
224
181
|
}
|
|
225
182
|
|
|
226
183
|
if (!isMin && newLocation <= cdsFeature.min) {
|
|
@@ -228,145 +185,23 @@ export const TranscriptWidgetEditLocation = observer(
|
|
|
228
185
|
'End location should be greater than CDS start location',
|
|
229
186
|
'error',
|
|
230
187
|
)
|
|
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
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
if (isMin && newLocation !== cdsFeature.min) {
|
|
251
|
-
const startChange: LocationStartChange = new LocationStartChange({
|
|
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
|
-
})
|
|
188
|
+
return false
|
|
296
189
|
}
|
|
297
190
|
|
|
298
|
-
|
|
299
|
-
|
|
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(
|
|
191
|
+
// overlapping exon of new CDS location
|
|
192
|
+
const overlappingExon = getOverlappingExonForCDS(
|
|
362
193
|
feature,
|
|
363
194
|
featureTypeOntology,
|
|
364
|
-
|
|
195
|
+
newLocation,
|
|
365
196
|
isMin,
|
|
366
197
|
)
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
198
|
+
|
|
199
|
+
if (!overlappingExon) {
|
|
200
|
+
notify(
|
|
201
|
+
'There should be an overlapping exon for the new CDS location',
|
|
202
|
+
'error',
|
|
203
|
+
)
|
|
204
|
+
return false
|
|
370
205
|
}
|
|
371
206
|
|
|
372
207
|
const change = isMin
|
|
@@ -397,6 +232,7 @@ export const TranscriptWidgetEditLocation = observer(
|
|
|
397
232
|
.catch(() => {
|
|
398
233
|
notify('Error updating feature CDS position', 'error')
|
|
399
234
|
})
|
|
235
|
+
return true
|
|
400
236
|
}
|
|
401
237
|
|
|
402
238
|
function handleExonLocationChange(
|
|
@@ -404,7 +240,7 @@ export const TranscriptWidgetEditLocation = observer(
|
|
|
404
240
|
newLocation: number,
|
|
405
241
|
feature: AnnotationFeature,
|
|
406
242
|
isMin: boolean,
|
|
407
|
-
) {
|
|
243
|
+
): boolean {
|
|
408
244
|
if (!feature.children) {
|
|
409
245
|
throw new Error('Transcript should have child features')
|
|
410
246
|
}
|
|
@@ -417,28 +253,28 @@ export const TranscriptWidgetEditLocation = observer(
|
|
|
417
253
|
|
|
418
254
|
if (!matchingExon) {
|
|
419
255
|
notify('No matching exon found', 'error')
|
|
420
|
-
return
|
|
256
|
+
return false
|
|
421
257
|
}
|
|
422
258
|
|
|
423
259
|
// Start location should be less than end location
|
|
424
260
|
if (isMin && newLocation >= matchingExon.max) {
|
|
425
261
|
notify(`Start location should be less than end location`, 'error')
|
|
426
|
-
return
|
|
262
|
+
return false
|
|
427
263
|
}
|
|
428
264
|
// End location should be greater than start location
|
|
429
265
|
if (!isMin && newLocation <= matchingExon.min) {
|
|
430
266
|
notify(`End location should be greater than start location`, 'error')
|
|
431
|
-
return
|
|
267
|
+
return false
|
|
432
268
|
}
|
|
433
269
|
// Changed location should be greater than end location of previous exon - give 2bp buffer
|
|
434
270
|
if (prevExon && prevExon.max + 2 > newLocation) {
|
|
435
271
|
notify(`Error while changing start location`, 'error')
|
|
436
|
-
return
|
|
272
|
+
return false
|
|
437
273
|
}
|
|
438
274
|
// Changed location should be less than start location of next exon - give 2bp buffer
|
|
439
275
|
if (nextExon && nextExon.min - 2 < newLocation) {
|
|
440
276
|
notify(`Error while changing end location`, 'error')
|
|
441
|
-
return
|
|
277
|
+
return false
|
|
442
278
|
}
|
|
443
279
|
|
|
444
280
|
const exonFeature = getExonFeature(
|
|
@@ -449,7 +285,7 @@ export const TranscriptWidgetEditLocation = observer(
|
|
|
449
285
|
)
|
|
450
286
|
if (!exonFeature) {
|
|
451
287
|
notify('No matching exon feature found', 'error')
|
|
452
|
-
return
|
|
288
|
+
return false
|
|
453
289
|
}
|
|
454
290
|
|
|
455
291
|
const cdsFeature = getFirstCDSFeature(feature, featureTypeOntology)
|
|
@@ -577,6 +413,7 @@ export const TranscriptWidgetEditLocation = observer(
|
|
|
577
413
|
notify('Error updating feature exon end position', 'error')
|
|
578
414
|
})
|
|
579
415
|
}
|
|
416
|
+
return true
|
|
580
417
|
}
|
|
581
418
|
|
|
582
419
|
const appendEndLocationChange = (
|
|
@@ -888,12 +725,15 @@ export const TranscriptWidgetEditLocation = observer(
|
|
|
888
725
|
<Typography
|
|
889
726
|
component={'span'}
|
|
890
727
|
style={{
|
|
891
|
-
backgroundColor: 'yellow',
|
|
728
|
+
backgroundColor: changeInProgress ? 'lightgray' : 'yellow',
|
|
892
729
|
cursor: 'pointer',
|
|
893
730
|
border: '1px solid black',
|
|
894
731
|
}}
|
|
895
732
|
key={codonGenomicPos}
|
|
896
733
|
onClick={() => {
|
|
734
|
+
if (changeInProgress) {
|
|
735
|
+
return
|
|
736
|
+
}
|
|
897
737
|
// NOTE: codonGenomicPos is important here for calculating the genomic location
|
|
898
738
|
// of the start codon. We are using the codonGenomicPos as the key in the typography
|
|
899
739
|
// elements to maintain the genomic postion of the codon start
|
|
@@ -1012,7 +852,7 @@ export const TranscriptWidgetEditLocation = observer(
|
|
|
1012
852
|
|
|
1013
853
|
// Trim any sequence before first start codon and after stop codon
|
|
1014
854
|
const startCodonIndex = translationSequence.indexOf('M')
|
|
1015
|
-
const stopCodonIndex = translationSequence.indexOf('*')
|
|
855
|
+
const stopCodonIndex = translationSequence.indexOf('*')
|
|
1016
856
|
|
|
1017
857
|
const startCodonPos =
|
|
1018
858
|
translSeqCodonStartGenomicPosArr[startCodonIndex].codonGenomicPos
|
|
@@ -1025,7 +865,7 @@ export const TranscriptWidgetEditLocation = observer(
|
|
|
1025
865
|
const startCodonGenomicLoc = getCodonGenomicLocation(
|
|
1026
866
|
startCodonPos as unknown as number,
|
|
1027
867
|
)
|
|
1028
|
-
|
|
868
|
+
let stopCodonGenomicLoc = getCodonGenomicLocation(
|
|
1029
869
|
stopCodonPos as unknown as number,
|
|
1030
870
|
)
|
|
1031
871
|
|
|
@@ -1038,6 +878,7 @@ export const TranscriptWidgetEditLocation = observer(
|
|
|
1038
878
|
return
|
|
1039
879
|
}
|
|
1040
880
|
let promise
|
|
881
|
+
stopCodonGenomicLoc += 3 // move to end of stop codon
|
|
1041
882
|
if (startCodonGenomicLoc !== cdsMin) {
|
|
1042
883
|
promise = new Promise((resolve) => {
|
|
1043
884
|
updateCDSLocation(
|
|
@@ -1073,6 +914,7 @@ export const TranscriptWidgetEditLocation = observer(
|
|
|
1073
914
|
return
|
|
1074
915
|
}
|
|
1075
916
|
let promise
|
|
917
|
+
stopCodonGenomicLoc -= 3 // move to end of stop codon
|
|
1076
918
|
if (startCodonGenomicLoc !== cdsMax) {
|
|
1077
919
|
promise = new Promise((resolve) => {
|
|
1078
920
|
updateCDSLocation(
|
|
@@ -1142,16 +984,22 @@ export const TranscriptWidgetEditLocation = observer(
|
|
|
1142
984
|
}}
|
|
1143
985
|
>
|
|
1144
986
|
<Tooltip title="Copy">
|
|
1145
|
-
<
|
|
1146
|
-
style={{ fontSize: 15, cursor: 'pointer' }}
|
|
987
|
+
<button
|
|
1147
988
|
onClick={onCopyClick}
|
|
1148
|
-
|
|
989
|
+
style={{ border: 'none', background: 'none', padding: 0 }}
|
|
990
|
+
disabled={changeInProgress}
|
|
991
|
+
>
|
|
992
|
+
<ContentCopyIcon style={{ fontSize: 15 }} />
|
|
993
|
+
</button>
|
|
1149
994
|
</Tooltip>
|
|
1150
995
|
<Tooltip title="Trim">
|
|
1151
|
-
<
|
|
1152
|
-
style={{ fontSize: 15, cursor: 'pointer' }}
|
|
996
|
+
<button
|
|
1153
997
|
onClick={trimTranslationSequence}
|
|
1154
|
-
|
|
998
|
+
style={{ border: 'none', background: 'none', padding: 0 }}
|
|
999
|
+
disabled={changeInProgress}
|
|
1000
|
+
>
|
|
1001
|
+
<ContentCutIcon style={{ fontSize: 15 }} />
|
|
1002
|
+
</button>
|
|
1155
1003
|
</Tooltip>
|
|
1156
1004
|
</div>
|
|
1157
1005
|
</AccordionDetails>
|
|
@@ -1170,7 +1018,7 @@ export const TranscriptWidgetEditLocation = observer(
|
|
|
1170
1018
|
variant="outlined"
|
|
1171
1019
|
value={cdsMin + 1}
|
|
1172
1020
|
onChangeCommitted={(newLocation: number) => {
|
|
1173
|
-
|
|
1021
|
+
return updateCDSLocation(
|
|
1174
1022
|
cdsMin,
|
|
1175
1023
|
newLocation - 1,
|
|
1176
1024
|
feature,
|
|
@@ -1178,6 +1026,7 @@ export const TranscriptWidgetEditLocation = observer(
|
|
|
1178
1026
|
)
|
|
1179
1027
|
}}
|
|
1180
1028
|
style={{ border: '1px solid black', borderRadius: 5 }}
|
|
1029
|
+
disabled={changeInProgress}
|
|
1181
1030
|
/>
|
|
1182
1031
|
</Grid>
|
|
1183
1032
|
) : (
|
|
@@ -1187,7 +1036,7 @@ export const TranscriptWidgetEditLocation = observer(
|
|
|
1187
1036
|
variant="outlined"
|
|
1188
1037
|
value={cdsMax}
|
|
1189
1038
|
onChangeCommitted={(newLocation: number) => {
|
|
1190
|
-
|
|
1039
|
+
return updateCDSLocation(
|
|
1191
1040
|
cdsMax,
|
|
1192
1041
|
newLocation,
|
|
1193
1042
|
feature,
|
|
@@ -1195,6 +1044,7 @@ export const TranscriptWidgetEditLocation = observer(
|
|
|
1195
1044
|
)
|
|
1196
1045
|
}}
|
|
1197
1046
|
style={{ border: '1px solid black', borderRadius: 5 }}
|
|
1047
|
+
disabled={changeInProgress}
|
|
1198
1048
|
/>
|
|
1199
1049
|
</Grid>
|
|
1200
1050
|
)}
|
|
@@ -1208,7 +1058,7 @@ export const TranscriptWidgetEditLocation = observer(
|
|
|
1208
1058
|
variant="outlined"
|
|
1209
1059
|
value={cdsMax}
|
|
1210
1060
|
onChangeCommitted={(newLocation: number) => {
|
|
1211
|
-
|
|
1061
|
+
return updateCDSLocation(
|
|
1212
1062
|
cdsMax,
|
|
1213
1063
|
newLocation,
|
|
1214
1064
|
feature,
|
|
@@ -1216,6 +1066,7 @@ export const TranscriptWidgetEditLocation = observer(
|
|
|
1216
1066
|
)
|
|
1217
1067
|
}}
|
|
1218
1068
|
style={{ border: '1px solid black', borderRadius: 5 }}
|
|
1069
|
+
disabled={changeInProgress}
|
|
1219
1070
|
/>
|
|
1220
1071
|
</Grid>
|
|
1221
1072
|
) : (
|
|
@@ -1225,7 +1076,7 @@ export const TranscriptWidgetEditLocation = observer(
|
|
|
1225
1076
|
variant="outlined"
|
|
1226
1077
|
value={cdsMin + 1}
|
|
1227
1078
|
onChangeCommitted={(newLocation: number) => {
|
|
1228
|
-
|
|
1079
|
+
return updateCDSLocation(
|
|
1229
1080
|
cdsMin,
|
|
1230
1081
|
newLocation - 1,
|
|
1231
1082
|
feature,
|
|
@@ -1233,6 +1084,7 @@ export const TranscriptWidgetEditLocation = observer(
|
|
|
1233
1084
|
)
|
|
1234
1085
|
}}
|
|
1235
1086
|
style={{ border: '1px solid black', borderRadius: 5 }}
|
|
1087
|
+
disabled={changeInProgress}
|
|
1236
1088
|
/>
|
|
1237
1089
|
</Grid>
|
|
1238
1090
|
)}
|
|
@@ -1270,13 +1122,14 @@ export const TranscriptWidgetEditLocation = observer(
|
|
|
1270
1122
|
variant="outlined"
|
|
1271
1123
|
value={loc.min + 1}
|
|
1272
1124
|
onChangeCommitted={(newLocation: number) => {
|
|
1273
|
-
handleExonLocationChange(
|
|
1125
|
+
return handleExonLocationChange(
|
|
1274
1126
|
loc.min,
|
|
1275
1127
|
newLocation - 1,
|
|
1276
1128
|
feature,
|
|
1277
1129
|
true,
|
|
1278
1130
|
)
|
|
1279
1131
|
}}
|
|
1132
|
+
disabled={changeInProgress}
|
|
1280
1133
|
/>
|
|
1281
1134
|
</Grid>
|
|
1282
1135
|
) : (
|
|
@@ -1286,13 +1139,14 @@ export const TranscriptWidgetEditLocation = observer(
|
|
|
1286
1139
|
variant="outlined"
|
|
1287
1140
|
value={loc.max}
|
|
1288
1141
|
onChangeCommitted={(newLocation: number) => {
|
|
1289
|
-
handleExonLocationChange(
|
|
1142
|
+
return handleExonLocationChange(
|
|
1290
1143
|
loc.max,
|
|
1291
1144
|
newLocation,
|
|
1292
1145
|
feature,
|
|
1293
1146
|
false,
|
|
1294
1147
|
)
|
|
1295
1148
|
}}
|
|
1149
|
+
disabled={changeInProgress}
|
|
1296
1150
|
/>
|
|
1297
1151
|
</Grid>
|
|
1298
1152
|
)}
|
|
@@ -1306,13 +1160,14 @@ export const TranscriptWidgetEditLocation = observer(
|
|
|
1306
1160
|
variant="outlined"
|
|
1307
1161
|
value={loc.max}
|
|
1308
1162
|
onChangeCommitted={(newLocation: number) => {
|
|
1309
|
-
handleExonLocationChange(
|
|
1163
|
+
return handleExonLocationChange(
|
|
1310
1164
|
loc.max,
|
|
1311
1165
|
newLocation,
|
|
1312
1166
|
feature,
|
|
1313
1167
|
false,
|
|
1314
1168
|
)
|
|
1315
1169
|
}}
|
|
1170
|
+
disabled={changeInProgress}
|
|
1316
1171
|
/>
|
|
1317
1172
|
</Grid>
|
|
1318
1173
|
) : (
|
|
@@ -1322,13 +1177,14 @@ export const TranscriptWidgetEditLocation = observer(
|
|
|
1322
1177
|
variant="outlined"
|
|
1323
1178
|
value={loc.min + 1}
|
|
1324
1179
|
onChangeCommitted={(newLocation: number) => {
|
|
1325
|
-
handleExonLocationChange(
|
|
1180
|
+
return handleExonLocationChange(
|
|
1326
1181
|
loc.min,
|
|
1327
1182
|
newLocation - 1,
|
|
1328
1183
|
feature,
|
|
1329
1184
|
true,
|
|
1330
1185
|
)
|
|
1331
1186
|
}}
|
|
1187
|
+
disabled={changeInProgress}
|
|
1332
1188
|
/>
|
|
1333
1189
|
</Grid>
|
|
1334
1190
|
)}
|
|
@@ -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
|
+
})
|