@apollo-annotation/jbrowse-plugin-apollo 1.0.0 → 1.1.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/ApolloInternetAccount/components/AuthTypeSelector.d.ts +8 -2
- package/dist/ApolloInternetAccount/components/AuthTypeSelector.d.ts.map +1 -1
- package/dist/ApolloInternetAccount/components/LoginButtons.d.ts +8 -3
- package/dist/ApolloInternetAccount/components/LoginButtons.d.ts.map +1 -1
- package/dist/ApolloInternetAccount/configSchema.d.ts +44 -0
- package/dist/ApolloInternetAccount/configSchema.d.ts.map +1 -0
- package/dist/ApolloInternetAccount/model.d.ts +174 -0
- package/dist/ApolloInternetAccount/model.d.ts.map +1 -0
- package/dist/ApolloJobModel.d.ts.map +1 -1
- package/dist/ApolloRefNameAliasAdapter/configSchema.d.ts +8 -0
- package/dist/ApolloRefNameAliasAdapter/configSchema.d.ts.map +1 -0
- package/dist/ApolloSequenceAdapter/configSchema.d.ts +8 -0
- package/dist/ApolloSequenceAdapter/configSchema.d.ts.map +1 -0
- package/dist/ApolloTextSearchAdapter/configSchema.d.ts +20 -0
- package/dist/ApolloTextSearchAdapter/configSchema.d.ts.map +1 -0
- package/dist/BackendDrivers/CollaborationServerDriver.d.ts +1 -1
- package/dist/BackendDrivers/CollaborationServerDriver.d.ts.map +1 -1
- package/dist/BackendDrivers/LocalDriver/LocalDriver.d.ts.map +1 -1
- package/dist/FeatureDetailsWidget/ApolloFeatureDetailsWidget.d.ts.map +1 -1
- package/dist/FeatureDetailsWidget/ApolloTranscriptDetailsWidget.d.ts.map +1 -1
- package/dist/FeatureDetailsWidget/Attributes.d.ts.map +1 -1
- package/dist/FeatureDetailsWidget/DefaultAttributeEditor.d.ts.map +1 -1
- package/dist/FeatureDetailsWidget/DefaultAttributeViewer.d.ts.map +1 -1
- package/dist/FeatureDetailsWidget/NumberTextField.d.ts.map +1 -1
- package/dist/FeatureDetailsWidget/StringTextField.d.ts.map +1 -1
- package/dist/FeatureDetailsWidget/TranscriptSequence.d.ts.map +1 -1
- package/dist/FeatureDetailsWidget/TranscriptWidgetEditLocation.d.ts.map +1 -1
- package/dist/FeatureDetailsWidget/Translation.d.ts +14 -0
- package/dist/FeatureDetailsWidget/Translation.d.ts.map +1 -0
- package/dist/LinearApolloDisplay/components/CheckResultWarnings.d.ts.map +1 -1
- package/dist/LinearApolloDisplay/configSchema.d.ts +2 -0
- package/dist/LinearApolloDisplay/configSchema.d.ts.map +1 -0
- package/dist/LinearApolloDisplay/glyphs/ExonGlyph.d.ts.map +1 -1
- package/dist/LinearApolloDisplay/glyphs/GeneGlyph.d.ts.map +1 -1
- package/dist/LinearApolloDisplay/glyphs/TranscriptGlyph.d.ts.map +1 -1
- package/dist/LinearApolloDisplay/stateModel/base.d.ts +1 -18
- package/dist/LinearApolloDisplay/stateModel/base.d.ts.map +1 -1
- package/dist/LinearApolloDisplay/stateModel/index.d.ts +1 -17
- package/dist/LinearApolloDisplay/stateModel/index.d.ts.map +1 -1
- package/dist/LinearApolloDisplay/stateModel/layouts.d.ts +2 -19
- package/dist/LinearApolloDisplay/stateModel/layouts.d.ts.map +1 -1
- package/dist/LinearApolloDisplay/stateModel/mouseEvents.d.ts +2 -34
- package/dist/LinearApolloDisplay/stateModel/mouseEvents.d.ts.map +1 -1
- package/dist/LinearApolloDisplay/stateModel/rendering.d.ts +2 -19
- package/dist/LinearApolloDisplay/stateModel/rendering.d.ts.map +1 -1
- package/dist/LinearApolloReferenceSequenceDisplay/configSchema.d.ts +2 -0
- package/dist/LinearApolloReferenceSequenceDisplay/configSchema.d.ts.map +1 -0
- package/dist/LinearApolloReferenceSequenceDisplay/stateModel/base.d.ts +1 -1
- package/dist/LinearApolloReferenceSequenceDisplay/stateModel/base.d.ts.map +1 -1
- package/dist/LinearApolloReferenceSequenceDisplay/stateModel/index.d.ts +1 -1
- package/dist/LinearApolloReferenceSequenceDisplay/stateModel/rendering.d.ts +1 -1
- package/dist/LinearApolloSixFrameDisplay/components/LinearApolloSixFrameDisplay.d.ts.map +1 -1
- package/dist/LinearApolloSixFrameDisplay/configSchema.d.ts +2 -0
- package/dist/LinearApolloSixFrameDisplay/configSchema.d.ts.map +1 -0
- package/dist/LinearApolloSixFrameDisplay/glyphs/GeneGlyph.d.ts.map +1 -1
- package/dist/LinearApolloSixFrameDisplay/stateModel/base.d.ts +1 -1
- package/dist/LinearApolloSixFrameDisplay/stateModel/base.d.ts.map +1 -1
- package/dist/LinearApolloSixFrameDisplay/stateModel/index.d.ts +1 -1
- package/dist/LinearApolloSixFrameDisplay/stateModel/index.d.ts.map +1 -1
- package/dist/LinearApolloSixFrameDisplay/stateModel/layouts.d.ts +2 -3
- package/dist/LinearApolloSixFrameDisplay/stateModel/layouts.d.ts.map +1 -1
- package/dist/LinearApolloSixFrameDisplay/stateModel/mouseEvents.d.ts +2 -2
- package/dist/LinearApolloSixFrameDisplay/stateModel/mouseEvents.d.ts.map +1 -1
- package/dist/LinearApolloSixFrameDisplay/stateModel/rendering.d.ts +2 -3
- package/dist/LinearApolloSixFrameDisplay/stateModel/rendering.d.ts.map +1 -1
- package/dist/OntologyManager/OntologyStore/fulltext.d.ts.map +1 -1
- package/dist/OntologyManager/index.d.ts +734 -0
- package/dist/OntologyManager/index.d.ts.map +1 -0
- package/dist/TabularEditor/HybridGrid/NumberCell.d.ts.map +1 -1
- package/dist/components/AddCodingSequence.d.ts +14 -0
- package/dist/components/AddCodingSequence.d.ts.map +1 -0
- package/dist/components/AddRefSeqAliases.d.ts.map +1 -1
- package/dist/components/CopyFeature.d.ts.map +1 -1
- package/dist/components/CreateApolloAnnotation.d.ts.map +1 -1
- package/dist/components/DeleteFeature.d.ts.map +1 -1
- package/dist/components/DownloadGFF3.d.ts.map +1 -1
- package/dist/components/DuplicateFeatureDialog.d.ts +12 -0
- package/dist/components/DuplicateFeatureDialog.d.ts.map +1 -0
- package/dist/components/ImportAnnotations.d.ts +9 -0
- package/dist/components/ImportAnnotations.d.ts.map +1 -0
- package/dist/components/ManageUsers.d.ts.map +1 -1
- package/dist/components/OntologyTermMultiSelect.d.ts.map +1 -1
- package/dist/components/ViewChangeLog.d.ts.map +1 -1
- package/dist/components/index.d.ts +2 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/extensions/annotationFromPileup.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.esm.js +830 -434
- package/dist/index.esm.js.map +1 -1
- package/dist/jbrowse-plugin-apollo.cjs.development.js +825 -429
- 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 +863 -468
- 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/dist/session/ClientDataStore.d.ts +2194 -0
- package/dist/session/ClientDataStore.d.ts.map +1 -0
- package/dist/session/handleApolloFeaturesUrlParam.d.ts +8 -0
- package/dist/session/handleApolloFeaturesUrlParam.d.ts.map +1 -0
- package/dist/session/session.d.ts +6788 -0
- package/dist/session/session.d.ts.map +1 -0
- package/dist/util/displayUtils.d.ts +36 -0
- package/dist/util/displayUtils.d.ts.map +1 -0
- package/dist/util/sequenceUtils.d.ts +2 -0
- package/dist/util/sequenceUtils.d.ts.map +1 -0
- package/package.json +14 -14
- package/src/ApolloInternetAccount/components/AuthTypeSelector.tsx +73 -38
- package/src/ApolloInternetAccount/components/LoginButtons.tsx +31 -10
- package/src/ApolloInternetAccount/model.ts +8 -5
- package/src/ApolloJobModel.ts +3 -8
- package/src/ApolloTextSearchAdapter/ApolloTextSearchAdapter.ts +1 -1
- package/src/BackendDrivers/CollaborationServerDriver.ts +7 -11
- package/src/BackendDrivers/LocalDriver/LocalDriver.ts +13 -4
- package/src/FeatureDetailsWidget/ApolloFeatureDetailsWidget.tsx +1 -0
- package/src/FeatureDetailsWidget/ApolloTranscriptDetailsWidget.tsx +4 -2
- package/src/FeatureDetailsWidget/Attributes.tsx +1 -0
- package/src/FeatureDetailsWidget/DefaultAttributeEditor.tsx +1 -0
- package/src/FeatureDetailsWidget/DefaultAttributeViewer.tsx +1 -0
- package/src/FeatureDetailsWidget/NumberTextField.tsx +1 -0
- package/src/FeatureDetailsWidget/StringTextField.tsx +1 -0
- package/src/FeatureDetailsWidget/TranscriptSequence.tsx +2 -1
- package/src/FeatureDetailsWidget/TranscriptWidgetEditLocation.tsx +17 -354
- package/src/FeatureDetailsWidget/Translation.tsx +358 -0
- package/src/LinearApolloDisplay/components/CheckResultWarnings.tsx +4 -1
- package/src/LinearApolloDisplay/glyphs/ExonGlyph.ts +2 -5
- package/src/LinearApolloDisplay/glyphs/GeneGlyph.ts +4 -6
- package/src/LinearApolloDisplay/glyphs/TranscriptGlyph.ts +39 -6
- package/src/LinearApolloDisplay/stateModel/base.ts +47 -23
- package/src/LinearApolloDisplay/stateModel/layouts.ts +7 -5
- package/src/LinearApolloDisplay/stateModel/mouseEvents.ts +4 -1
- package/src/LinearApolloDisplay/stateModel/rendering.ts +1 -5
- package/src/LinearApolloReferenceSequenceDisplay/stateModel/base.ts +10 -10
- package/src/LinearApolloSixFrameDisplay/components/LinearApolloSixFrameDisplay.tsx +5 -3
- package/src/LinearApolloSixFrameDisplay/components/TrackLines.tsx +1 -1
- package/src/LinearApolloSixFrameDisplay/glyphs/GeneGlyph.ts +2 -3
- package/src/LinearApolloSixFrameDisplay/stateModel/base.ts +12 -20
- package/src/LinearApolloSixFrameDisplay/stateModel/layouts.ts +10 -6
- package/src/LinearApolloSixFrameDisplay/stateModel/mouseEvents.ts +38 -45
- package/src/LinearApolloSixFrameDisplay/stateModel/rendering.ts +1 -4
- package/src/OntologyManager/OntologyStore/fulltext.ts +0 -2
- package/src/OntologyManager/OntologyStore/index.ts +1 -1
- package/src/TabularEditor/HybridGrid/ChangeHandling.ts +2 -2
- package/src/TabularEditor/HybridGrid/NumberCell.tsx +2 -1
- package/src/components/AddAssemblyAliases.tsx +1 -1
- package/src/components/AddCodingSequence.tsx +255 -0
- package/src/components/AddFeature.tsx +1 -1
- package/src/components/AddRefSeqAliases.tsx +3 -2
- package/src/components/CopyFeature.tsx +9 -7
- package/src/components/CreateApolloAnnotation.tsx +28 -23
- package/src/components/DeleteAssembly.tsx +2 -2
- package/src/components/DeleteFeature.tsx +1 -4
- package/src/components/DownloadGFF3.tsx +4 -3
- package/src/components/DuplicateFeatureDialog.tsx +154 -0
- package/src/components/DuplicateTranscript.tsx +1 -1
- package/src/components/FilterTranscripts.tsx +1 -1
- package/src/components/ImportAnnotations.tsx +108 -0
- package/src/components/ManageUsers.tsx +1 -2
- package/src/components/OntologyTermAutocomplete.tsx +1 -3
- package/src/components/OntologyTermMultiSelect.tsx +3 -1
- package/src/components/ViewChangeLog.tsx +2 -1
- package/src/components/index.ts +2 -0
- package/src/extensions/annotationFromPileup.ts +34 -26
- package/src/index.ts +9 -8
- package/src/session/ClientDataStore.ts +16 -21
- package/src/session/handleApolloFeaturesUrlParam.ts +122 -0
- package/src/session/session.ts +49 -9
- package/src/util/annotationFeatureUtils.ts +1 -1
- package/src/util/displayUtils.ts +1 -1
- package/src/util/glyphUtils.ts +3 -3
- package/src/util/sequenceUtils.ts +29 -0
|
@@ -3107,12 +3107,10 @@
|
|
|
3107
3107
|
}, {
|
|
3108
3108
|
key: "addChild",
|
|
3109
3109
|
value: function addChild(parentFeature, child) {
|
|
3110
|
-
var _parentFeature$attrib;
|
|
3110
|
+
var _parentFeature$attrib, _parentFeature$childr;
|
|
3111
3111
|
if (!((_parentFeature$attrib = parentFeature.attributes) !== null && _parentFeature$attrib !== void 0 && _parentFeature$attrib._id)) {
|
|
3112
|
-
var
|
|
3113
|
-
|
|
3114
|
-
attributes = {};
|
|
3115
|
-
}
|
|
3112
|
+
var _parentFeature$attrib2 = parentFeature.attributes,
|
|
3113
|
+
attributes = _parentFeature$attrib2 === void 0 ? {} : _parentFeature$attrib2;
|
|
3116
3114
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
3117
3115
|
attributes = _objectSpread2({
|
|
3118
3116
|
_id: [parentFeature._id.toString()]
|
|
@@ -3120,9 +3118,7 @@
|
|
|
3120
3118
|
parentFeature.attributes = attributes;
|
|
3121
3119
|
}
|
|
3122
3120
|
var _id = child._id;
|
|
3123
|
-
|
|
3124
|
-
parentFeature.children = new Map();
|
|
3125
|
-
}
|
|
3121
|
+
(_parentFeature$childr = parentFeature.children) !== null && _parentFeature$childr !== void 0 ? _parentFeature$childr : parentFeature.children = new Map();
|
|
3126
3122
|
parentFeature.children.set(_id, _objectSpread2(_objectSpread2({
|
|
3127
3123
|
allIds: []
|
|
3128
3124
|
}, child), {}, {
|
|
@@ -4284,10 +4280,9 @@
|
|
|
4284
4280
|
}, {
|
|
4285
4281
|
key: "mergeFeatureIntoTranscriptOnServer",
|
|
4286
4282
|
value: function mergeFeatureIntoTranscriptOnServer(secondFeatureChild, firstTranscript) {
|
|
4287
|
-
var
|
|
4288
|
-
|
|
4289
|
-
|
|
4290
|
-
}
|
|
4283
|
+
var _firstTranscript$chil,
|
|
4284
|
+
_this2 = this;
|
|
4285
|
+
(_firstTranscript$chil = firstTranscript.children) !== null && _firstTranscript$chil !== void 0 ? _firstTranscript$chil : firstTranscript.children = new Map();
|
|
4291
4286
|
var merged = false;
|
|
4292
4287
|
var mrgChild;
|
|
4293
4288
|
var toDelete;
|
|
@@ -4304,11 +4299,10 @@
|
|
|
4304
4299
|
toDelete = true;
|
|
4305
4300
|
}
|
|
4306
4301
|
if (mrgChild.type === secondFeatureChild.type && mrgChild.type === firstFeatureChild.type && util$1.doesIntersect2(secondFeatureChild.min, secondFeatureChild.max, mrgChild.min, mrgChild.max) && util$1.doesIntersect2(firstFeatureChild.min, firstFeatureChild.max, mrgChild.min, mrgChild.max)) {
|
|
4302
|
+
var _mrgChild, _mrgChild$attributes;
|
|
4307
4303
|
mrgChild.min = Math.min(secondFeatureChild.min, mrgChild.min, firstFeatureChild.min);
|
|
4308
4304
|
mrgChild.max = Math.max(secondFeatureChild.max, mrgChild.max, firstFeatureChild.max);
|
|
4309
|
-
|
|
4310
|
-
mrgChild.attributes = {};
|
|
4311
|
-
}
|
|
4305
|
+
(_mrgChild$attributes = (_mrgChild = mrgChild).attributes) !== null && _mrgChild$attributes !== void 0 ? _mrgChild$attributes : _mrgChild.attributes = {};
|
|
4312
4306
|
var mrgChildAttr = JSON.parse(JSON.stringify(mrgChild.attributes));
|
|
4313
4307
|
if (!Object.keys(mrgChildAttr).includes('merged_with')) {
|
|
4314
4308
|
mrgChildAttr.merged_with = [];
|
|
@@ -4371,9 +4365,8 @@
|
|
|
4371
4365
|
}, {
|
|
4372
4366
|
key: "mergeFeatureIntoTranscriptOnClient",
|
|
4373
4367
|
value: function mergeFeatureIntoTranscriptOnClient(secondFeatureChild, firstTranscript) {
|
|
4374
|
-
|
|
4375
|
-
|
|
4376
|
-
}
|
|
4368
|
+
var _firstTranscript$chil2;
|
|
4369
|
+
(_firstTranscript$chil2 = firstTranscript.children) !== null && _firstTranscript$chil2 !== void 0 ? _firstTranscript$chil2 : firstTranscript.children = new Map();
|
|
4377
4370
|
var merged = false;
|
|
4378
4371
|
var mrgChild;
|
|
4379
4372
|
var toDelete;
|
|
@@ -5633,21 +5626,21 @@
|
|
|
5633
5626
|
var _feature$attributes, _feature$attributes2;
|
|
5634
5627
|
var gff_id = (_feature$attributes = feature.attributes) === null || _feature$attributes === void 0 || (_feature$attributes = _feature$attributes.gff_id) === null || _feature$attributes === void 0 ? void 0 : _feature$attributes.join(', ');
|
|
5635
5628
|
if (gff_id) {
|
|
5636
|
-
return "".concat(gff_id, " (_id: ").concat(feature._id
|
|
5629
|
+
return "".concat(gff_id, " (_id: ").concat(feature._id, ")");
|
|
5637
5630
|
}
|
|
5638
5631
|
var gff_name = (_feature$attributes2 = feature.attributes) === null || _feature$attributes2 === void 0 || (_feature$attributes2 = _feature$attributes2.gff_name) === null || _feature$attributes2 === void 0 ? void 0 : _feature$attributes2.join(', ');
|
|
5639
5632
|
if (gff_name) {
|
|
5640
|
-
return "".concat(gff_name, " (_id: ").concat(feature._id
|
|
5633
|
+
return "".concat(gff_name, " (_id: ").concat(feature._id, ")");
|
|
5641
5634
|
}
|
|
5642
|
-
return "_id: ".concat(feature._id
|
|
5635
|
+
return "_id: ".concat(feature._id);
|
|
5643
5636
|
}
|
|
5644
5637
|
|
|
5645
|
-
var STOP_CODONS;
|
|
5638
|
+
var STOP_CODONS$1;
|
|
5646
5639
|
(function (STOP_CODONS) {
|
|
5647
5640
|
STOP_CODONS[STOP_CODONS["TAG"] = 0] = "TAG";
|
|
5648
5641
|
STOP_CODONS[STOP_CODONS["TAA"] = 1] = "TAA";
|
|
5649
5642
|
STOP_CODONS[STOP_CODONS["TGA"] = 2] = "TGA";
|
|
5650
|
-
})(STOP_CODONS || (STOP_CODONS = {}));
|
|
5643
|
+
})(STOP_CODONS$1 || (STOP_CODONS$1 = {}));
|
|
5651
5644
|
var START_CODONS;
|
|
5652
5645
|
(function (START_CODONS) {
|
|
5653
5646
|
START_CODONS[START_CODONS["ATG"] = 0] = "ATG";
|
|
@@ -5748,8 +5741,8 @@
|
|
|
5748
5741
|
return a.min < b.min ? -1 : 1;
|
|
5749
5742
|
});
|
|
5750
5743
|
var i = 0;
|
|
5751
|
-
var currentStart
|
|
5752
|
-
var currentEnd
|
|
5744
|
+
var currentStart;
|
|
5745
|
+
var currentEnd;
|
|
5753
5746
|
for (var iloc = 0; iloc < sortedLocation.length; iloc++) {
|
|
5754
5747
|
var loc = sortedLocation[iloc];
|
|
5755
5748
|
var phase = loc.phase;
|
|
@@ -5819,20 +5812,20 @@
|
|
|
5819
5812
|
name: CHECK_NAME$1,
|
|
5820
5813
|
cause: CAUSES$1[CAUSES$1.MissingStartCodon],
|
|
5821
5814
|
ids: ids,
|
|
5822
|
-
refSeq: refSeq
|
|
5815
|
+
refSeq: refSeq,
|
|
5823
5816
|
start: cdsStart,
|
|
5824
5817
|
end: cdsStart,
|
|
5825
5818
|
message: "Unexpected start codon \"".concat(start_codon, "\" in feature \"").concat(getPrintableId(feature), "\": ")
|
|
5826
5819
|
});
|
|
5827
5820
|
}
|
|
5828
5821
|
lastCodon = codons.at(-1); // Last codon is supposed to be a stop
|
|
5829
|
-
if (lastCodon && !(lastCodon.toUpperCase() in STOP_CODONS)) {
|
|
5822
|
+
if (lastCodon && !(lastCodon.toUpperCase() in STOP_CODONS$1)) {
|
|
5830
5823
|
checkResults.push({
|
|
5831
5824
|
_id: new ObjectID().toHexString(),
|
|
5832
5825
|
name: CHECK_NAME$1,
|
|
5833
5826
|
cause: CAUSES$1[CAUSES$1.MissingStopCodon],
|
|
5834
5827
|
ids: ids,
|
|
5835
|
-
refSeq: refSeq
|
|
5828
|
+
refSeq: refSeq,
|
|
5836
5829
|
start: cdsEnd,
|
|
5837
5830
|
end: cdsEnd,
|
|
5838
5831
|
message: "Missing stop codon in feature \"".concat(getPrintableId(feature), "\"")
|
|
@@ -5844,7 +5837,7 @@
|
|
|
5844
5837
|
name: CHECK_NAME$1,
|
|
5845
5838
|
cause: CAUSES$1[CAUSES$1.MissingStopCodon],
|
|
5846
5839
|
ids: ids,
|
|
5847
|
-
refSeq: refSeq
|
|
5840
|
+
refSeq: refSeq,
|
|
5848
5841
|
start: cdsEnd,
|
|
5849
5842
|
end: cdsEnd,
|
|
5850
5843
|
message: "Missing stop codon in feature \"".concat(getPrintableId(feature), "\"")
|
|
@@ -5866,14 +5859,14 @@
|
|
|
5866
5859
|
return _context3.a(3, 9);
|
|
5867
5860
|
case 7:
|
|
5868
5861
|
location = getOriginalCodonLocation(cdsLocation, strand, idx);
|
|
5869
|
-
if (location && codon.toUpperCase() in STOP_CODONS) {
|
|
5862
|
+
if (location && codon.toUpperCase() in STOP_CODONS$1) {
|
|
5870
5863
|
_location = _slicedToArray(location, 2), codonStart = _location[0], codonEnd = _location[1];
|
|
5871
5864
|
checkResults.push({
|
|
5872
5865
|
_id: new ObjectID().toHexString(),
|
|
5873
5866
|
name: CHECK_NAME$1,
|
|
5874
5867
|
cause: CAUSES$1[CAUSES$1.InternalStopCodon],
|
|
5875
5868
|
ids: ids,
|
|
5876
|
-
refSeq: refSeq
|
|
5869
|
+
refSeq: refSeq,
|
|
5877
5870
|
start: codonStart,
|
|
5878
5871
|
end: codonEnd,
|
|
5879
5872
|
message: "Internal stop codon in feature \"".concat(getPrintableId(feature), "\"")
|
|
@@ -6171,7 +6164,7 @@
|
|
|
6171
6164
|
name: CHECK_NAME,
|
|
6172
6165
|
cause: CAUSES[CAUSES.NonCanonicalSpliceSiteAtFivePrime],
|
|
6173
6166
|
ids: [feature._id],
|
|
6174
|
-
refSeq: feature.refSeq
|
|
6167
|
+
refSeq: feature.refSeq,
|
|
6175
6168
|
start: spliceSequence.fivePrimeMin,
|
|
6176
6169
|
end: spliceSequence.fivePrimeMin + 2,
|
|
6177
6170
|
message: "Unexpected 5\u2032 splice site in \"".concat(getPrintableId(feature), "\". Expected: ").concat(_toConsumableArray(VALID_FIVE_PRIME_SEQ).join('|'), ", got: ").concat(spliceSequence.fivePrimeSeq)
|
|
@@ -6183,7 +6176,7 @@
|
|
|
6183
6176
|
name: CHECK_NAME,
|
|
6184
6177
|
cause: CAUSES[CAUSES.NonCanonicalSpliceSiteAtThreePrime],
|
|
6185
6178
|
ids: [feature._id],
|
|
6186
|
-
refSeq: feature.refSeq
|
|
6179
|
+
refSeq: feature.refSeq,
|
|
6187
6180
|
start: spliceSequence.threePrimeMin,
|
|
6188
6181
|
end: spliceSequence.threePrimeMin + 2,
|
|
6189
6182
|
message: "Unexpected 3\u2032 splice site in \"".concat(getPrintableId(feature), "\". Expected: ").concat(_toConsumableArray(VALID_THREE_PRIME_SEQ).join('|'), ", got: ").concat(spliceSequence.threePrimeSeq)
|
|
@@ -6351,8 +6344,8 @@
|
|
|
6351
6344
|
delete attributes.gff_score;
|
|
6352
6345
|
}
|
|
6353
6346
|
return {
|
|
6354
|
-
start:
|
|
6355
|
-
end:
|
|
6347
|
+
start: featureLoc.min + 1,
|
|
6348
|
+
end: featureLoc.max,
|
|
6356
6349
|
seq_id: featureLoc.refSeq,
|
|
6357
6350
|
source: source,
|
|
6358
6351
|
type: featureLoc.type,
|
|
@@ -6557,7 +6550,7 @@
|
|
|
6557
6550
|
return transcriptParts;
|
|
6558
6551
|
}
|
|
6559
6552
|
function getCdsLocations(feature) {
|
|
6560
|
-
var transcriptParts
|
|
6553
|
+
var transcriptParts;
|
|
6561
6554
|
try {
|
|
6562
6555
|
transcriptParts = getTranscriptParts(feature);
|
|
6563
6556
|
} catch (_unused) {
|
|
@@ -7122,7 +7115,7 @@
|
|
|
7122
7115
|
d: "M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6z"
|
|
7123
7116
|
}), 'Add');
|
|
7124
7117
|
|
|
7125
|
-
var version = "1.
|
|
7118
|
+
var version = "1.1.0";
|
|
7126
7119
|
|
|
7127
7120
|
const ApolloConfigSchema = configuration.ConfigurationSchema('ApolloInternetAccount', {
|
|
7128
7121
|
baseURL: {
|
|
@@ -21815,9 +21808,7 @@
|
|
|
21815
21808
|
result = customTermList;
|
|
21816
21809
|
}
|
|
21817
21810
|
}
|
|
21818
|
-
|
|
21819
|
-
result = await ontologyStore.getAllTerms();
|
|
21820
|
-
}
|
|
21811
|
+
result ??= await ontologyStore.getAllTerms();
|
|
21821
21812
|
return filterTerms ? result.filter((element) => filterTerms(element)) : result;
|
|
21822
21813
|
}
|
|
21823
21814
|
|
|
@@ -21998,7 +21989,7 @@
|
|
|
21998
21989
|
setErrorMessage('No assemblies to copy to');
|
|
21999
21990
|
return;
|
|
22000
21991
|
}
|
|
22001
|
-
const assembly = await assemblyManager.waitForAssembly(selectedAssemblyId);
|
|
21992
|
+
const assembly = (await assemblyManager.waitForAssembly(selectedAssemblyId));
|
|
22002
21993
|
if (!assembly) {
|
|
22003
21994
|
return;
|
|
22004
21995
|
}
|
|
@@ -22027,7 +22018,7 @@
|
|
|
22027
22018
|
event.preventDefault();
|
|
22028
22019
|
setErrorMessage('');
|
|
22029
22020
|
const featureLength = sourceFeature.length;
|
|
22030
|
-
const assembly = await assemblyManager.waitForAssembly(selectedAssemblyId);
|
|
22021
|
+
const assembly = (await assemblyManager.waitForAssembly(selectedAssemblyId));
|
|
22031
22022
|
if (!assembly) {
|
|
22032
22023
|
setErrorMessage(`Assembly not found: ${selectedAssemblyId}.`);
|
|
22033
22024
|
return;
|
|
@@ -22365,8 +22356,7 @@
|
|
|
22365
22356
|
locationChanges.push(geneChange);
|
|
22366
22357
|
}
|
|
22367
22358
|
}
|
|
22368
|
-
if (featureTypeOntology
|
|
22369
|
-
featureTypeOntology.isTypeOf(sourceFeature.type, 'exon')) {
|
|
22359
|
+
if (featureTypeOntology?.isTypeOf(sourceFeature.type, 'exon')) {
|
|
22370
22360
|
const cdsChange = trimCDS(sourceFeature);
|
|
22371
22361
|
if (cdsChange) {
|
|
22372
22362
|
if (cdsChange.typeName === 'DeleteFeatureChange') {
|
|
@@ -22619,7 +22609,7 @@
|
|
|
22619
22609
|
return;
|
|
22620
22610
|
}
|
|
22621
22611
|
function isSelectedFeature(feature, selectedFeature) {
|
|
22622
|
-
return
|
|
22612
|
+
return feature._id === selectedFeature?._id;
|
|
22623
22613
|
}
|
|
22624
22614
|
function makeFeatureLabel(feature) {
|
|
22625
22615
|
let name;
|
|
@@ -23225,6 +23215,153 @@
|
|
|
23225
23215
|
}, pageSizeOptions: [5], processRowUpdate: processRowUpdate, disableRowSelectionOnClick: true }) }) }), errorMessage ? (jsxRuntime.jsx(material.DialogContent, { children: jsxRuntime.jsx(material.DialogContentText, { color: "error", children: errorMessage }) })) : null] }));
|
|
23226
23216
|
}
|
|
23227
23217
|
|
|
23218
|
+
const START_CODON = 'ATG';
|
|
23219
|
+
const STOP_CODONS = new Set(['TAA', 'TAG', 'TGA']);
|
|
23220
|
+
function findLongestOrf(sequence) {
|
|
23221
|
+
const starts = [
|
|
23222
|
+
null,
|
|
23223
|
+
null,
|
|
23224
|
+
null,
|
|
23225
|
+
];
|
|
23226
|
+
let longest;
|
|
23227
|
+
for (let start = 0; start < sequence.length - 2; start++) {
|
|
23228
|
+
const codon = sequence.slice(start, start + 3).toUpperCase();
|
|
23229
|
+
const frame = (start % 3);
|
|
23230
|
+
if (codon === START_CODON && starts[frame] === null) {
|
|
23231
|
+
starts[frame] = start;
|
|
23232
|
+
}
|
|
23233
|
+
else if (STOP_CODONS.has(codon)) {
|
|
23234
|
+
const inFrameStart = starts[frame];
|
|
23235
|
+
if (inFrameStart === null) {
|
|
23236
|
+
continue;
|
|
23237
|
+
}
|
|
23238
|
+
const length = start - inFrameStart;
|
|
23239
|
+
if (!longest || longest[1] - longest[0] < length) {
|
|
23240
|
+
longest = [inFrameStart, start];
|
|
23241
|
+
}
|
|
23242
|
+
starts[frame] = null;
|
|
23243
|
+
}
|
|
23244
|
+
}
|
|
23245
|
+
return longest;
|
|
23246
|
+
}
|
|
23247
|
+
|
|
23248
|
+
// Returns the genomic half-open boundary for stitched position `pos`.
|
|
23249
|
+
// For strand +1: the inclusive start (min) of the nucleotide.
|
|
23250
|
+
// For strand -1: the exclusive end (max) of the nucleotide.
|
|
23251
|
+
// Symmetric usage:
|
|
23252
|
+
// plus: cdsMin = helper(orf[0]), cdsMax = helper(orf[1]+3)
|
|
23253
|
+
// minus: cdsMax = helper(orf[0]), cdsMin = helper(orf[1]+3)
|
|
23254
|
+
function stitchedToGenomicBound(pos, exons, strand) {
|
|
23255
|
+
let cum = 0;
|
|
23256
|
+
for (const exon of exons) {
|
|
23257
|
+
const len = exon.max - exon.min;
|
|
23258
|
+
if (pos <= cum + len) {
|
|
23259
|
+
const off = pos - cum;
|
|
23260
|
+
return strand === 1 ? exon.min + off : exon.max - off;
|
|
23261
|
+
}
|
|
23262
|
+
cum += len;
|
|
23263
|
+
}
|
|
23264
|
+
const last = exons.at(-1);
|
|
23265
|
+
if (!last) {
|
|
23266
|
+
throw new Error('No exons found');
|
|
23267
|
+
}
|
|
23268
|
+
return strand === 1 ? last.max : last.min;
|
|
23269
|
+
}
|
|
23270
|
+
function AddCodingSequence({ changeManager, handleClose, refName, session, sourceAssemblyId, sourceFeature, }) {
|
|
23271
|
+
const [method, setMethod] = React.useState('longest-orf');
|
|
23272
|
+
const [minInput, setMinInput] = React.useState('');
|
|
23273
|
+
const [maxInput, setMaxInput] = React.useState('');
|
|
23274
|
+
const [errorMessage, setErrorMessage] = React.useState('');
|
|
23275
|
+
async function onSubmit(event) {
|
|
23276
|
+
event.preventDefault();
|
|
23277
|
+
setErrorMessage('');
|
|
23278
|
+
let cdsMin;
|
|
23279
|
+
let cdsMax;
|
|
23280
|
+
try {
|
|
23281
|
+
if (method === 'longest-orf') {
|
|
23282
|
+
const exonParts = sourceFeature.transcriptExonParts.filter((p) => p.type === 'exon');
|
|
23283
|
+
if (exonParts.length === 0) {
|
|
23284
|
+
setErrorMessage('No exons found in this transcript');
|
|
23285
|
+
return;
|
|
23286
|
+
}
|
|
23287
|
+
const backendDriver = session.apolloDataStore.getBackendDriver(sourceAssemblyId);
|
|
23288
|
+
if (!backendDriver) {
|
|
23289
|
+
setErrorMessage('No backend driver found for this assembly');
|
|
23290
|
+
return;
|
|
23291
|
+
}
|
|
23292
|
+
let stitchedSequence = '';
|
|
23293
|
+
for (const exon of exonParts) {
|
|
23294
|
+
const { seq } = await backendDriver.getSequence({
|
|
23295
|
+
assemblyName: sourceAssemblyId,
|
|
23296
|
+
refName,
|
|
23297
|
+
start: exon.min,
|
|
23298
|
+
end: exon.max,
|
|
23299
|
+
});
|
|
23300
|
+
stitchedSequence += sourceFeature.strand === -1 ? util$1.revcom(seq) : seq;
|
|
23301
|
+
}
|
|
23302
|
+
const orf = findLongestOrf(stitchedSequence);
|
|
23303
|
+
if (!orf) {
|
|
23304
|
+
;
|
|
23305
|
+
session.notify('No open reading frame found in this transcript', 'error');
|
|
23306
|
+
handleClose();
|
|
23307
|
+
return;
|
|
23308
|
+
}
|
|
23309
|
+
const strand = sourceFeature.strand ?? 1;
|
|
23310
|
+
if (strand === 1) {
|
|
23311
|
+
cdsMin = stitchedToGenomicBound(orf[0], exonParts, 1);
|
|
23312
|
+
cdsMax = stitchedToGenomicBound(orf[1] + 3, exonParts, 1);
|
|
23313
|
+
}
|
|
23314
|
+
else {
|
|
23315
|
+
cdsMax = stitchedToGenomicBound(orf[0], exonParts, -1);
|
|
23316
|
+
cdsMin = stitchedToGenomicBound(orf[1] + 3, exonParts, -1);
|
|
23317
|
+
}
|
|
23318
|
+
}
|
|
23319
|
+
else {
|
|
23320
|
+
cdsMin = Number(minInput) - 1;
|
|
23321
|
+
cdsMax = Number(maxInput);
|
|
23322
|
+
}
|
|
23323
|
+
const _id = new ObjectID().toHexString();
|
|
23324
|
+
const addedFeature = {
|
|
23325
|
+
_id,
|
|
23326
|
+
refSeq: sourceFeature.refSeq,
|
|
23327
|
+
min: cdsMin,
|
|
23328
|
+
max: cdsMax,
|
|
23329
|
+
type: 'CDS',
|
|
23330
|
+
};
|
|
23331
|
+
if (sourceFeature.strand) {
|
|
23332
|
+
addedFeature.strand = sourceFeature.strand;
|
|
23333
|
+
}
|
|
23334
|
+
const change = new AddFeatureChange({
|
|
23335
|
+
changedIds: [sourceFeature._id],
|
|
23336
|
+
typeName: 'AddFeatureChange',
|
|
23337
|
+
assembly: sourceAssemblyId,
|
|
23338
|
+
addedFeature,
|
|
23339
|
+
parentFeatureId: sourceFeature._id,
|
|
23340
|
+
});
|
|
23341
|
+
await changeManager.submit(change);
|
|
23342
|
+
session.apolloSetSelectedFeature(_id);
|
|
23343
|
+
handleClose();
|
|
23344
|
+
}
|
|
23345
|
+
catch (error) {
|
|
23346
|
+
setErrorMessage(error instanceof Error ? error.message : 'An unknown error occurred');
|
|
23347
|
+
}
|
|
23348
|
+
}
|
|
23349
|
+
const manualError = method === 'manual' &&
|
|
23350
|
+
Boolean(minInput) &&
|
|
23351
|
+
Boolean(maxInput) &&
|
|
23352
|
+
Number(maxInput) <= Number(minInput);
|
|
23353
|
+
const submitDisabled = method === 'manual' ? !(minInput && maxInput) || manualError : false;
|
|
23354
|
+
return (jsxRuntime.jsxs(Dialog, { open: true, title: "Add coding sequence", handleClose: handleClose, maxWidth: false, "data-testid": "add-coding-sequence", children: [jsxRuntime.jsxs("form", { onSubmit: (event) => {
|
|
23355
|
+
void onSubmit(event);
|
|
23356
|
+
}, children: [jsxRuntime.jsxs(material.DialogContent, { style: { display: 'flex', flexDirection: 'column' }, children: [jsxRuntime.jsx(material.FormControl, { children: jsxRuntime.jsxs(material.RadioGroup, { value: method, onChange: (e) => {
|
|
23357
|
+
setMethod(e.target.value);
|
|
23358
|
+
}, children: [jsxRuntime.jsx(material.FormControlLabel, { value: "longest-orf", control: jsxRuntime.jsx(material.Radio, {}), label: "Calculate longest open reading frame" }), jsxRuntime.jsx(material.FormControlLabel, { value: "manual", control: jsxRuntime.jsx(material.Radio, {}), label: "Manual" })] }) }), method === 'manual' ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(material.TextField, { margin: "dense", id: "cds-min", label: "Min", type: "number", fullWidth: true, variant: "outlined", value: minInput, onChange: (e) => {
|
|
23359
|
+
setMinInput(e.target.value);
|
|
23360
|
+
} }), jsxRuntime.jsx(material.TextField, { margin: "dense", id: "cds-max", label: "Max", type: "number", fullWidth: true, variant: "outlined", value: maxInput, onChange: (e) => {
|
|
23361
|
+
setMaxInput(e.target.value);
|
|
23362
|
+
}, error: manualError, helperText: manualError ? '"Max" must be greater than "Min"' : null })] })) : null] }), jsxRuntime.jsxs(material.DialogActions, { children: [jsxRuntime.jsx(material.Button, { variant: "contained", type: "submit", disabled: submitDisabled, children: "Submit" }), jsxRuntime.jsx(material.Button, { variant: "outlined", type: "button", onClick: handleClose, children: "Cancel" })] })] }), errorMessage ? (jsxRuntime.jsx(material.DialogContent, { children: jsxRuntime.jsx(material.DialogContentText, { color: "error", children: errorMessage }) })) : null] }));
|
|
23363
|
+
}
|
|
23364
|
+
|
|
23228
23365
|
class BackendDriver {
|
|
23229
23366
|
clientStore;
|
|
23230
23367
|
constructor(clientStore) {
|
|
@@ -23297,7 +23434,7 @@
|
|
|
23297
23434
|
async getSequence(region) {
|
|
23298
23435
|
const session = util$1.getSession(this.clientStore);
|
|
23299
23436
|
const { assemblyManager } = session;
|
|
23300
|
-
const assembly = await assemblyManager.waitForAssembly(region.assemblyName);
|
|
23437
|
+
const assembly = (await assemblyManager.waitForAssembly(region.assemblyName));
|
|
23301
23438
|
if (!assembly) {
|
|
23302
23439
|
throw new Error(`Assembly not found: "${region.assemblyName}"`);
|
|
23303
23440
|
}
|
|
@@ -23316,7 +23453,10 @@
|
|
|
23316
23453
|
const adapter = new CLASS(
|
|
23317
23454
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
23318
23455
|
adapterConf, undefined, pluginManager);
|
|
23319
|
-
const seq = await adapter.getSequence(
|
|
23456
|
+
const seq = await adapter.getSequence({
|
|
23457
|
+
...region,
|
|
23458
|
+
refName: assembly.getSeqAdapterRefName(region.refName),
|
|
23459
|
+
});
|
|
23320
23460
|
if (!seq) {
|
|
23321
23461
|
throw new Error(`Sequence not found: ${JSON.stringify(region)}`);
|
|
23322
23462
|
}
|
|
@@ -23325,7 +23465,7 @@
|
|
|
23325
23465
|
async getRegions(assemblyName) {
|
|
23326
23466
|
const session = util$1.getSession(this.clientStore);
|
|
23327
23467
|
const { assemblyManager } = session;
|
|
23328
|
-
const assembly = await assemblyManager.waitForAssembly(assemblyName);
|
|
23468
|
+
const assembly = (await assemblyManager.waitForAssembly(assemblyName));
|
|
23329
23469
|
if (!assembly) {
|
|
23330
23470
|
throw new Error(`Assembly not found: "${assemblyName}"`);
|
|
23331
23471
|
}
|
|
@@ -23341,7 +23481,7 @@
|
|
|
23341
23481
|
async getRefNameAliases(assemblyName) {
|
|
23342
23482
|
const session = util$1.getSession(this.clientStore);
|
|
23343
23483
|
const { assemblyManager } = session;
|
|
23344
|
-
const assembly = await assemblyManager.waitForAssembly(assemblyName);
|
|
23484
|
+
const assembly = (await assemblyManager.waitForAssembly(assemblyName));
|
|
23345
23485
|
if (!assembly) {
|
|
23346
23486
|
throw new Error(`Assembly not found: "${assemblyName}"`);
|
|
23347
23487
|
}
|
|
@@ -24000,7 +24140,7 @@
|
|
|
24000
24140
|
const localSessionId = makeUserSessionId(token);
|
|
24001
24141
|
const changeManager = new ChangeManager(this.clientStore);
|
|
24002
24142
|
// Save server last change sequence into session storage
|
|
24003
|
-
internetAccount.setLastChangeSequenceNumber(
|
|
24143
|
+
internetAccount.setLastChangeSequenceNumber(message.changeSequence);
|
|
24004
24144
|
if (message.userSessionId === localSessionId) {
|
|
24005
24145
|
return; // we did this change, no need to apply it again
|
|
24006
24146
|
}
|
|
@@ -24048,14 +24188,10 @@
|
|
|
24048
24188
|
const seq = await inFlightPromise;
|
|
24049
24189
|
return { seq, refSeq };
|
|
24050
24190
|
}
|
|
24051
|
-
|
|
24052
|
-
|
|
24053
|
-
|
|
24054
|
-
|
|
24055
|
-
let apolloRefSeq = apolloAssembly.refSeqs.get(refSeq);
|
|
24056
|
-
if (!apolloRefSeq) {
|
|
24057
|
-
apolloRefSeq = apolloAssembly.addRefSeq(refSeq, refName);
|
|
24058
|
-
}
|
|
24191
|
+
const apolloAssembly = this.clientStore.assemblies.get(assemblyName) ??
|
|
24192
|
+
this.clientStore.addAssembly(assemblyName);
|
|
24193
|
+
const apolloRefSeq = apolloAssembly.refSeqs.get(refSeq) ??
|
|
24194
|
+
apolloAssembly.addRefSeq(refSeq, refName);
|
|
24059
24195
|
const clientStoreSequence = apolloRefSeq.getSequence(start, end);
|
|
24060
24196
|
if (clientStoreSequence.length === end - start) {
|
|
24061
24197
|
return { seq: clientStoreSequence, refSeq };
|
|
@@ -24412,7 +24548,7 @@
|
|
|
24412
24548
|
setType(NewFeature[value]);
|
|
24413
24549
|
}
|
|
24414
24550
|
};
|
|
24415
|
-
let submitDisabled =
|
|
24551
|
+
let submitDisabled = error || !(start && end && type);
|
|
24416
24552
|
if ((type === NewFeature.CUSTOM && !customType) ||
|
|
24417
24553
|
(!strand && type === NewFeature.GENE_AND_SUBFEATURES) ||
|
|
24418
24554
|
(!strand && type === NewFeature.TRANSCRIPT_AND_SUBFEATURES)) {
|
|
@@ -24433,7 +24569,7 @@
|
|
|
24433
24569
|
function DeleteAssembly({ changeManager, handleClose, session, }) {
|
|
24434
24570
|
const { internetAccounts } = mobxStateTree.getRoot(session);
|
|
24435
24571
|
const [errorMessage, setErrorMessage] = React.useState('');
|
|
24436
|
-
const [confirmDelete,
|
|
24572
|
+
const [confirmDelete, setConfirmDelete] = React.useState(false);
|
|
24437
24573
|
const [submitted, setSubmitted] = React.useState(false);
|
|
24438
24574
|
const apolloInternetAccounts = internetAccounts.filter((ia) => ia.type === 'ApolloInternetAccount');
|
|
24439
24575
|
if (apolloInternetAccounts.length === 0) {
|
|
@@ -24474,7 +24610,7 @@
|
|
|
24474
24610
|
event.preventDefault();
|
|
24475
24611
|
}
|
|
24476
24612
|
return (jsxRuntime.jsxs(Dialog, { open: true, title: "Delete Assembly", handleClose: handleClose, maxWidth: false, "data-testid": "delete-assembly", children: [jsxRuntime.jsxs("form", { onSubmit: onSubmit, children: [jsxRuntime.jsxs(material.DialogContent, { style: { display: 'flex', flexDirection: 'column' }, children: [apolloInternetAccounts.length > 1 ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(material.DialogContentText, { children: "Select account" }), jsxRuntime.jsx(material.Select, { value: selectedInternetAccount.internetAccountId, onChange: handleChangeInternetAccount, disabled: submitted && !errorMessage, children: internetAccounts.map((option) => (jsxRuntime.jsx(material.MenuItem, { value: option.internetAccountId, children: option.name }, option.id))) })] })) : null, jsxRuntime.jsx(material.DialogContentText, { children: "Select assembly" }), jsxRuntime.jsx(material.Select, { labelId: "label", value: selectedAssembly?.name ?? '', onChange: handleChangeAssembly, disabled: assemblies.length === 0, children: assemblies.map((option) => (jsxRuntime.jsx(material.MenuItem, { value: option.name, children: option.displayName }, option.name))) }), jsxRuntime.jsx(material.DialogContentText, { children: jsxRuntime.jsx("strong", { style: { color: 'red' }, children: "NOTE: All assembly data will be deleted and this operation cannot be undone!" }) }), jsxRuntime.jsx(material.FormGroup, { children: jsxRuntime.jsx(material.FormControlLabel, { control: jsxRuntime.jsx(material.Checkbox, { checked: confirmDelete, onChange: () => {
|
|
24477
|
-
|
|
24613
|
+
setConfirmDelete(!confirmDelete);
|
|
24478
24614
|
} }), label: "I understand that all assembly data will be deleted" }) })] }), jsxRuntime.jsxs(material.DialogActions, { children: [jsxRuntime.jsx(material.Button, { disabled: !selectedAssembly || !confirmDelete, variant: "contained", type: "submit", children: "Delete" }), jsxRuntime.jsx(material.Button, { variant: "outlined", type: "submit", onClick: handleClose, children: "Cancel" })] })] }), errorMessage ? (jsxRuntime.jsx(material.DialogContent, { children: jsxRuntime.jsx(material.DialogContentText, { color: "error", children: errorMessage }) })) : null] }));
|
|
24479
24615
|
}
|
|
24480
24616
|
|
|
@@ -25555,7 +25691,7 @@
|
|
|
25555
25691
|
return (jsxRuntime.jsx(material.SvgIcon, { viewBox: "0 0 24 24", ...props, children: jsxRuntime.jsx("path", { d: "M23,12L19,8V11H10V13H19V16M1,18V6C1,4.89 1.9,4 3,4H15A2,2 0 0,1 17,6V9H15V6H3V18H15V15H17V18A2,2 0 0,1 15,20H3A2,2 0 0,1 1,18Z" }) }));
|
|
25556
25692
|
}
|
|
25557
25693
|
function DownloadGFF3({ handleClose, session, assembly: assemblyName, }) {
|
|
25558
|
-
const [includeFASTA,
|
|
25694
|
+
const [includeFASTA, setIncludeFASTA] = React.useState(false);
|
|
25559
25695
|
const [errorMessage, setErrorMessage] = React.useState('');
|
|
25560
25696
|
const { getInternetAccount } = session.apolloDataStore;
|
|
25561
25697
|
const { assemblyManager } = session;
|
|
@@ -25604,7 +25740,7 @@
|
|
|
25604
25740
|
window.open(exportUri, '_blank');
|
|
25605
25741
|
}
|
|
25606
25742
|
return (jsxRuntime.jsxs(Dialog, { open: true, title: "Export annotations", handleClose: handleClose, maxWidth: false, "data-testid": "download-gff3", children: [jsxRuntime.jsxs("form", { onSubmit: onSubmit, children: [jsxRuntime.jsxs(material.DialogContent, { style: { display: 'flex', flexDirection: 'column' }, children: [jsxRuntime.jsxs(material.DialogContentText, { children: ["Exporting annotations for ", assemblyName] }), jsxRuntime.jsx(material.FormGroup, { children: jsxRuntime.jsx(material.FormControlLabel, { "data-testid": "include-fasta-checkbox", control: jsxRuntime.jsx(material.Checkbox, { checked: includeFASTA, onChange: () => {
|
|
25607
|
-
|
|
25743
|
+
setIncludeFASTA(!includeFASTA);
|
|
25608
25744
|
}, disabled: !internetAccountConfigId }), label: "Include fasta sequence in GFF output" }) })] }), jsxRuntime.jsxs(material.DialogActions, { children: [jsxRuntime.jsx(material.Button, { variant: "contained", type: "submit", children: "Download" }), jsxRuntime.jsx(material.Button, { variant: "outlined", type: "submit", onClick: handleClose, children: "Cancel" })] })] }), errorMessage ? (jsxRuntime.jsx(material.DialogContent, { children: jsxRuntime.jsx(material.DialogContentText, { color: "error", children: errorMessage }) })) : null] }));
|
|
25609
25745
|
}
|
|
25610
25746
|
function getAssemblyGFF3Stream(assemblyName) {
|
|
@@ -25643,6 +25779,49 @@
|
|
|
25643
25779
|
db.close();
|
|
25644
25780
|
}
|
|
25645
25781
|
|
|
25782
|
+
function ImportAnnotations({ assemblyName, handleClose, session, }) {
|
|
25783
|
+
const { changeManager } = session.apolloDataStore;
|
|
25784
|
+
const [file, setFile] = React.useState();
|
|
25785
|
+
const [errorMessage, setErrorMessage] = React.useState('');
|
|
25786
|
+
const [loading, setLoading] = React.useState(false);
|
|
25787
|
+
function handleChangeFile(e) {
|
|
25788
|
+
if (e.target.files) {
|
|
25789
|
+
setFile(e.target.files[0]);
|
|
25790
|
+
}
|
|
25791
|
+
}
|
|
25792
|
+
async function onSubmit(event) {
|
|
25793
|
+
event.preventDefault();
|
|
25794
|
+
if (!file) {
|
|
25795
|
+
return;
|
|
25796
|
+
}
|
|
25797
|
+
setLoading(true);
|
|
25798
|
+
setErrorMessage('');
|
|
25799
|
+
try {
|
|
25800
|
+
const stream = file
|
|
25801
|
+
.stream()
|
|
25802
|
+
.pipeThrough(new TransformStream(new esmExports.GFFTransformer({ parseSequences: false })));
|
|
25803
|
+
for await (const value of stream) {
|
|
25804
|
+
const annotationFeature = gff3ToAnnotationFeature(value);
|
|
25805
|
+
const change = new AddFeatureChange({
|
|
25806
|
+
changedIds: [annotationFeature._id],
|
|
25807
|
+
typeName: 'AddFeatureChange',
|
|
25808
|
+
assembly: assemblyName,
|
|
25809
|
+
addedFeature: annotationFeature,
|
|
25810
|
+
});
|
|
25811
|
+
await changeManager.submit(change);
|
|
25812
|
+
}
|
|
25813
|
+
handleClose();
|
|
25814
|
+
}
|
|
25815
|
+
catch (error) {
|
|
25816
|
+
setErrorMessage(String(error));
|
|
25817
|
+
}
|
|
25818
|
+
finally {
|
|
25819
|
+
setLoading(false);
|
|
25820
|
+
}
|
|
25821
|
+
}
|
|
25822
|
+
return (jsxRuntime.jsxs(Dialog, { open: true, title: "Import annotations", handleClose: handleClose, children: [loading ? jsxRuntime.jsx(material.LinearProgress, {}) : null, jsxRuntime.jsxs("form", { onSubmit: onSubmit, children: [jsxRuntime.jsxs(material.DialogContent, { children: [jsxRuntime.jsx(material.DialogContentText, { children: "Import annotations from a GFF3 file into the current Apollo track. Features are parsed and stored locally in the browser, so importing very large GFF3 files is not recommended." }), jsxRuntime.jsx("input", { type: "file", accept: ".gff,.gff3", onChange: handleChangeFile, disabled: loading }), errorMessage ? (jsxRuntime.jsx(material.DialogContentText, { color: "error", children: errorMessage })) : null] }), jsxRuntime.jsxs(material.DialogActions, { children: [jsxRuntime.jsx(material.Button, { variant: "contained", type: "submit", disabled: !file || loading, children: "Import" }), jsxRuntime.jsx(material.Button, { variant: "outlined", onClick: handleClose, children: "Cancel" })] })] })] }));
|
|
25823
|
+
}
|
|
25824
|
+
|
|
25646
25825
|
function ImportFeatures({ changeManager, handleClose, session, }) {
|
|
25647
25826
|
const { apolloDataStore } = session;
|
|
25648
25827
|
const [file, setFile] = React.useState();
|
|
@@ -26046,7 +26225,7 @@
|
|
|
26046
26225
|
});
|
|
26047
26226
|
return newRow;
|
|
26048
26227
|
}
|
|
26049
|
-
return (jsxRuntime.jsxs(Dialog, { open: true, fullScreen: true, title: "Manage users", handleClose: handleClose, "data-testid": "manage-users", children: [jsxRuntime.jsxs(material.DialogContent, { children: [apolloInternetAccounts.length > 1 ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(material.DialogContentText, { children: "Select account" }), jsxRuntime.jsx(material.Select, { value: selectedInternetAccount.internetAccountId, onChange: handleChangeInternetAccount, disabled: !errorMessage, children: internetAccounts.map((option) => (jsxRuntime.jsx(material.MenuItem, { value: option.internetAccountId, children: option.name }, option.id))) })] })) : null, jsxRuntime.jsx("div", { style: { height: '100%', width: '100%' }, children: jsxRuntime.jsx(xDataGrid.DataGrid, { pagination: true, rows: users, columns: gridColumns, getRowId: (row) => row._id,
|
|
26228
|
+
return (jsxRuntime.jsxs(Dialog, { open: true, fullScreen: true, title: "Manage users", handleClose: handleClose, "data-testid": "manage-users", children: [jsxRuntime.jsxs(material.DialogContent, { children: [apolloInternetAccounts.length > 1 ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(material.DialogContentText, { children: "Select account" }), jsxRuntime.jsx(material.Select, { value: selectedInternetAccount.internetAccountId, onChange: handleChangeInternetAccount, disabled: !errorMessage, children: internetAccounts.map((option) => (jsxRuntime.jsx(material.MenuItem, { value: option.internetAccountId, children: option.name }, option.id))) })] })) : null, jsxRuntime.jsx("div", { style: { height: '100%', width: '100%' }, children: jsxRuntime.jsx(xDataGrid.DataGrid, { pagination: true, rows: users, columns: gridColumns, getRowId: (row) => row._id, showToolbar: true, getRowHeight: () => 'auto', isCellEditable: (params) => !isCurrentUser(params.id), processRowUpdate: processRowUpdate, onProcessRowUpdateError: (error) => {
|
|
26050
26229
|
setErrorMessage(String(error));
|
|
26051
26230
|
} }) })] }), jsxRuntime.jsx(material.DialogActions, { children: jsxRuntime.jsx(material.Button, { variant: "outlined", type: "submit", onClick: handleClose, children: "Close" }) }), errorMessage ? (jsxRuntime.jsx(material.DialogContent, { children: jsxRuntime.jsx(material.DialogContentText, { color: "error", children: errorMessage }) })) : null] }));
|
|
26052
26231
|
}
|
|
@@ -26356,12 +26535,13 @@
|
|
|
26356
26535
|
const [enableSubmit, setEnableSubmit] = React.useState(false);
|
|
26357
26536
|
const [selectedAssembly, setSelectedAssembly] = React.useState();
|
|
26358
26537
|
const [selectedRows, setSelectedRows] = React.useState([]);
|
|
26359
|
-
const [refNameAliasMap, setRefNameAliasMap] = React.useState(new Map());
|
|
26538
|
+
const [refNameAliasMap, setRefNameAliasMap] = React.useState(() => new Map());
|
|
26360
26539
|
const { apolloDataStore } = session;
|
|
26361
26540
|
const { collaborationServerDriver } = apolloDataStore;
|
|
26362
26541
|
const assemblies = collaborationServerDriver.getAssemblies();
|
|
26363
26542
|
React.useEffect(() => {
|
|
26364
26543
|
if (assemblies.length > 0) {
|
|
26544
|
+
// eslint-disable-next-line @eslint-react/set-state-in-effect
|
|
26365
26545
|
setSelectedAssembly(assemblies[0]);
|
|
26366
26546
|
collaborationServerDriver
|
|
26367
26547
|
.getRefNameAliases(assemblies[0].name)
|
|
@@ -26373,7 +26553,7 @@
|
|
|
26373
26553
|
setErrorMessage('Error fetching refName aliases for assembly');
|
|
26374
26554
|
});
|
|
26375
26555
|
}
|
|
26376
|
-
// eslint-disable-next-line react
|
|
26556
|
+
// eslint-disable-next-line @eslint-react/exhaustive-deps
|
|
26377
26557
|
}, []);
|
|
26378
26558
|
const initializeRefNameAliasMap = (refNameAliasesList) => {
|
|
26379
26559
|
const initialMap = new Map();
|
|
@@ -26758,6 +26938,10 @@
|
|
|
26758
26938
|
d: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2m0 4c1.93 0 3.5 1.57 3.5 3.5S13.93 13 12 13s-3.5-1.57-3.5-3.5S10.07 6 12 6m0 14c-2.03 0-4.43-.82-6.14-2.88C7.55 15.8 9.68 15 12 15s4.45.8 6.14 2.12C16.43 19.18 14.03 20 12 20"
|
|
26759
26939
|
}), 'AccountCircle');
|
|
26760
26940
|
|
|
26941
|
+
var BusinessIcon = /*#__PURE__*/utils.createSvgIcon(/*#__PURE__*/jsxRuntime.jsx("path", {
|
|
26942
|
+
d: "M12 7V3H2v18h20V7zM6 19H4v-2h2zm0-4H4v-2h2zm0-4H4V9h2zm0-4H4V5h2zm4 12H8v-2h2zm0-4H8v-2h2zm0-4H8V9h2zm0-4H8V5h2zm10 12h-8v-2h2v-2h-2v-2h2v-2h-2V9h8zm-2-8h-2v2h2zm0 4h-2v2h2z"
|
|
26943
|
+
}), 'Business');
|
|
26944
|
+
|
|
26761
26945
|
// Icon source: https://developers.google.com/identity/branding-guidelines
|
|
26762
26946
|
function Google(props) {
|
|
26763
26947
|
const { color } = props;
|
|
@@ -26782,17 +26966,23 @@
|
|
|
26782
26966
|
}));
|
|
26783
26967
|
function GoogleButton(props) {
|
|
26784
26968
|
const { classes } = useStyles$d();
|
|
26785
|
-
const {
|
|
26786
|
-
return (jsxRuntime.jsx(material.Button, { className: classes.loginButton, variant: "outlined", startIcon: jsxRuntime.jsx(Google, {
|
|
26969
|
+
const { message } = props;
|
|
26970
|
+
return (jsxRuntime.jsx(material.Button, { className: classes.loginButton, variant: "outlined", startIcon: jsxRuntime.jsx(Google, {}), ...props, children: message }));
|
|
26787
26971
|
}
|
|
26788
26972
|
function MicrosoftButton(props) {
|
|
26789
26973
|
const { classes } = useStyles$d();
|
|
26790
|
-
const {
|
|
26791
|
-
return (jsxRuntime.jsx(material.Button, { className: classes.loginButton, variant: "outlined", startIcon: jsxRuntime.jsx(Microsoft, {
|
|
26974
|
+
const { message } = props;
|
|
26975
|
+
return (jsxRuntime.jsx(material.Button, { className: classes.loginButton, variant: "outlined", startIcon: jsxRuntime.jsx(Microsoft, {}), ...props, children: message }));
|
|
26792
26976
|
}
|
|
26793
26977
|
function GuestButton(props) {
|
|
26794
26978
|
const { classes } = useStyles$d();
|
|
26795
|
-
|
|
26979
|
+
const { message } = props;
|
|
26980
|
+
return (jsxRuntime.jsx(material.Button, { className: classes.loginButton, variant: "outlined", startIcon: jsxRuntime.jsx(AccountCircleIcon, { fontSize: "small" }), ...props, children: message }));
|
|
26981
|
+
}
|
|
26982
|
+
function GenericButton(props) {
|
|
26983
|
+
const { classes } = useStyles$d();
|
|
26984
|
+
const { message } = props;
|
|
26985
|
+
return (jsxRuntime.jsx(material.Button, { className: classes.loginButton, variant: "outlined", startIcon: jsxRuntime.jsx(BusinessIcon, { fontSize: "small" }), ...props, children: message }));
|
|
26796
26986
|
}
|
|
26797
26987
|
|
|
26798
26988
|
const useStyles$c = makeStyles()((theme) => ({
|
|
@@ -26804,7 +26994,7 @@
|
|
|
26804
26994
|
const AuthTypeSelector = ({ baseURL, handleClose, name, }) => {
|
|
26805
26995
|
const { classes } = useStyles$c();
|
|
26806
26996
|
const [errorMessage, setErrorMessage] = React.useState('');
|
|
26807
|
-
const [loginTypes, setLoginTypes] = React.useState(
|
|
26997
|
+
const [loginTypes, setLoginTypes] = React.useState(null);
|
|
26808
26998
|
React.useEffect(() => {
|
|
26809
26999
|
const controller = new AbortController();
|
|
26810
27000
|
const { signal } = controller;
|
|
@@ -26818,6 +27008,9 @@
|
|
|
26818
27008
|
}
|
|
26819
27009
|
const data = (await response.json());
|
|
26820
27010
|
setLoginTypes(data);
|
|
27011
|
+
if (data.length === 0) {
|
|
27012
|
+
setErrorMessage('No login types configured');
|
|
27013
|
+
}
|
|
26821
27014
|
}
|
|
26822
27015
|
getAuthTypes().catch((error) => {
|
|
26823
27016
|
if (!isAbortException(error)) {
|
|
@@ -26829,26 +27022,35 @@
|
|
|
26829
27022
|
};
|
|
26830
27023
|
}, [baseURL]);
|
|
26831
27024
|
function handleClick(authType) {
|
|
26832
|
-
|
|
26833
|
-
|
|
26834
|
-
|
|
26835
|
-
|
|
26836
|
-
|
|
26837
|
-
|
|
26838
|
-
|
|
26839
|
-
|
|
26840
|
-
|
|
26841
|
-
}
|
|
26842
|
-
|
|
26843
|
-
|
|
26844
|
-
|
|
26845
|
-
|
|
26846
|
-
|
|
26847
|
-
|
|
26848
|
-
|
|
26849
|
-
|
|
26850
|
-
|
|
26851
|
-
|
|
27025
|
+
handleClose(authType);
|
|
27026
|
+
}
|
|
27027
|
+
if (loginTypes === null) {
|
|
27028
|
+
return 'Loading…';
|
|
27029
|
+
}
|
|
27030
|
+
const firstLoginType = loginTypes.at(0);
|
|
27031
|
+
if (firstLoginType && loginTypes.length === 1 && !firstLoginType.needsPopup) {
|
|
27032
|
+
handleClick(firstLoginType);
|
|
27033
|
+
}
|
|
27034
|
+
return (jsxRuntime.jsxs(Dialog, { open: true, title: `Log in to ${name}`, handleClose: handleClose, maxWidth: false, "data-testid": "login-apollo", children: [jsxRuntime.jsx(material.DialogContent, { style: { display: 'flex', flexDirection: 'column', paddingTop: 8 }, children: loginTypes.map((loginType) => {
|
|
27035
|
+
if (loginType.name === 'google') {
|
|
27036
|
+
return (jsxRuntime.jsx(GoogleButton, { message: loginType.message, onClick: () => {
|
|
27037
|
+
handleClick(loginType);
|
|
27038
|
+
} }, loginType.name));
|
|
27039
|
+
}
|
|
27040
|
+
if (loginType.name === 'microsoft') {
|
|
27041
|
+
return (jsxRuntime.jsx(MicrosoftButton, { message: loginType.message, onClick: () => {
|
|
27042
|
+
handleClick(loginType);
|
|
27043
|
+
} }, loginType.name));
|
|
27044
|
+
}
|
|
27045
|
+
if (loginType.name === 'guest') {
|
|
27046
|
+
return (jsxRuntime.jsxs(React.Fragment, { children: [jsxRuntime.jsx(material.Divider, { className: classes.divider }), jsxRuntime.jsx(GuestButton, { message: loginType.message, onClick: () => {
|
|
27047
|
+
handleClick(loginType);
|
|
27048
|
+
} })] }, loginType.name));
|
|
27049
|
+
}
|
|
27050
|
+
return (jsxRuntime.jsx(GenericButton, { message: loginType.message, onClick: () => {
|
|
27051
|
+
handleClick(loginType);
|
|
27052
|
+
} }, loginType.name));
|
|
27053
|
+
}) }), jsxRuntime.jsx(material.DialogActions, { children: jsxRuntime.jsx(material.Button, { variant: "outlined", type: "submit", onClick: () => {
|
|
26852
27054
|
handleClose();
|
|
26853
27055
|
}, children: "Cancel" }) }), errorMessage ? (jsxRuntime.jsx(material.DialogContent, { children: jsxRuntime.jsx(material.DialogContentText, { color: "error", children: errorMessage }) })) : null] }));
|
|
26854
27056
|
};
|
|
@@ -27044,13 +27246,13 @@
|
|
|
27044
27246
|
},
|
|
27045
27247
|
]);
|
|
27046
27248
|
});
|
|
27047
|
-
if (authType
|
|
27249
|
+
if (authType.needsPopup) {
|
|
27048
27250
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
27049
|
-
self.openAuthWindow(authType, resolve, reject);
|
|
27251
|
+
self.openAuthWindow(authType.name, resolve, reject);
|
|
27050
27252
|
return;
|
|
27051
27253
|
}
|
|
27052
27254
|
const url = new URL('auth/login', baseURL);
|
|
27053
|
-
const searchParams = new URLSearchParams({ type: authType });
|
|
27255
|
+
const searchParams = new URLSearchParams({ type: authType.name });
|
|
27054
27256
|
url.search = searchParams.toString();
|
|
27055
27257
|
const uri = url.toString();
|
|
27056
27258
|
const response = await fetch(uri, { signal: self.controller.signal });
|
|
@@ -27171,7 +27373,7 @@
|
|
|
27171
27373
|
socket.on('COMMON', (message) => {
|
|
27172
27374
|
if ('checkResult' in message) {
|
|
27173
27375
|
if (message.deleted) {
|
|
27174
|
-
deleteCheckResult(message.checkResult._id
|
|
27376
|
+
deleteCheckResult(message.checkResult._id);
|
|
27175
27377
|
}
|
|
27176
27378
|
else {
|
|
27177
27379
|
addCheckResult(message.checkResult);
|
|
@@ -27998,7 +28200,9 @@
|
|
|
27998
28200
|
return newValues;
|
|
27999
28201
|
});
|
|
28000
28202
|
}
|
|
28001
|
-
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [newValues.map((value, idx) => (
|
|
28203
|
+
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [newValues.map((value, idx) => (
|
|
28204
|
+
// eslint-disable-next-line @eslint-react/no-array-index-key
|
|
28205
|
+
jsxRuntime.jsxs("div", { style: { display: 'flex' }, children: [jsxRuntime.jsx(StringTextField, { value: value, onChangeCommitted: (editedValue) => {
|
|
28002
28206
|
updateValue(idx, editedValue);
|
|
28003
28207
|
}, variant: "outlined", fullWidth: true }), jsxRuntime.jsx(material.IconButton, { "aria-label": "delete", size: "medium", edge: "end", onClick: () => {
|
|
28004
28208
|
deleteValue(idx);
|
|
@@ -28010,7 +28214,9 @@
|
|
|
28010
28214
|
});
|
|
28011
28215
|
|
|
28012
28216
|
function DefaultAttributeViewer({ values }) {
|
|
28013
|
-
return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: values?.map((value, idx) => (jsxRuntime.jsx(material.Typography
|
|
28217
|
+
return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: values?.map((value, idx) => (jsxRuntime.jsx(material.Typography
|
|
28218
|
+
// eslint-disable-next-line @eslint-react/no-array-index-key
|
|
28219
|
+
, { variant: "body2", color: "textSecondary", children: value }, `${idx}.${value}`))) }));
|
|
28014
28220
|
}
|
|
28015
28221
|
|
|
28016
28222
|
const useStyles$a = makeStyles()((theme) => ({
|
|
@@ -28316,6 +28522,7 @@
|
|
|
28316
28522
|
const { classes } = useStyles$8();
|
|
28317
28523
|
const [panelState, setPanelState] = React.useState(['attributes']);
|
|
28318
28524
|
React.useEffect(() => {
|
|
28525
|
+
// eslint-disable-next-line @eslint-react/set-state-in-effect
|
|
28319
28526
|
setPanelState(['attributes']);
|
|
28320
28527
|
}, [feature]);
|
|
28321
28528
|
if (!(feature && currentAssembly)) {
|
|
@@ -28402,6 +28609,7 @@
|
|
|
28402
28609
|
*/
|
|
28403
28610
|
get minWithChildren() {
|
|
28404
28611
|
var min = self.min;
|
|
28612
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
|
28405
28613
|
var children = self.children;
|
|
28406
28614
|
if (!children) {
|
|
28407
28615
|
return min;
|
|
@@ -28428,6 +28636,7 @@
|
|
|
28428
28636
|
*/
|
|
28429
28637
|
get maxWithChildren() {
|
|
28430
28638
|
var max = self.max;
|
|
28639
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
|
28431
28640
|
var children = self.children;
|
|
28432
28641
|
if (!children) {
|
|
28433
28642
|
return max;
|
|
@@ -28536,6 +28745,7 @@
|
|
|
28536
28745
|
if (!featureTypeOntology.isTypeOf(self.type, 'transcript') && !featureTypeOntology.isTypeOf(self.type, 'pseudogenic_transcript')) {
|
|
28537
28746
|
throw new Error('Only features of type "transcript" or equivalent can calculate CDS locations');
|
|
28538
28747
|
}
|
|
28748
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
|
28539
28749
|
var children = self.children;
|
|
28540
28750
|
if (!children) {
|
|
28541
28751
|
throw new Error('no CDS or exons in transcript');
|
|
@@ -29440,7 +29650,7 @@
|
|
|
29440
29650
|
else {
|
|
29441
29651
|
setSequenceOptions(defaultSequenceOptions);
|
|
29442
29652
|
}
|
|
29443
|
-
// eslint-disable-next-line react
|
|
29653
|
+
// eslint-disable-next-line @eslint-react/exhaustive-deps
|
|
29444
29654
|
}, [feature]);
|
|
29445
29655
|
if (!(currentAssembly && refData)) {
|
|
29446
29656
|
return null;
|
|
@@ -29503,6 +29713,10 @@
|
|
|
29503
29713
|
.join(';'), "(strand=", feature.strand === 1 ? '+' : '-', ";length=", getSequenceLength(sequenceSegments), ")", jsxRuntime.jsx("br", {}), wrapSequence(sequenceSegments, SEQUENCE_WRAP_LENGTH)] })] }));
|
|
29504
29714
|
});
|
|
29505
29715
|
|
|
29716
|
+
var RemoveIcon = /*#__PURE__*/utils.createSvgIcon(/*#__PURE__*/jsxRuntime.jsx("path", {
|
|
29717
|
+
d: "M19 13H5v-2h14z"
|
|
29718
|
+
}), 'Remove');
|
|
29719
|
+
|
|
29506
29720
|
var ContentCopyIcon = /*#__PURE__*/utils.createSvgIcon(/*#__PURE__*/jsxRuntime.jsx("path", {
|
|
29507
29721
|
d: "M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2m0 16H8V7h11z"
|
|
29508
29722
|
}), 'ContentCopy');
|
|
@@ -29511,23 +29725,6 @@
|
|
|
29511
29725
|
d: "M9.64 7.64c.23-.5.36-1.05.36-1.64 0-2.21-1.79-4-4-4S2 3.79 2 6s1.79 4 4 4c.59 0 1.14-.13 1.64-.36L10 12l-2.36 2.36C7.14 14.13 6.59 14 6 14c-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4c0-.59-.13-1.14-.36-1.64L12 14l7 7h3v-1zM6 8c-1.1 0-2-.89-2-2s.9-2 2-2 2 .89 2 2-.9 2-2 2m0 12c-1.1 0-2-.89-2-2s.9-2 2-2 2 .89 2 2-.9 2-2 2m6-7.5c-.28 0-.5-.22-.5-.5s.22-.5.5-.5.5.22.5.5-.22.5-.5.5M19 3l-6 6 2 2 7-7V3z"
|
|
29512
29726
|
}), 'ContentCut');
|
|
29513
29727
|
|
|
29514
|
-
var RemoveIcon = /*#__PURE__*/utils.createSvgIcon(/*#__PURE__*/jsxRuntime.jsx("path", {
|
|
29515
|
-
d: "M19 13H5v-2h14z"
|
|
29516
|
-
}), 'Remove');
|
|
29517
|
-
|
|
29518
|
-
const StyledTextField = newStyled(NumberTextField)(() => ({
|
|
29519
|
-
'&.MuiFormControl-root': {
|
|
29520
|
-
marginTop: 0,
|
|
29521
|
-
marginBottom: 0,
|
|
29522
|
-
width: '100%',
|
|
29523
|
-
},
|
|
29524
|
-
'& .MuiInputBase-input': {
|
|
29525
|
-
fontSize: 12,
|
|
29526
|
-
height: 20,
|
|
29527
|
-
padding: 1,
|
|
29528
|
-
paddingLeft: 10,
|
|
29529
|
-
},
|
|
29530
|
-
}));
|
|
29531
29728
|
const SequenceContainer = newStyled('div')({
|
|
29532
29729
|
display: 'flex',
|
|
29533
29730
|
justifyContent: 'center',
|
|
@@ -29549,6 +29746,187 @@
|
|
|
29549
29746
|
maxHeight: 30,
|
|
29550
29747
|
},
|
|
29551
29748
|
}));
|
|
29749
|
+
function Translation({ changeInProgress, cdsLocations, refData, strand,
|
|
29750
|
+
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
29751
|
+
updateCDSLocation, cdsMin, cdsMax, feature, session, }) {
|
|
29752
|
+
const seqRef = React.useRef(null);
|
|
29753
|
+
const { notify } = session;
|
|
29754
|
+
const cdsSequences = [];
|
|
29755
|
+
const [firstLocation] = cdsLocations;
|
|
29756
|
+
for (const loc of firstLocation) {
|
|
29757
|
+
const seq = refData.getSequence(loc.min, loc.max);
|
|
29758
|
+
cdsSequences.push(strand === -1 ? util$1.revcom(seq) : seq);
|
|
29759
|
+
}
|
|
29760
|
+
const cdsSequence = cdsSequences.join('');
|
|
29761
|
+
const proteinSequence = [];
|
|
29762
|
+
for (let codonGenomicPos = 0; codonGenomicPos < cdsSequence.length; codonGenomicPos += 3) {
|
|
29763
|
+
const codonSeq = cdsSequence
|
|
29764
|
+
.slice(codonGenomicPos, codonGenomicPos + 3)
|
|
29765
|
+
.toUpperCase();
|
|
29766
|
+
const protein = util$1.defaultCodonTable[codonSeq] || '&';
|
|
29767
|
+
proteinSequence.push(protein);
|
|
29768
|
+
}
|
|
29769
|
+
const onCopyClick = () => {
|
|
29770
|
+
const seqDiv = seqRef.current;
|
|
29771
|
+
if (!seqDiv) {
|
|
29772
|
+
return;
|
|
29773
|
+
}
|
|
29774
|
+
void copyToClipboard(seqDiv);
|
|
29775
|
+
};
|
|
29776
|
+
// Codon position is the index of the start codon in the CDS genomic sequence
|
|
29777
|
+
// Calculate the genomic location of the start codon based on the codon position in the CDS
|
|
29778
|
+
const getCodonGenomicLocation = (codonGenomicPosition) => {
|
|
29779
|
+
const [firstLocation] = cdsLocations;
|
|
29780
|
+
let cdsLen = 0;
|
|
29781
|
+
const sortedCDSLocations = firstLocation.toSorted(({ min: a }, { min: b }) => a - b);
|
|
29782
|
+
// Suppose CDS locations are [{min: 0, max: 10}, {min: 20, max: 30}, {min: 40, max: 50}]
|
|
29783
|
+
// and codonGenomicPosition is 25
|
|
29784
|
+
// ((10 - 0) + (30 - 20) + (50 - 40)) > 25
|
|
29785
|
+
// So, start codon is in (40, 50)
|
|
29786
|
+
// 40 + (25-20) = 45 is the genomic location of the start codon
|
|
29787
|
+
if (strand === 1) {
|
|
29788
|
+
for (const loc of sortedCDSLocations) {
|
|
29789
|
+
const locLength = loc.max - loc.min;
|
|
29790
|
+
if (cdsLen + locLength > codonGenomicPosition) {
|
|
29791
|
+
return loc.min + (codonGenomicPosition - cdsLen);
|
|
29792
|
+
}
|
|
29793
|
+
cdsLen += locLength;
|
|
29794
|
+
}
|
|
29795
|
+
}
|
|
29796
|
+
else if (strand === -1) {
|
|
29797
|
+
for (let i = sortedCDSLocations.length - 1; i >= 0; i--) {
|
|
29798
|
+
const loc = sortedCDSLocations[i];
|
|
29799
|
+
const locLength = loc.max - loc.min;
|
|
29800
|
+
if (cdsLen + locLength > codonGenomicPosition) {
|
|
29801
|
+
return loc.max - (codonGenomicPosition - cdsLen);
|
|
29802
|
+
}
|
|
29803
|
+
cdsLen += locLength;
|
|
29804
|
+
}
|
|
29805
|
+
}
|
|
29806
|
+
if (strand === 1) {
|
|
29807
|
+
return cdsMin;
|
|
29808
|
+
}
|
|
29809
|
+
return cdsMax;
|
|
29810
|
+
};
|
|
29811
|
+
const trimTranslationSequence = () => {
|
|
29812
|
+
if ((proteinSequence.at(0) === 'M' && proteinSequence.at(-1) === '*') ||
|
|
29813
|
+
proteinSequence.length === 0) {
|
|
29814
|
+
return;
|
|
29815
|
+
}
|
|
29816
|
+
// Trim any sequence before first start codon and after stop codon
|
|
29817
|
+
const startCodonIndex = proteinSequence.indexOf('M');
|
|
29818
|
+
const stopCodonIndex = proteinSequence.lastIndexOf('*');
|
|
29819
|
+
const startCodonPos = startCodonIndex * 3;
|
|
29820
|
+
const stopCodonPos = stopCodonIndex * 3;
|
|
29821
|
+
const startCodonGenomicLoc = getCodonGenomicLocation(startCodonPos);
|
|
29822
|
+
let stopCodonGenomicLoc = getCodonGenomicLocation(stopCodonPos);
|
|
29823
|
+
if (strand === 1) {
|
|
29824
|
+
if (startCodonGenomicLoc > stopCodonGenomicLoc) {
|
|
29825
|
+
notify('Start codon genomic location should be less than stop codon genomic location', 'error');
|
|
29826
|
+
return;
|
|
29827
|
+
}
|
|
29828
|
+
let promise;
|
|
29829
|
+
stopCodonGenomicLoc += 3; // move to end of stop codon
|
|
29830
|
+
if (startCodonGenomicLoc !== cdsMin) {
|
|
29831
|
+
promise = new Promise((resolve) => {
|
|
29832
|
+
updateCDSLocation(cdsMin, startCodonGenomicLoc, feature, true, () => {
|
|
29833
|
+
resolve(true);
|
|
29834
|
+
});
|
|
29835
|
+
});
|
|
29836
|
+
}
|
|
29837
|
+
if (stopCodonGenomicLoc !== cdsMax) {
|
|
29838
|
+
if (promise) {
|
|
29839
|
+
void promise.then(() => {
|
|
29840
|
+
updateCDSLocation(cdsMax, stopCodonGenomicLoc, feature, false);
|
|
29841
|
+
});
|
|
29842
|
+
}
|
|
29843
|
+
else {
|
|
29844
|
+
updateCDSLocation(cdsMax, stopCodonGenomicLoc, feature, false);
|
|
29845
|
+
}
|
|
29846
|
+
}
|
|
29847
|
+
}
|
|
29848
|
+
if (strand === -1) {
|
|
29849
|
+
// reverse strand
|
|
29850
|
+
if (startCodonGenomicLoc < stopCodonGenomicLoc) {
|
|
29851
|
+
notify('Start codon genomic location should be less than stop codon genomic location', 'error');
|
|
29852
|
+
return;
|
|
29853
|
+
}
|
|
29854
|
+
let promise;
|
|
29855
|
+
stopCodonGenomicLoc -= 3; // move to end of stop codon
|
|
29856
|
+
if (startCodonGenomicLoc !== cdsMax) {
|
|
29857
|
+
promise = new Promise((resolve) => {
|
|
29858
|
+
updateCDSLocation(cdsMax, startCodonGenomicLoc, feature, false, () => {
|
|
29859
|
+
resolve(true);
|
|
29860
|
+
});
|
|
29861
|
+
});
|
|
29862
|
+
}
|
|
29863
|
+
if (stopCodonGenomicLoc !== cdsMin) {
|
|
29864
|
+
if (promise) {
|
|
29865
|
+
void promise.then(() => {
|
|
29866
|
+
updateCDSLocation(cdsMin, stopCodonGenomicLoc, feature, true);
|
|
29867
|
+
});
|
|
29868
|
+
}
|
|
29869
|
+
else {
|
|
29870
|
+
updateCDSLocation(cdsMin, stopCodonGenomicLoc, feature, true);
|
|
29871
|
+
}
|
|
29872
|
+
}
|
|
29873
|
+
}
|
|
29874
|
+
notify('Translation sequence trimmed to start and stop codons', 'success');
|
|
29875
|
+
};
|
|
29876
|
+
return (jsxRuntime.jsx("div", { children: jsxRuntime.jsxs(material.Accordion, { children: [jsxRuntime.jsx(StyledAccordionSummary$1, { expandIcon: jsxRuntime.jsx(ExpandMoreIcon, { style: { color: 'white' } }), "aria-controls": "panel1-content", id: "panel1-header", children: jsxRuntime.jsx(material.Typography, { component: "span", fontWeight: 'bold', children: "Translation" }) }), jsxRuntime.jsxs(material.AccordionDetails, { children: [jsxRuntime.jsx(SequenceContainer, { children: jsxRuntime.jsx(material.Typography, { component: 'span', ref: seqRef, style: { maxHeight: 120, overflowY: 'scroll' }, children: proteinSequence.map((protein, idx) => {
|
|
29877
|
+
const codonGenomicPos = idx * 3;
|
|
29878
|
+
if (protein === 'M') {
|
|
29879
|
+
return (jsxRuntime.jsx(material.Typography, { component: 'span', style: {
|
|
29880
|
+
backgroundColor: changeInProgress
|
|
29881
|
+
? 'lightgray'
|
|
29882
|
+
: 'yellow',
|
|
29883
|
+
cursor: 'pointer',
|
|
29884
|
+
border: '1px solid black',
|
|
29885
|
+
}, onClick: () => {
|
|
29886
|
+
if (changeInProgress) {
|
|
29887
|
+
return;
|
|
29888
|
+
}
|
|
29889
|
+
// NOTE: codonGenomicPos is important here for calculating the genomic location
|
|
29890
|
+
// of the start codon. We are using the codonGenomicPos as the key in the typography
|
|
29891
|
+
// elements to maintain the genomic postion of the codon start
|
|
29892
|
+
const startCodonGenomicLocation = getCodonGenomicLocation(codonGenomicPos);
|
|
29893
|
+
if (startCodonGenomicLocation !== cdsMin &&
|
|
29894
|
+
strand === 1) {
|
|
29895
|
+
updateCDSLocation(cdsMin, startCodonGenomicLocation, feature, true);
|
|
29896
|
+
}
|
|
29897
|
+
if (startCodonGenomicLocation !== cdsMax &&
|
|
29898
|
+
strand === -1) {
|
|
29899
|
+
updateCDSLocation(cdsMax, startCodonGenomicLocation, feature, false);
|
|
29900
|
+
}
|
|
29901
|
+
}, children: protein }, codonGenomicPos));
|
|
29902
|
+
}
|
|
29903
|
+
if (protein === '*') {
|
|
29904
|
+
return (jsxRuntime.jsx(material.Typography, { style: { backgroundColor: 'red', color: 'white' }, component: 'span', children: protein }, codonGenomicPos));
|
|
29905
|
+
}
|
|
29906
|
+
// Pass the codonGenomicPos as the key to maintain the genomic position of the codon
|
|
29907
|
+
return (jsxRuntime.jsx(material.Typography, { component: 'span', children: protein }, codonGenomicPos));
|
|
29908
|
+
}) }) }), jsxRuntime.jsxs("div", { style: {
|
|
29909
|
+
marginTop: 10,
|
|
29910
|
+
display: 'flex',
|
|
29911
|
+
flexDirection: 'row',
|
|
29912
|
+
alignItems: 'center',
|
|
29913
|
+
gap: 10,
|
|
29914
|
+
}, children: [jsxRuntime.jsx(material.Tooltip, { title: "Copy", children: jsxRuntime.jsx("button", { onClick: onCopyClick, style: { border: 'none', background: 'none', padding: 0 }, disabled: changeInProgress, children: jsxRuntime.jsx(ContentCopyIcon, { style: { fontSize: 15 } }) }) }), jsxRuntime.jsx(material.Tooltip, { title: "Trim", children: jsxRuntime.jsx("button", { onClick: trimTranslationSequence, style: { border: 'none', background: 'none', padding: 0 }, disabled: changeInProgress, children: jsxRuntime.jsx(ContentCutIcon, { style: { fontSize: 15 } }) }) })] })] })] }) }));
|
|
29915
|
+
}
|
|
29916
|
+
|
|
29917
|
+
const StyledTextField = newStyled(NumberTextField)(() => ({
|
|
29918
|
+
'&.MuiFormControl-root': {
|
|
29919
|
+
marginTop: 0,
|
|
29920
|
+
marginBottom: 0,
|
|
29921
|
+
width: '100%',
|
|
29922
|
+
},
|
|
29923
|
+
'& .MuiInputBase-input': {
|
|
29924
|
+
fontSize: 12,
|
|
29925
|
+
height: 20,
|
|
29926
|
+
padding: 1,
|
|
29927
|
+
paddingLeft: 10,
|
|
29928
|
+
},
|
|
29929
|
+
}));
|
|
29552
29930
|
const Strand = (props) => {
|
|
29553
29931
|
const { strand } = props;
|
|
29554
29932
|
return (jsxRuntime.jsx("div", { children: strand === 1 ? (jsxRuntime.jsx(AddIcon, {})) : strand === -1 ? (jsxRuntime.jsx(RemoveIcon, {})) : (jsxRuntime.jsx(material.Typography, { component: 'span', children: "N/A" })) }));
|
|
@@ -29567,7 +29945,6 @@
|
|
|
29567
29945
|
const currentAssembly = session.apolloDataStore.assemblies.get(assembly);
|
|
29568
29946
|
const refData = currentAssembly?.getByRefName(refName);
|
|
29569
29947
|
const { changeManager } = session.apolloDataStore;
|
|
29570
|
-
const seqRef = React.useRef(null);
|
|
29571
29948
|
const { changeInProgress } = session;
|
|
29572
29949
|
if (!refData) {
|
|
29573
29950
|
return null;
|
|
@@ -29994,184 +30371,6 @@
|
|
|
29994
30371
|
},
|
|
29995
30372
|
];
|
|
29996
30373
|
};
|
|
29997
|
-
const getTranslationSequence = () => {
|
|
29998
|
-
let wholeSequence = '';
|
|
29999
|
-
const [firstLocation] = cdsLocations;
|
|
30000
|
-
const sortedCDSLocations = firstLocation.toSorted(({ min: a }, { min: b }) => a - b);
|
|
30001
|
-
for (const loc of sortedCDSLocations) {
|
|
30002
|
-
wholeSequence += refData.getSequence(loc.min, loc.max);
|
|
30003
|
-
}
|
|
30004
|
-
if (strand === -1) {
|
|
30005
|
-
// Original: ACGCAT
|
|
30006
|
-
// Complement: TGCGTA
|
|
30007
|
-
// Reverse complement: ATGCGT
|
|
30008
|
-
wholeSequence = util$1.revcom(wholeSequence);
|
|
30009
|
-
}
|
|
30010
|
-
const elements = [];
|
|
30011
|
-
for (let codonGenomicPos = 0; codonGenomicPos < wholeSequence.length; codonGenomicPos += 3) {
|
|
30012
|
-
const codonSeq = wholeSequence
|
|
30013
|
-
.slice(codonGenomicPos, codonGenomicPos + 3)
|
|
30014
|
-
.toUpperCase();
|
|
30015
|
-
const protein = util$1.defaultCodonTable[codonSeq] || '&';
|
|
30016
|
-
// highlight start codon and stop codons
|
|
30017
|
-
if (codonSeq === 'ATG') {
|
|
30018
|
-
elements.push(jsxRuntime.jsx(material.Typography, { component: 'span', style: {
|
|
30019
|
-
backgroundColor: changeInProgress ? 'lightgray' : 'yellow',
|
|
30020
|
-
cursor: 'pointer',
|
|
30021
|
-
border: '1px solid black',
|
|
30022
|
-
}, onClick: () => {
|
|
30023
|
-
if (changeInProgress) {
|
|
30024
|
-
return;
|
|
30025
|
-
}
|
|
30026
|
-
// NOTE: codonGenomicPos is important here for calculating the genomic location
|
|
30027
|
-
// of the start codon. We are using the codonGenomicPos as the key in the typography
|
|
30028
|
-
// elements to maintain the genomic postion of the codon start
|
|
30029
|
-
const startCodonGenomicLocation = getCodonGenomicLocation(codonGenomicPos);
|
|
30030
|
-
if (startCodonGenomicLocation !== cdsMin && strand === 1) {
|
|
30031
|
-
updateCDSLocation(cdsMin, startCodonGenomicLocation, feature, true);
|
|
30032
|
-
}
|
|
30033
|
-
if (startCodonGenomicLocation !== cdsMax && strand === -1) {
|
|
30034
|
-
updateCDSLocation(cdsMax, startCodonGenomicLocation, feature, false);
|
|
30035
|
-
}
|
|
30036
|
-
}, children: protein }, codonGenomicPos));
|
|
30037
|
-
}
|
|
30038
|
-
else if (['TAA', 'TAG', 'TGA'].includes(codonSeq)) {
|
|
30039
|
-
elements.push(jsxRuntime.jsx(material.Typography, { style: { backgroundColor: 'red', color: 'white' }, component: 'span', children: protein }, codonGenomicPos));
|
|
30040
|
-
}
|
|
30041
|
-
else {
|
|
30042
|
-
elements.push(
|
|
30043
|
-
// Pass the codonGenomicPos as the key to maintain the genomic position of the codon
|
|
30044
|
-
jsxRuntime.jsx(material.Typography, { component: 'span', children: protein }, codonGenomicPos));
|
|
30045
|
-
}
|
|
30046
|
-
}
|
|
30047
|
-
return elements;
|
|
30048
|
-
};
|
|
30049
|
-
// Codon position is the index of the start codon in the CDS genomic sequence
|
|
30050
|
-
// Calculate the genomic location of the start codon based on the codon position in the CDS
|
|
30051
|
-
const getCodonGenomicLocation = (codonGenomicPosition) => {
|
|
30052
|
-
const [firstLocation] = cdsLocations;
|
|
30053
|
-
let cdsLen = 0;
|
|
30054
|
-
const sortedCDSLocations = firstLocation.toSorted(({ min: a }, { min: b }) => a - b);
|
|
30055
|
-
// Suppose CDS locations are [{min: 0, max: 10}, {min: 20, max: 30}, {min: 40, max: 50}]
|
|
30056
|
-
// and codonGenomicPosition is 25
|
|
30057
|
-
// ((10 - 0) + (30 - 20) + (50 - 40)) > 25
|
|
30058
|
-
// So, start codon is in (40, 50)
|
|
30059
|
-
// 40 + (25-20) = 45 is the genomic location of the start codon
|
|
30060
|
-
if (strand === 1) {
|
|
30061
|
-
for (const loc of sortedCDSLocations) {
|
|
30062
|
-
const locLength = loc.max - loc.min;
|
|
30063
|
-
if (cdsLen + locLength > codonGenomicPosition) {
|
|
30064
|
-
return loc.min + (codonGenomicPosition - cdsLen);
|
|
30065
|
-
}
|
|
30066
|
-
cdsLen += locLength;
|
|
30067
|
-
}
|
|
30068
|
-
}
|
|
30069
|
-
else if (strand === -1) {
|
|
30070
|
-
for (let i = sortedCDSLocations.length - 1; i >= 0; i--) {
|
|
30071
|
-
const loc = sortedCDSLocations[i];
|
|
30072
|
-
const locLength = loc.max - loc.min;
|
|
30073
|
-
if (cdsLen + locLength > codonGenomicPosition) {
|
|
30074
|
-
return loc.max - (codonGenomicPosition - cdsLen);
|
|
30075
|
-
}
|
|
30076
|
-
cdsLen += locLength;
|
|
30077
|
-
}
|
|
30078
|
-
}
|
|
30079
|
-
if (strand === 1) {
|
|
30080
|
-
return cdsMin;
|
|
30081
|
-
}
|
|
30082
|
-
return cdsMax;
|
|
30083
|
-
};
|
|
30084
|
-
const trimTranslationSequence = () => {
|
|
30085
|
-
const sequenceElements = getTranslationSequence();
|
|
30086
|
-
const translationSequence = sequenceElements
|
|
30087
|
-
.map((el) => el.props.children)
|
|
30088
|
-
.join('');
|
|
30089
|
-
if (translationSequence.startsWith('M') &&
|
|
30090
|
-
translationSequence.endsWith('*')) {
|
|
30091
|
-
return;
|
|
30092
|
-
}
|
|
30093
|
-
// NOTE: We are maintaining the genomic location of the codon start as the "key"
|
|
30094
|
-
// in typography elements. See getTranslationSequence function
|
|
30095
|
-
const translSeqCodonStartGenomicPosArr = [];
|
|
30096
|
-
for (const el of sequenceElements) {
|
|
30097
|
-
translSeqCodonStartGenomicPosArr.push({
|
|
30098
|
-
codonGenomicPos: el.key,
|
|
30099
|
-
sequenceLetter: el.props.children,
|
|
30100
|
-
});
|
|
30101
|
-
}
|
|
30102
|
-
if (translSeqCodonStartGenomicPosArr.length === 0) {
|
|
30103
|
-
return;
|
|
30104
|
-
}
|
|
30105
|
-
// Trim any sequence before first start codon and after stop codon
|
|
30106
|
-
const startCodonIndex = translationSequence.indexOf('M');
|
|
30107
|
-
const stopCodonIndex = translationSequence.indexOf('*');
|
|
30108
|
-
const startCodonPos = translSeqCodonStartGenomicPosArr[startCodonIndex].codonGenomicPos;
|
|
30109
|
-
const stopCodonPos = translSeqCodonStartGenomicPosArr[stopCodonIndex].codonGenomicPos;
|
|
30110
|
-
if (!startCodonPos || !stopCodonPos) {
|
|
30111
|
-
return;
|
|
30112
|
-
}
|
|
30113
|
-
const startCodonGenomicLoc = getCodonGenomicLocation(startCodonPos);
|
|
30114
|
-
let stopCodonGenomicLoc = getCodonGenomicLocation(stopCodonPos);
|
|
30115
|
-
if (strand === 1) {
|
|
30116
|
-
if (startCodonGenomicLoc > stopCodonGenomicLoc) {
|
|
30117
|
-
notify('Start codon genomic location should be less than stop codon genomic location', 'error');
|
|
30118
|
-
return;
|
|
30119
|
-
}
|
|
30120
|
-
let promise;
|
|
30121
|
-
stopCodonGenomicLoc += 3; // move to end of stop codon
|
|
30122
|
-
if (startCodonGenomicLoc !== cdsMin) {
|
|
30123
|
-
promise = new Promise((resolve) => {
|
|
30124
|
-
updateCDSLocation(cdsMin, startCodonGenomicLoc, feature, true, () => {
|
|
30125
|
-
resolve(true);
|
|
30126
|
-
});
|
|
30127
|
-
});
|
|
30128
|
-
}
|
|
30129
|
-
if (stopCodonGenomicLoc !== cdsMax) {
|
|
30130
|
-
if (promise) {
|
|
30131
|
-
void promise.then(() => {
|
|
30132
|
-
updateCDSLocation(cdsMax, stopCodonGenomicLoc, feature, false);
|
|
30133
|
-
});
|
|
30134
|
-
}
|
|
30135
|
-
else {
|
|
30136
|
-
updateCDSLocation(cdsMax, stopCodonGenomicLoc, feature, false);
|
|
30137
|
-
}
|
|
30138
|
-
}
|
|
30139
|
-
}
|
|
30140
|
-
if (strand === -1) {
|
|
30141
|
-
// reverse strand
|
|
30142
|
-
if (startCodonGenomicLoc < stopCodonGenomicLoc) {
|
|
30143
|
-
notify('Start codon genomic location should be less than stop codon genomic location', 'error');
|
|
30144
|
-
return;
|
|
30145
|
-
}
|
|
30146
|
-
let promise;
|
|
30147
|
-
stopCodonGenomicLoc -= 3; // move to end of stop codon
|
|
30148
|
-
if (startCodonGenomicLoc !== cdsMax) {
|
|
30149
|
-
promise = new Promise((resolve) => {
|
|
30150
|
-
updateCDSLocation(cdsMax, startCodonGenomicLoc, feature, false, () => {
|
|
30151
|
-
resolve(true);
|
|
30152
|
-
});
|
|
30153
|
-
});
|
|
30154
|
-
}
|
|
30155
|
-
if (stopCodonGenomicLoc !== cdsMin) {
|
|
30156
|
-
if (promise) {
|
|
30157
|
-
void promise.then(() => {
|
|
30158
|
-
updateCDSLocation(cdsMin, stopCodonGenomicLoc, feature, true);
|
|
30159
|
-
});
|
|
30160
|
-
}
|
|
30161
|
-
else {
|
|
30162
|
-
updateCDSLocation(cdsMin, stopCodonGenomicLoc, feature, true);
|
|
30163
|
-
}
|
|
30164
|
-
}
|
|
30165
|
-
}
|
|
30166
|
-
notify('Translation sequence trimmed to start and stop codons', 'success');
|
|
30167
|
-
};
|
|
30168
|
-
const onCopyClick = () => {
|
|
30169
|
-
const seqDiv = seqRef.current;
|
|
30170
|
-
if (!seqDiv) {
|
|
30171
|
-
return;
|
|
30172
|
-
}
|
|
30173
|
-
void copyToClipboard(seqDiv);
|
|
30174
|
-
};
|
|
30175
30374
|
return (jsxRuntime.jsxs("div", { children: [cdsPresent && (jsxRuntime.jsx("div", { children: jsxRuntime.jsxs(material.Grid, { container: true, justifyContent: "center", alignItems: "center", style: { textAlign: 'center' }, children: [jsxRuntime.jsx(material.Grid, { size: 1 }), strand === 1 ? (jsxRuntime.jsx(material.Grid, { size: 4, children: jsxRuntime.jsx(StyledTextField, { margin: "dense", variant: "outlined", value: cdsMin + 1, onChangeCommitted: (newLocation) => {
|
|
30176
30375
|
return updateCDSLocation(cdsMin, newLocation - 1, feature, true);
|
|
30177
30376
|
}, style: { border: '1px solid black', borderRadius: 5 }, disabled: changeInProgress }) })) : (jsxRuntime.jsx(material.Grid, { size: 4, children: jsxRuntime.jsx(StyledTextField, { margin: "dense", variant: "outlined", value: cdsMax, onChangeCommitted: (newLocation) => {
|
|
@@ -30181,8 +30380,12 @@
|
|
|
30181
30380
|
}, style: { border: '1px solid black', borderRadius: 5 }, disabled: changeInProgress }) })) : (jsxRuntime.jsx(material.Grid, { size: 4, children: jsxRuntime.jsx(StyledTextField, { margin: "dense", variant: "outlined", value: cdsMin + 1, onChangeCommitted: (newLocation) => {
|
|
30182
30381
|
return updateCDSLocation(cdsMin, newLocation - 1, feature, true);
|
|
30183
30382
|
}, style: { border: '1px solid black', borderRadius: 5 }, disabled: changeInProgress }) })), jsxRuntime.jsx(material.Grid, { size: 1 })] }) })), jsxRuntime.jsxs("div", { style: { marginTop: 5, marginBottom: 10 }, children: [jsxRuntime.jsx("div", { style: { textAlign: 'center' }, children: jsxRuntime.jsx(material.Typography, { children: "Exons" }) }), transcriptExonParts.map((loc, index) => {
|
|
30184
|
-
return (
|
|
30185
|
-
|
|
30383
|
+
return (
|
|
30384
|
+
// eslint-disable-next-line @eslint-react/no-array-index-key
|
|
30385
|
+
jsxRuntime.jsx("div", { children: loc.type === 'exon' && (jsxRuntime.jsxs(material.Grid, { container: true, justifyContent: "center", alignItems: "center", style: { textAlign: 'center' }, children: [jsxRuntime.jsx(material.Grid, { size: 1, children: index !== 0 &&
|
|
30386
|
+
getFivePrimeSpliceSite(loc, index).map((site, idx) => (jsxRuntime.jsx(material.Typography
|
|
30387
|
+
// eslint-disable-next-line @eslint-react/no-array-index-key
|
|
30388
|
+
, { component: 'span', color: site.color, children: site.spliceSite }, idx))) }), strand === 1 ? (jsxRuntime.jsx(material.Grid, { size: 4, style: { padding: 0 }, children: jsxRuntime.jsx(StyledTextField, { margin: "dense", variant: "outlined", value: loc.min + 1, onChangeCommitted: (newLocation) => {
|
|
30186
30389
|
return handleExonLocationChange(loc.min, newLocation - 1, feature, true);
|
|
30187
30390
|
}, disabled: changeInProgress }) })) : (jsxRuntime.jsx(material.Grid, { size: 4, style: { padding: 0 }, children: jsxRuntime.jsx(StyledTextField, { margin: "dense", variant: "outlined", value: loc.max, onChangeCommitted: (newLocation) => {
|
|
30188
30391
|
return handleExonLocationChange(loc.max, newLocation, feature, false);
|
|
@@ -30191,14 +30394,10 @@
|
|
|
30191
30394
|
}, disabled: changeInProgress }) })) : (jsxRuntime.jsx(material.Grid, { size: 4, style: { padding: 0 }, children: jsxRuntime.jsx(StyledTextField, { margin: "dense", variant: "outlined", value: loc.min + 1, onChangeCommitted: (newLocation) => {
|
|
30192
30395
|
return handleExonLocationChange(loc.min, newLocation - 1, feature, true);
|
|
30193
30396
|
}, disabled: changeInProgress }) })), jsxRuntime.jsx(material.Grid, { size: 1, children: index !== transcriptExonParts.length - 1 &&
|
|
30194
|
-
getThreePrimeSpliceSite(loc, index).map((site, idx) => (jsxRuntime.jsx(material.Typography
|
|
30195
|
-
|
|
30196
|
-
|
|
30197
|
-
|
|
30198
|
-
flexDirection: 'row',
|
|
30199
|
-
alignItems: 'center',
|
|
30200
|
-
gap: 10,
|
|
30201
|
-
}, children: [jsxRuntime.jsx(material.Tooltip, { title: "Copy", children: jsxRuntime.jsx("button", { onClick: onCopyClick, style: { border: 'none', background: 'none', padding: 0 }, disabled: changeInProgress, children: jsxRuntime.jsx(ContentCopyIcon, { style: { fontSize: 15 } }) }) }), jsxRuntime.jsx(material.Tooltip, { title: "Trim", children: jsxRuntime.jsx("button", { onClick: trimTranslationSequence, style: { border: 'none', background: 'none', padding: 0 }, disabled: changeInProgress, children: jsxRuntime.jsx(ContentCutIcon, { style: { fontSize: 15 } }) }) })] })] })] }) }))] }));
|
|
30397
|
+
getThreePrimeSpliceSite(loc, index).map((site, idx) => (jsxRuntime.jsx(material.Typography
|
|
30398
|
+
// eslint-disable-next-line @eslint-react/no-array-index-key
|
|
30399
|
+
, { component: 'span', color: site.color, children: site.spliceSite }, idx))) })] })) }, index));
|
|
30400
|
+
})] }), cdsPresent && (jsxRuntime.jsx(Translation, { changeInProgress: changeInProgress, cdsLocations: cdsLocations, refData: refData, strand: strand, updateCDSLocation: updateCDSLocation, cdsMin: cdsMin, cdsMax: cdsMax, feature: feature, session: session }))] }));
|
|
30202
30401
|
});
|
|
30203
30402
|
|
|
30204
30403
|
const HeaderTableCell = newStyled(material.TableCell)(() => ({
|
|
@@ -30235,7 +30434,7 @@
|
|
|
30235
30434
|
const { assembly, feature, refName } = model;
|
|
30236
30435
|
React.useEffect(() => {
|
|
30237
30436
|
setPanelState(DEFAULT_PANELS);
|
|
30238
|
-
// eslint-disable-next-line react
|
|
30437
|
+
// eslint-disable-next-line @eslint-react/exhaustive-deps
|
|
30239
30438
|
}, [feature]);
|
|
30240
30439
|
const session = util$1.getSession(model);
|
|
30241
30440
|
const { pluginManager } = util$1.getEnv(session);
|
|
@@ -30294,8 +30493,8 @@
|
|
|
30294
30493
|
typeName: 'TypeChange',
|
|
30295
30494
|
changedIds: [featureId],
|
|
30296
30495
|
featureId,
|
|
30297
|
-
oldType
|
|
30298
|
-
newType
|
|
30496
|
+
oldType,
|
|
30497
|
+
newType,
|
|
30299
30498
|
assembly: feature.assemblyId,
|
|
30300
30499
|
});
|
|
30301
30500
|
return changeManager.submit(change);
|
|
@@ -30391,7 +30590,7 @@
|
|
|
30391
30590
|
if (initialValue !== value) {
|
|
30392
30591
|
setValue(initialValue);
|
|
30393
30592
|
}
|
|
30394
|
-
// eslint-disable-next-line react
|
|
30593
|
+
// eslint-disable-next-line @eslint-react/exhaustive-deps
|
|
30395
30594
|
}, [initialValue]);
|
|
30396
30595
|
React.useEffect(() => {
|
|
30397
30596
|
if (blur) {
|
|
@@ -31240,8 +31439,9 @@
|
|
|
31240
31439
|
const [top, left, width] = getFeatureBox(display, gene, row, block);
|
|
31241
31440
|
const height = getRowCount$2(display, gene) * apolloRowHeight;
|
|
31242
31441
|
if (width > 2) {
|
|
31243
|
-
|
|
31244
|
-
|
|
31442
|
+
const selectedColor = configuration.readConfObject(session.getPluginConfiguration(), 'geneBackgroundColor', {
|
|
31443
|
+
featureType: gene.type,
|
|
31444
|
+
}) ?? material.alpha(theme.palette.background.paper, 0.6);
|
|
31245
31445
|
ctx.fillStyle = selectedColor;
|
|
31246
31446
|
ctx.fillRect(left, top, width, height);
|
|
31247
31447
|
}
|
|
@@ -31514,7 +31714,7 @@
|
|
|
31514
31714
|
}
|
|
31515
31715
|
return layout;
|
|
31516
31716
|
}
|
|
31517
|
-
function getContextMenuItems$1(display,
|
|
31717
|
+
function getContextMenuItems$1(display, transcript) {
|
|
31518
31718
|
const { changeManager, regions, selectedFeature, session } = display;
|
|
31519
31719
|
const [region] = regions;
|
|
31520
31720
|
const currentAssemblyId = display.getAssemblyId(region.assemblyName);
|
|
@@ -31524,7 +31724,7 @@
|
|
|
31524
31724
|
label: 'Open transcript editor',
|
|
31525
31725
|
onClick: () => {
|
|
31526
31726
|
const apolloTranscriptWidget = session.addWidget('ApolloTranscriptDetails', 'apolloTranscriptDetails', {
|
|
31527
|
-
feature,
|
|
31727
|
+
feature: transcript,
|
|
31528
31728
|
assembly: currentAssemblyId,
|
|
31529
31729
|
changeManager,
|
|
31530
31730
|
refName: region.refName,
|
|
@@ -31544,7 +31744,7 @@
|
|
|
31544
31744
|
doneCallback();
|
|
31545
31745
|
},
|
|
31546
31746
|
changeManager,
|
|
31547
|
-
sourceFeature:
|
|
31747
|
+
sourceFeature: transcript,
|
|
31548
31748
|
sourceAssemblyId: currentAssemblyId,
|
|
31549
31749
|
selectedFeature,
|
|
31550
31750
|
setSelectedFeature: (feature) => {
|
|
@@ -31564,7 +31764,7 @@
|
|
|
31564
31764
|
doneCallback();
|
|
31565
31765
|
},
|
|
31566
31766
|
changeManager,
|
|
31567
|
-
sourceFeature:
|
|
31767
|
+
sourceFeature: transcript,
|
|
31568
31768
|
sourceAssemblyId: currentAssemblyId,
|
|
31569
31769
|
selectedFeature,
|
|
31570
31770
|
setSelectedFeature: (feature) => {
|
|
@@ -31574,6 +31774,31 @@
|
|
|
31574
31774
|
]);
|
|
31575
31775
|
},
|
|
31576
31776
|
});
|
|
31777
|
+
const { children } = transcript;
|
|
31778
|
+
if (!children) {
|
|
31779
|
+
return [];
|
|
31780
|
+
}
|
|
31781
|
+
const cdsChildren = [...children.values()].filter((child) => isCDSFeature(child, session));
|
|
31782
|
+
if (cdsChildren.length === 0) {
|
|
31783
|
+
menuItems.push({
|
|
31784
|
+
label: 'Add coding sequence',
|
|
31785
|
+
onClick: () => {
|
|
31786
|
+
session.queueDialog((doneCallback) => [
|
|
31787
|
+
AddCodingSequence,
|
|
31788
|
+
{
|
|
31789
|
+
session,
|
|
31790
|
+
handleClose: () => {
|
|
31791
|
+
doneCallback();
|
|
31792
|
+
},
|
|
31793
|
+
changeManager,
|
|
31794
|
+
sourceFeature: transcript,
|
|
31795
|
+
sourceAssemblyId: currentAssemblyId,
|
|
31796
|
+
refName: region.refName,
|
|
31797
|
+
},
|
|
31798
|
+
]);
|
|
31799
|
+
},
|
|
31800
|
+
});
|
|
31801
|
+
}
|
|
31577
31802
|
return menuItems;
|
|
31578
31803
|
}
|
|
31579
31804
|
// False positive here, none of these functions use "this"
|
|
@@ -31760,7 +31985,7 @@
|
|
|
31760
31985
|
letterUpper === 'C' ||
|
|
31761
31986
|
letterUpper === 'G' ||
|
|
31762
31987
|
letterUpper === 'T') {
|
|
31763
|
-
return theme.palette.bases[letterUpper].main
|
|
31988
|
+
return theme.palette.bases[letterUpper].main;
|
|
31764
31989
|
}
|
|
31765
31990
|
return 'lightgray';
|
|
31766
31991
|
}
|
|
@@ -31857,8 +32082,7 @@
|
|
|
31857
32082
|
return internetAccounts.find((ia) => configuration.getConf(ia, 'internetAccountId') === internetAccountConfigId);
|
|
31858
32083
|
},
|
|
31859
32084
|
get changeManager() {
|
|
31860
|
-
return self.session.apolloDataStore
|
|
31861
|
-
.changeManager;
|
|
32085
|
+
return self.session.apolloDataStore.changeManager;
|
|
31862
32086
|
},
|
|
31863
32087
|
getAssemblyId(assemblyName) {
|
|
31864
32088
|
const { assemblyManager } = self.session;
|
|
@@ -31869,12 +32093,10 @@
|
|
|
31869
32093
|
return assembly.name;
|
|
31870
32094
|
},
|
|
31871
32095
|
get selectedFeature() {
|
|
31872
|
-
return self.session
|
|
31873
|
-
.apolloSelectedFeature;
|
|
32096
|
+
return self.session.apolloSelectedFeature;
|
|
31874
32097
|
},
|
|
31875
32098
|
get hoveredFeature() {
|
|
31876
|
-
return self.session
|
|
31877
|
-
.apolloHoveredFeature;
|
|
32099
|
+
return self.session.apolloHoveredFeature;
|
|
31878
32100
|
},
|
|
31879
32101
|
}))
|
|
31880
32102
|
.actions((self) => ({
|
|
@@ -31919,8 +32141,11 @@
|
|
|
31919
32141
|
const { filteredFeatureTypes, trackMenuItems: superTrackMenuItems } = self;
|
|
31920
32142
|
return {
|
|
31921
32143
|
trackMenuItems() {
|
|
31922
|
-
const { graphical, table, showCheckResults } = self;
|
|
31923
|
-
|
|
32144
|
+
const { graphical, table, showCheckResults, session } = self;
|
|
32145
|
+
const [region] = self.regions;
|
|
32146
|
+
const { assemblyName } = region;
|
|
32147
|
+
const backendDriver = session.apolloDataStore.getBackendDriver(assemblyName);
|
|
32148
|
+
const items = [
|
|
31924
32149
|
...superTrackMenuItems(),
|
|
31925
32150
|
{
|
|
31926
32151
|
type: 'subMenu',
|
|
@@ -31972,7 +32197,7 @@
|
|
|
31972
32197
|
{
|
|
31973
32198
|
label: 'Filter features by type',
|
|
31974
32199
|
onClick: () => {
|
|
31975
|
-
const session = self
|
|
32200
|
+
const { session } = self;
|
|
31976
32201
|
self.session.queueDialog((doneCallback) => [
|
|
31977
32202
|
FilterFeatures,
|
|
31978
32203
|
{
|
|
@@ -31988,76 +32213,93 @@
|
|
|
31988
32213
|
]);
|
|
31989
32214
|
},
|
|
31990
32215
|
},
|
|
31991
|
-
|
|
31992
|
-
|
|
31993
|
-
|
|
32216
|
+
];
|
|
32217
|
+
if (backendDriver instanceof LocalDriver) {
|
|
32218
|
+
items.push({
|
|
32219
|
+
label: 'Import annotations',
|
|
32220
|
+
icon: InputIcon,
|
|
31994
32221
|
onClick: () => {
|
|
31995
|
-
const [region] = self.regions;
|
|
31996
|
-
const { assemblyName } = region;
|
|
31997
|
-
const assembly = self.getAssemblyId(assemblyName);
|
|
31998
|
-
if (!assembly) {
|
|
31999
|
-
return;
|
|
32000
|
-
}
|
|
32001
|
-
const session = self.session;
|
|
32002
32222
|
session.queueDialog((doneCallback) => [
|
|
32003
|
-
|
|
32223
|
+
ImportAnnotations,
|
|
32004
32224
|
{
|
|
32005
32225
|
session,
|
|
32226
|
+
assemblyName,
|
|
32006
32227
|
handleClose: () => {
|
|
32007
32228
|
doneCallback();
|
|
32008
32229
|
},
|
|
32009
|
-
assembly,
|
|
32010
32230
|
},
|
|
32011
32231
|
]);
|
|
32012
32232
|
},
|
|
32233
|
+
});
|
|
32234
|
+
}
|
|
32235
|
+
items.push({
|
|
32236
|
+
label: 'Export annotations',
|
|
32237
|
+
icon: Export,
|
|
32238
|
+
onClick: () => {
|
|
32239
|
+
const [region] = self.regions;
|
|
32240
|
+
const { assemblyName } = region;
|
|
32241
|
+
const assembly = self.getAssemblyId(assemblyName);
|
|
32242
|
+
if (!assembly) {
|
|
32243
|
+
return;
|
|
32244
|
+
}
|
|
32245
|
+
const { session } = self;
|
|
32246
|
+
session.queueDialog((doneCallback) => [
|
|
32247
|
+
DownloadGFF3,
|
|
32248
|
+
{
|
|
32249
|
+
session,
|
|
32250
|
+
handleClose: () => {
|
|
32251
|
+
doneCallback();
|
|
32252
|
+
},
|
|
32253
|
+
assembly,
|
|
32254
|
+
},
|
|
32255
|
+
]);
|
|
32013
32256
|
},
|
|
32014
|
-
|
|
32015
|
-
|
|
32016
|
-
|
|
32017
|
-
|
|
32018
|
-
|
|
32019
|
-
|
|
32020
|
-
|
|
32021
|
-
|
|
32022
|
-
|
|
32023
|
-
|
|
32024
|
-
|
|
32025
|
-
|
|
32026
|
-
|
|
32027
|
-
|
|
32028
|
-
|
|
32029
|
-
|
|
32030
|
-
|
|
32031
|
-
},
|
|
32032
|
-
assembly,
|
|
32257
|
+
}, {
|
|
32258
|
+
label: 'View Change Log',
|
|
32259
|
+
icon: TrackChangesIcon,
|
|
32260
|
+
onClick: () => {
|
|
32261
|
+
const [region] = self.regions;
|
|
32262
|
+
const { assemblyName } = region;
|
|
32263
|
+
const assembly = self.getAssemblyId(assemblyName);
|
|
32264
|
+
if (!assembly) {
|
|
32265
|
+
return;
|
|
32266
|
+
}
|
|
32267
|
+
const { session } = self;
|
|
32268
|
+
session.queueDialog((doneCallback) => [
|
|
32269
|
+
ViewChangeLog,
|
|
32270
|
+
{
|
|
32271
|
+
session,
|
|
32272
|
+
handleClose: () => {
|
|
32273
|
+
doneCallback();
|
|
32033
32274
|
},
|
|
32034
|
-
|
|
32035
|
-
|
|
32275
|
+
assembly,
|
|
32276
|
+
},
|
|
32277
|
+
]);
|
|
32036
32278
|
},
|
|
32037
|
-
|
|
32038
|
-
|
|
32039
|
-
|
|
32040
|
-
|
|
32041
|
-
|
|
32042
|
-
|
|
32043
|
-
|
|
32044
|
-
|
|
32045
|
-
|
|
32046
|
-
|
|
32047
|
-
|
|
32048
|
-
|
|
32049
|
-
|
|
32050
|
-
|
|
32051
|
-
|
|
32052
|
-
|
|
32053
|
-
|
|
32054
|
-
},
|
|
32055
|
-
assembly,
|
|
32279
|
+
}, {
|
|
32280
|
+
label: 'View Check Results',
|
|
32281
|
+
icon: FactCheckIcon,
|
|
32282
|
+
onClick: () => {
|
|
32283
|
+
const [region] = self.regions;
|
|
32284
|
+
const { assemblyName } = region;
|
|
32285
|
+
const assembly = self.getAssemblyId(assemblyName);
|
|
32286
|
+
if (!assembly) {
|
|
32287
|
+
return;
|
|
32288
|
+
}
|
|
32289
|
+
const { session } = self;
|
|
32290
|
+
session.queueDialog((doneCallback) => [
|
|
32291
|
+
ViewCheckResults,
|
|
32292
|
+
{
|
|
32293
|
+
session,
|
|
32294
|
+
handleClose: () => {
|
|
32295
|
+
doneCallback();
|
|
32056
32296
|
},
|
|
32057
|
-
|
|
32058
|
-
|
|
32297
|
+
assembly,
|
|
32298
|
+
},
|
|
32299
|
+
]);
|
|
32059
32300
|
},
|
|
32060
|
-
|
|
32301
|
+
});
|
|
32302
|
+
return items;
|
|
32061
32303
|
},
|
|
32062
32304
|
};
|
|
32063
32305
|
})
|
|
@@ -33123,8 +33365,7 @@
|
|
|
33123
33365
|
return internetAccounts.find((ia) => configuration.getConf(ia, 'internetAccountId') === internetAccountConfigId);
|
|
33124
33366
|
},
|
|
33125
33367
|
get changeManager() {
|
|
33126
|
-
return self.session.apolloDataStore
|
|
33127
|
-
.changeManager;
|
|
33368
|
+
return self.session.apolloDataStore.changeManager;
|
|
33128
33369
|
},
|
|
33129
33370
|
getAssemblyId(assemblyName) {
|
|
33130
33371
|
const { assemblyManager } = self.session;
|
|
@@ -33135,12 +33376,10 @@
|
|
|
33135
33376
|
return assembly.name;
|
|
33136
33377
|
},
|
|
33137
33378
|
get selectedFeature() {
|
|
33138
|
-
return self.session
|
|
33139
|
-
.apolloSelectedFeature;
|
|
33379
|
+
return self.session.apolloSelectedFeature;
|
|
33140
33380
|
},
|
|
33141
33381
|
get hoveredFeature() {
|
|
33142
|
-
return self.session
|
|
33143
|
-
.apolloHoveredFeature;
|
|
33382
|
+
return self.session.apolloHoveredFeature;
|
|
33144
33383
|
},
|
|
33145
33384
|
get height() {
|
|
33146
33385
|
const { sequenceRowHeight } = self;
|
|
@@ -33352,11 +33591,9 @@
|
|
|
33352
33591
|
onUpdate(newForms);
|
|
33353
33592
|
setExcludedTranscripts(newForms);
|
|
33354
33593
|
};
|
|
33355
|
-
return (jsxRuntime.jsx(Dialog, { open: true, maxWidth: false, "data-testid": "filter-transcripts-dialog", title: "Filter transcripts by ID", handleClose: handleClose, children: jsxRuntime.jsxs(material.DialogContent, { children: [jsxRuntime.jsx(material.DialogContentText, { children: "Select the alternate transcripts you want to display in the apollo track" }), jsxRuntime.jsx(material.Grid, { container: true, spacing: 2, children: jsxRuntime.jsx(material.Grid, { size: 8, children: jsxRuntime.jsx(material.FormGroup, { children: allTranscripts.map((item) => (
|
|
33356
|
-
// eslint-disable-next-line react/jsx-key
|
|
33357
|
-
jsxRuntime.jsx(material.FormControlLabel, { control: jsxRuntime.jsx(material.Checkbox, { checked: !excludedTranscripts.includes(item), onChange: () => {
|
|
33594
|
+
return (jsxRuntime.jsx(Dialog, { open: true, maxWidth: false, "data-testid": "filter-transcripts-dialog", title: "Filter transcripts by ID", handleClose: handleClose, children: jsxRuntime.jsxs(material.DialogContent, { children: [jsxRuntime.jsx(material.DialogContentText, { children: "Select the alternate transcripts you want to display in the apollo track" }), jsxRuntime.jsx(material.Grid, { container: true, spacing: 2, children: jsxRuntime.jsx(material.Grid, { size: 8, children: jsxRuntime.jsx(material.FormGroup, { children: allTranscripts.map((item) => (jsxRuntime.jsx(material.FormControlLabel, { control: jsxRuntime.jsx(material.Checkbox, { checked: !excludedTranscripts.includes(item), onChange: () => {
|
|
33358
33595
|
handleChange(item);
|
|
33359
|
-
}, slotProps: { input: { 'aria-label': 'controlled' } } }), label: item }))) }) }) })] }) }));
|
|
33596
|
+
}, slotProps: { input: { 'aria-label': 'controlled' } } }), label: item }, item))) }) }) })] }) }));
|
|
33360
33597
|
});
|
|
33361
33598
|
|
|
33362
33599
|
let forwardFillLight = null;
|
|
@@ -34202,8 +34439,7 @@
|
|
|
34202
34439
|
return internetAccounts.find((ia) => configuration.getConf(ia, 'internetAccountId') === internetAccountConfigId);
|
|
34203
34440
|
},
|
|
34204
34441
|
get changeManager() {
|
|
34205
|
-
return self.session.apolloDataStore
|
|
34206
|
-
.changeManager;
|
|
34442
|
+
return self.session.apolloDataStore.changeManager;
|
|
34207
34443
|
},
|
|
34208
34444
|
getAssemblyId(assemblyName) {
|
|
34209
34445
|
const { assemblyManager } = self.session;
|
|
@@ -34214,12 +34450,10 @@
|
|
|
34214
34450
|
return assembly.name;
|
|
34215
34451
|
},
|
|
34216
34452
|
get selectedFeature() {
|
|
34217
|
-
return self.session
|
|
34218
|
-
.apolloSelectedFeature;
|
|
34453
|
+
return self.session.apolloSelectedFeature;
|
|
34219
34454
|
},
|
|
34220
34455
|
get hoveredFeature() {
|
|
34221
|
-
return self.session
|
|
34222
|
-
.apolloHoveredFeature;
|
|
34456
|
+
return self.session.apolloHoveredFeature;
|
|
34223
34457
|
},
|
|
34224
34458
|
}))
|
|
34225
34459
|
.actions((self) => ({
|
|
@@ -34347,7 +34581,7 @@
|
|
|
34347
34581
|
{
|
|
34348
34582
|
label: 'Filter features by type',
|
|
34349
34583
|
onClick: () => {
|
|
34350
|
-
const session = self
|
|
34584
|
+
const { session } = self;
|
|
34351
34585
|
self.session.queueDialog((doneCallback) => [
|
|
34352
34586
|
FilterFeatures,
|
|
34353
34587
|
{
|
|
@@ -34785,17 +35019,12 @@
|
|
|
34785
35019
|
if (!featureTypeOntology) {
|
|
34786
35020
|
throw new Error('featureTypeOntology is undefined');
|
|
34787
35021
|
}
|
|
34788
|
-
|
|
34789
|
-
|
|
34790
|
-
foundFeature = layoutRow.find((f) => f.feature.type == 'exon' &&
|
|
35022
|
+
const foundFeature = self.geneTrackRowNums.includes(row)
|
|
35023
|
+
? layoutRow.find((f) => f.feature.type == 'exon' &&
|
|
34791
35024
|
bp >= f.feature.min &&
|
|
34792
|
-
bp <= f.feature.max)
|
|
34793
|
-
|
|
34794
|
-
|
|
34795
|
-
}
|
|
34796
|
-
}
|
|
34797
|
-
else {
|
|
34798
|
-
foundFeature = layoutRow.find((f) => {
|
|
35025
|
+
bp <= f.feature.max) ??
|
|
35026
|
+
layoutRow.find((f) => bp >= f.feature.min && bp <= f.feature.max)
|
|
35027
|
+
: layoutRow.find((f) => {
|
|
34799
35028
|
const { feature } = f;
|
|
34800
35029
|
const featureID = feature.attributes.get('gff_id')?.toString();
|
|
34801
35030
|
const isTranscript = featureTypeOntology.isTypeOf(feature.type, 'transcript');
|
|
@@ -34817,7 +35046,6 @@
|
|
|
34817
35046
|
}
|
|
34818
35047
|
return false;
|
|
34819
35048
|
});
|
|
34820
|
-
}
|
|
34821
35049
|
if (!foundFeature) {
|
|
34822
35050
|
return mousePosition;
|
|
34823
35051
|
}
|
|
@@ -35141,26 +35369,32 @@
|
|
|
35141
35369
|
const apolloAssembly = apolloSessionModel.apolloDataStore.assemblies.get(assembly.name);
|
|
35142
35370
|
const refSeq = apolloAssembly?.refSeqs.get(refSeqId);
|
|
35143
35371
|
const features = refSeq?.getFeatures(region.start, region.end);
|
|
35144
|
-
const getDestinationFeatures = () => {
|
|
35145
|
-
const filteredFeatures = [];
|
|
35146
|
-
for (const f of features ?? []) {
|
|
35147
|
-
if (f.min > region.end || f.max < region.start) {
|
|
35148
|
-
continue;
|
|
35149
|
-
}
|
|
35150
|
-
// Destination feature should be of type gene
|
|
35151
|
-
if (featureTypeOntology?.isTypeOf(f.type, 'gene')) {
|
|
35152
|
-
const featureSnapshot = mobxStateTree.getSnapshot(f);
|
|
35153
|
-
filteredFeatures.push(featureSnapshot);
|
|
35154
|
-
}
|
|
35155
|
-
}
|
|
35156
|
-
return filteredFeatures;
|
|
35157
|
-
};
|
|
35158
35372
|
React.useEffect(() => {
|
|
35373
|
+
const getDestinationFeatures = () => {
|
|
35374
|
+
const filteredFeatures = [];
|
|
35375
|
+
for (const f of features ?? []) {
|
|
35376
|
+
if (f.min > region.end || f.max < region.start) {
|
|
35377
|
+
continue;
|
|
35378
|
+
}
|
|
35379
|
+
// Destination feature should be of type gene
|
|
35380
|
+
if (featureTypeOntology?.isTypeOf(f.type, 'gene')) {
|
|
35381
|
+
const featureSnapshot = mobxStateTree.getSnapshot(f);
|
|
35382
|
+
filteredFeatures.push(featureSnapshot);
|
|
35383
|
+
}
|
|
35384
|
+
}
|
|
35385
|
+
return filteredFeatures;
|
|
35386
|
+
};
|
|
35159
35387
|
setErrorMessage('');
|
|
35160
|
-
const
|
|
35161
|
-
setDestinationFeatures(
|
|
35162
|
-
setSelectedDestinationFeature(
|
|
35163
|
-
}, [
|
|
35388
|
+
const destinationFeatures = getDestinationFeatures();
|
|
35389
|
+
setDestinationFeatures(destinationFeatures);
|
|
35390
|
+
setSelectedDestinationFeature(destinationFeatures[0]);
|
|
35391
|
+
}, [
|
|
35392
|
+
checkedChildrens,
|
|
35393
|
+
featureTypeOntology,
|
|
35394
|
+
features,
|
|
35395
|
+
parentFeatureChecked,
|
|
35396
|
+
region,
|
|
35397
|
+
]);
|
|
35164
35398
|
const handleParentFeatureCheck = (event) => {
|
|
35165
35399
|
const isChecked = event.target.checked;
|
|
35166
35400
|
setParentFeatureChecked(isChecked);
|
|
@@ -35440,8 +35674,21 @@
|
|
|
35440
35674
|
getAnnotationFeature(jbrowseFeature, refSeqId) {
|
|
35441
35675
|
const start = jbrowseFeature.get('start');
|
|
35442
35676
|
const end = jbrowseFeature.get('end');
|
|
35443
|
-
const strand = jbrowseFeature.get('strand');
|
|
35444
35677
|
const name = jbrowseFeature.get('name');
|
|
35678
|
+
let strand;
|
|
35679
|
+
const tags = jbrowseFeature.get('tags');
|
|
35680
|
+
const { ts, TS, XS } = tags;
|
|
35681
|
+
for (const tag of [ts, TS, XS]) {
|
|
35682
|
+
if (!strand && tag) {
|
|
35683
|
+
if ([1, '1', '+'].includes(tag)) {
|
|
35684
|
+
strand = 1;
|
|
35685
|
+
}
|
|
35686
|
+
else if ([-1, '-1', '-'].includes(tag)) {
|
|
35687
|
+
strand = -1;
|
|
35688
|
+
}
|
|
35689
|
+
}
|
|
35690
|
+
}
|
|
35691
|
+
strand ??= jbrowseFeature.get('strand');
|
|
35445
35692
|
const cigarData = jbrowseFeature.get('CIGAR');
|
|
35446
35693
|
const ops = parseCigar(cigarData);
|
|
35447
35694
|
let position = start;
|
|
@@ -35457,9 +35704,7 @@
|
|
|
35457
35704
|
case 'M':
|
|
35458
35705
|
case '=':
|
|
35459
35706
|
case 'X': {
|
|
35460
|
-
|
|
35461
|
-
currentExonStart = position;
|
|
35462
|
-
}
|
|
35707
|
+
currentExonStart ??= position;
|
|
35463
35708
|
position += len;
|
|
35464
35709
|
break;
|
|
35465
35710
|
}
|
|
@@ -35885,7 +36130,7 @@
|
|
|
35885
36130
|
: undefined, menuItems: contextMenuItems })] }))] }));
|
|
35886
36131
|
});
|
|
35887
36132
|
|
|
35888
|
-
const TrackLines = mobxReact.observer(function TrackLines({ model, hrStyle = { margin: 0, top: 0, color: 'black' }, idx
|
|
36133
|
+
const TrackLines = mobxReact.observer(function TrackLines({ model, hrStyle = { margin: 0, top: 0, color: 'black' }, idx, }) {
|
|
35889
36134
|
const { apolloRowHeight, highestRow, showFeatureLabels } = model;
|
|
35890
36135
|
const featureLabelSpacer = showFeatureLabels ? 2 : 1;
|
|
35891
36136
|
return (jsxRuntime.jsx("div", { style: {
|
|
@@ -35957,8 +36202,7 @@
|
|
|
35957
36202
|
regionNumber: idx,
|
|
35958
36203
|
})?.offsetPx ?? 0) - lgv.offsetPx;
|
|
35959
36204
|
const [feature] = checkResult.featureIds;
|
|
35960
|
-
if (!feature ||
|
|
35961
|
-
!feature.parent ||
|
|
36205
|
+
if (!feature?.parent ||
|
|
35962
36206
|
!looksLikeGene(feature.parent, session)) {
|
|
35963
36207
|
return null;
|
|
35964
36208
|
}
|
|
@@ -36226,18 +36470,15 @@
|
|
|
36226
36470
|
d: "M17 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V7zm-5 16c-1.66 0-3-1.34-3-3s1.34-3 3-3 3 1.34 3 3-1.34 3-3 3m3-10H5V5h10z"
|
|
36227
36471
|
}), 'Save');
|
|
36228
36472
|
|
|
36229
|
-
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
|
36230
36473
|
/* eslint-disable @typescript-eslint/no-confusing-void-expression */
|
|
36231
36474
|
const ApolloJobModel = mobxStateTree.types
|
|
36232
36475
|
.model('JobsManager', {})
|
|
36233
36476
|
.views((self) => ({
|
|
36234
36477
|
get jobStatusWidget() {
|
|
36235
36478
|
const { widgets } = util$1.getSession(self);
|
|
36236
|
-
|
|
36237
|
-
if (!jobStatusWidget) {
|
|
36479
|
+
const jobStatusWidget = widgets.get('JobsList') ??
|
|
36238
36480
|
// @ts-expect-error: addWidget function not detected on the session
|
|
36239
|
-
|
|
36240
|
-
}
|
|
36481
|
+
util$1.getSession(self).addWidget('JobsListWidget', 'JobsList');
|
|
36241
36482
|
return jobStatusWidget;
|
|
36242
36483
|
},
|
|
36243
36484
|
}))
|
|
@@ -36516,19 +36757,15 @@
|
|
|
36516
36757
|
continue;
|
|
36517
36758
|
}
|
|
36518
36759
|
const { assemblyName, refName } = region;
|
|
36519
|
-
|
|
36520
|
-
|
|
36521
|
-
assembly = self.assemblies.put({ _id: assemblyName, refSeqs: {} });
|
|
36522
|
-
}
|
|
36760
|
+
const assembly = self.assemblies.get(assemblyName) ??
|
|
36761
|
+
self.assemblies.put({ _id: assemblyName, refSeqs: {} });
|
|
36523
36762
|
const [firstFeature] = features;
|
|
36524
|
-
|
|
36525
|
-
|
|
36526
|
-
ref = assembly.refSeqs.put({
|
|
36763
|
+
const ref = assembly.refSeqs.get(firstFeature.refSeq) ??
|
|
36764
|
+
assembly.refSeqs.put({
|
|
36527
36765
|
_id: firstFeature.refSeq,
|
|
36528
36766
|
name: refName,
|
|
36529
36767
|
features: {},
|
|
36530
36768
|
});
|
|
36531
|
-
}
|
|
36532
36769
|
for (const feature of features) {
|
|
36533
36770
|
if (!ref.features.has(feature._id)) {
|
|
36534
36771
|
ref.features.put(feature);
|
|
@@ -36545,24 +36782,153 @@
|
|
|
36545
36782
|
}
|
|
36546
36783
|
const { refSeq, seq } = yield backendDriver.getSequence(region);
|
|
36547
36784
|
const { assemblyName, end, refName, start } = region;
|
|
36548
|
-
|
|
36549
|
-
|
|
36550
|
-
|
|
36551
|
-
|
|
36552
|
-
let ref = assembly.refSeqs.get(refSeq);
|
|
36553
|
-
if (!ref) {
|
|
36554
|
-
ref = assembly.refSeqs.put({
|
|
36555
|
-
_id: refSeq,
|
|
36556
|
-
name: refName,
|
|
36557
|
-
sequence: [],
|
|
36558
|
-
});
|
|
36559
|
-
}
|
|
36785
|
+
const assembly = self.assemblies.get(assemblyName) ??
|
|
36786
|
+
self.assemblies.put({ _id: assemblyName, refSeqs: {} });
|
|
36787
|
+
const ref = assembly.refSeqs.get(refSeq) ??
|
|
36788
|
+
assembly.refSeqs.put({ _id: refSeq, name: refName, sequence: [] });
|
|
36560
36789
|
ref.addSequence({ start, stop: end, sequence: seq });
|
|
36561
36790
|
}
|
|
36562
36791
|
}),
|
|
36563
36792
|
}));
|
|
36564
36793
|
}
|
|
36565
36794
|
|
|
36795
|
+
function reassignIds(feature) {
|
|
36796
|
+
const newChildren = {};
|
|
36797
|
+
if (feature.children) {
|
|
36798
|
+
for (const child of Object.values(feature.children)) {
|
|
36799
|
+
const newChild = reassignIds(child);
|
|
36800
|
+
newChildren[newChild._id] = newChild;
|
|
36801
|
+
}
|
|
36802
|
+
}
|
|
36803
|
+
return {
|
|
36804
|
+
...feature,
|
|
36805
|
+
_id: new ObjectID().toHexString(),
|
|
36806
|
+
children: feature.children ? newChildren : undefined,
|
|
36807
|
+
};
|
|
36808
|
+
}
|
|
36809
|
+
function DuplicateFeatureDialog({ assemblyName, changeManager, existingFeature, featureSnapshot, handleClose, }) {
|
|
36810
|
+
const [choice, setChoice] = React.useState('keepExisting');
|
|
36811
|
+
const [errorMessage, setErrorMessage] = React.useState('');
|
|
36812
|
+
const [submitted, setSubmitted] = React.useState(false);
|
|
36813
|
+
const handleSubmit = async () => {
|
|
36814
|
+
setErrorMessage('');
|
|
36815
|
+
setSubmitted(true);
|
|
36816
|
+
try {
|
|
36817
|
+
if (choice === 'useNew') {
|
|
36818
|
+
const deleteChange = new DeleteFeatureChange({
|
|
36819
|
+
typeName: 'DeleteFeatureChange',
|
|
36820
|
+
assembly: assemblyName,
|
|
36821
|
+
changedIds: [existingFeature._id],
|
|
36822
|
+
deletedFeature: existingFeature,
|
|
36823
|
+
});
|
|
36824
|
+
await changeManager.submit(deleteChange);
|
|
36825
|
+
const addChange = new AddFeatureChange({
|
|
36826
|
+
typeName: 'AddFeatureChange',
|
|
36827
|
+
assembly: assemblyName,
|
|
36828
|
+
changedIds: [featureSnapshot._id],
|
|
36829
|
+
addedFeature: featureSnapshot,
|
|
36830
|
+
});
|
|
36831
|
+
await changeManager.submit(addChange);
|
|
36832
|
+
}
|
|
36833
|
+
else if (choice === 'keepBoth') {
|
|
36834
|
+
const newSnapshot = reassignIds(featureSnapshot);
|
|
36835
|
+
const addChange = new AddFeatureChange({
|
|
36836
|
+
typeName: 'AddFeatureChange',
|
|
36837
|
+
assembly: assemblyName,
|
|
36838
|
+
changedIds: [newSnapshot._id],
|
|
36839
|
+
addedFeature: newSnapshot,
|
|
36840
|
+
});
|
|
36841
|
+
await changeManager.submit(addChange);
|
|
36842
|
+
}
|
|
36843
|
+
handleClose();
|
|
36844
|
+
}
|
|
36845
|
+
catch (error) {
|
|
36846
|
+
setErrorMessage(String(error));
|
|
36847
|
+
setSubmitted(false);
|
|
36848
|
+
}
|
|
36849
|
+
};
|
|
36850
|
+
return (jsxRuntime.jsxs(Dialog, { open: true, title: "Duplicate Feature Detected", handleClose: handleClose, maxWidth: "sm", fullWidth: true, children: [jsxRuntime.jsxs(material.DialogContent, { children: [jsxRuntime.jsxs(material.DialogContentText, { children: ["A feature with ID \u201C", featureSnapshot._id, "\u201D already exists. How would you like to resolve this conflict?"] }), jsxRuntime.jsxs(material.FormControl, { component: "fieldset", sx: { mt: 2 }, children: [jsxRuntime.jsx(material.FormLabel, { component: "legend", children: "Resolution" }), jsxRuntime.jsxs(material.RadioGroup, { value: choice, onChange: (e) => {
|
|
36851
|
+
setChoice(e.target.value);
|
|
36852
|
+
}, children: [jsxRuntime.jsx(material.FormControlLabel, { value: "keepExisting", control: jsxRuntime.jsx(material.Radio, {}), label: "Keep the existing feature" }), jsxRuntime.jsx(material.FormControlLabel, { value: "useNew", control: jsxRuntime.jsx(material.Radio, {}), label: "Replace with the new feature" }), jsxRuntime.jsx(material.FormControlLabel, { value: "keepBoth", control: jsxRuntime.jsx(material.Radio, {}), label: "Keep both (assign new IDs to the incoming feature)" })] })] }), errorMessage ? (jsxRuntime.jsx(material.DialogContentText, { color: "error", sx: { mt: 1 }, children: errorMessage })) : null] }), jsxRuntime.jsxs(material.DialogActions, { children: [jsxRuntime.jsx(material.Button, { variant: "contained", onClick: handleSubmit, disabled: submitted, children: "Confirm" }), jsxRuntime.jsx(material.Button, { onClick: handleClose, disabled: submitted, children: "Cancel" })] })] }));
|
|
36853
|
+
}
|
|
36854
|
+
|
|
36855
|
+
function fromUrlSafeBase64(urlSafeBase64) {
|
|
36856
|
+
let base64 = urlSafeBase64.replaceAll('-', '+').replaceAll('_', '/');
|
|
36857
|
+
const pad = base64.length % 4;
|
|
36858
|
+
if (pad) {
|
|
36859
|
+
base64 += '='.repeat(4 - pad);
|
|
36860
|
+
}
|
|
36861
|
+
return base64;
|
|
36862
|
+
}
|
|
36863
|
+
// Base64 decode + decompress
|
|
36864
|
+
async function decompress(encoded) {
|
|
36865
|
+
const binaryString = atob(encoded);
|
|
36866
|
+
// eslint-disable-next-line unicorn/prefer-code-point
|
|
36867
|
+
const bytes = Uint8Array.from(binaryString, (char) => char.charCodeAt(0));
|
|
36868
|
+
const stream = new Blob([bytes]).stream();
|
|
36869
|
+
const decompressionStream = new DecompressionStream('gzip');
|
|
36870
|
+
const decompressedStream = stream.pipeThrough(decompressionStream);
|
|
36871
|
+
const response = new Response(decompressedStream);
|
|
36872
|
+
const decompressed = await response.arrayBuffer();
|
|
36873
|
+
return JSON.parse(new TextDecoder().decode(decompressed));
|
|
36874
|
+
}
|
|
36875
|
+
async function handleApolloFeaturesUrlParam(encodedFeatures, apolloDataStore, assemblyManager, session) {
|
|
36876
|
+
const base64 = fromUrlSafeBase64(encodedFeatures);
|
|
36877
|
+
const decompressed = await decompress(base64);
|
|
36878
|
+
const featuresData = decompressed;
|
|
36879
|
+
for (const [assemblyName, featureSnapshots] of Object.entries(featuresData)) {
|
|
36880
|
+
const backendDriver = apolloDataStore.getBackendDriver(assemblyName);
|
|
36881
|
+
if (!(backendDriver instanceof LocalDriver)) {
|
|
36882
|
+
continue;
|
|
36883
|
+
}
|
|
36884
|
+
const assembly = (await assemblyManager.waitForAssembly(assemblyName));
|
|
36885
|
+
if (!assembly) {
|
|
36886
|
+
throw new Error(`Assembly not found: "${assemblyName}"`);
|
|
36887
|
+
}
|
|
36888
|
+
const { regions } = assembly;
|
|
36889
|
+
if (!regions) {
|
|
36890
|
+
throw new Error(`Assembly not found: "${assemblyName}"`);
|
|
36891
|
+
}
|
|
36892
|
+
const refNames = regions.map((r) => r.refName);
|
|
36893
|
+
const db = await openDb(assemblyName, refNames);
|
|
36894
|
+
for (const featureSnapshot of featureSnapshots) {
|
|
36895
|
+
const storeName = `features-${featureSnapshot.refSeq}`;
|
|
36896
|
+
const existing = (await db.get(storeName, featureSnapshot._id));
|
|
36897
|
+
if (existing === undefined) {
|
|
36898
|
+
const change = new AddFeatureChange({
|
|
36899
|
+
typeName: 'AddFeatureChange',
|
|
36900
|
+
assembly: assemblyName,
|
|
36901
|
+
changedIds: [featureSnapshot._id],
|
|
36902
|
+
addedFeature: featureSnapshot,
|
|
36903
|
+
});
|
|
36904
|
+
await apolloDataStore.changeManager.submit(change);
|
|
36905
|
+
}
|
|
36906
|
+
else {
|
|
36907
|
+
// get rid of undefined values in JSON
|
|
36908
|
+
// eslint-disable-next-line unicorn/prefer-structured-clone
|
|
36909
|
+
const existingFeature = JSON.parse(JSON.stringify(existing));
|
|
36910
|
+
if (!equal(featureSnapshot, existingFeature)) {
|
|
36911
|
+
await new Promise((resolve) => {
|
|
36912
|
+
session.queueDialog((doneCallback) => [
|
|
36913
|
+
DuplicateFeatureDialog,
|
|
36914
|
+
{
|
|
36915
|
+
featureSnapshot,
|
|
36916
|
+
existingFeature,
|
|
36917
|
+
assemblyName,
|
|
36918
|
+
changeManager: apolloDataStore.changeManager,
|
|
36919
|
+
handleClose: () => {
|
|
36920
|
+
doneCallback();
|
|
36921
|
+
resolve();
|
|
36922
|
+
},
|
|
36923
|
+
},
|
|
36924
|
+
]);
|
|
36925
|
+
});
|
|
36926
|
+
}
|
|
36927
|
+
}
|
|
36928
|
+
}
|
|
36929
|
+
}
|
|
36930
|
+
}
|
|
36931
|
+
|
|
36566
36932
|
/* eslint-disable @typescript-eslint/no-unnecessary-condition */
|
|
36567
36933
|
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
|
36568
36934
|
function extendSession(pluginManager, sessionModel) {
|
|
@@ -36648,8 +37014,7 @@
|
|
|
36648
37014
|
for (const block of dynamicBlocks.contentBlocks) {
|
|
36649
37015
|
const { assemblyName, end, refName, start } = block;
|
|
36650
37016
|
const assembly = self.apolloDataStore.assemblies.get(assemblyName);
|
|
36651
|
-
if (assembly
|
|
36652
|
-
assembly.backendDriverType === 'CollaborationServerDriver') {
|
|
37017
|
+
if (assembly?.backendDriverType === 'CollaborationServerDriver') {
|
|
36653
37018
|
locations.push({ assemblyName, refName, start, end });
|
|
36654
37019
|
}
|
|
36655
37020
|
}
|
|
@@ -36708,8 +37073,8 @@
|
|
|
36708
37073
|
for (const block of dynamicBlocks.contentBlocks) {
|
|
36709
37074
|
const { assemblyName, end, refName, start } = block;
|
|
36710
37075
|
const assembly = self.apolloDataStore.assemblies.get(assemblyName);
|
|
36711
|
-
if (assembly
|
|
36712
|
-
|
|
37076
|
+
if (assembly?.backendDriverType ===
|
|
37077
|
+
'CollaborationServerDriver') {
|
|
36713
37078
|
locations.push({ assemblyName, refName, start, end });
|
|
36714
37079
|
}
|
|
36715
37080
|
}
|
|
@@ -36829,6 +37194,37 @@
|
|
|
36829
37194
|
beforeDestroy() {
|
|
36830
37195
|
self.abortController.abort(new DOMException('Clean up Apollo session', 'AbortError'));
|
|
36831
37196
|
},
|
|
37197
|
+
}))
|
|
37198
|
+
.actions((self) => ({
|
|
37199
|
+
async afterCreate() {
|
|
37200
|
+
if (util$1.isElectron) {
|
|
37201
|
+
return;
|
|
37202
|
+
}
|
|
37203
|
+
const url = new URL(globalThis.location.href);
|
|
37204
|
+
const apolloFeatures = url.searchParams.get('apolloFeatures');
|
|
37205
|
+
if (!apolloFeatures) {
|
|
37206
|
+
return;
|
|
37207
|
+
}
|
|
37208
|
+
const { assemblyManager } = self;
|
|
37209
|
+
await handleApolloFeaturesUrlParam(apolloFeatures, self.apolloDataStore, assemblyManager, self);
|
|
37210
|
+
await new Promise((resolve) => setTimeout(resolve, 2000));
|
|
37211
|
+
const updatedURL = new URL(globalThis.location.href);
|
|
37212
|
+
updatedURL.searchParams.delete('apolloFeatures');
|
|
37213
|
+
globalThis.history.replaceState(null, '', updatedURL.toString());
|
|
37214
|
+
},
|
|
37215
|
+
afterAttach() {
|
|
37216
|
+
mobxStateTree.addDisposer(self, mobx.autorun((reaction) => {
|
|
37217
|
+
const { focusedViewId, activeWidgets } = self;
|
|
37218
|
+
if (!(focusedViewId && activeWidgets)) {
|
|
37219
|
+
return;
|
|
37220
|
+
}
|
|
37221
|
+
const trackSelector = activeWidgets.get('hierarchicalTrackSelector');
|
|
37222
|
+
// @ts-expect-error Don't have type for track selector
|
|
37223
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
|
37224
|
+
trackSelector?.setView(focusedViewId);
|
|
37225
|
+
reaction.dispose();
|
|
37226
|
+
}));
|
|
37227
|
+
},
|
|
36832
37228
|
}))
|
|
36833
37229
|
.views((self) => {
|
|
36834
37230
|
const superTrackActions = self
|
|
@@ -36960,7 +37356,6 @@
|
|
|
36960
37356
|
}
|
|
36961
37357
|
|
|
36962
37358
|
/* eslint-disable @typescript-eslint/unbound-method */
|
|
36963
|
-
/* eslint-disable @typescript-eslint/no-unnecessary-condition */
|
|
36964
37359
|
/* eslint-disable @typescript-eslint/no-misused-promises */
|
|
36965
37360
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
36966
37361
|
function isApolloMessageData(data) {
|
|
@@ -37148,10 +37543,10 @@
|
|
|
37148
37543
|
});
|
|
37149
37544
|
if (!inWebWorker) {
|
|
37150
37545
|
pluginManager.addToExtensionPoint('Core-extendWorker', (handle) => {
|
|
37151
|
-
if (!('on' in handle && handle.on)) {
|
|
37546
|
+
if (!('on' in handle.client && handle.client.on)) {
|
|
37152
37547
|
return handle;
|
|
37153
37548
|
}
|
|
37154
|
-
handle.on('apollo', async (event) => {
|
|
37549
|
+
handle.client.on('apollo', async (event) => {
|
|
37155
37550
|
if (!isApolloMessageData(event)) {
|
|
37156
37551
|
return;
|
|
37157
37552
|
}
|
|
@@ -37169,7 +37564,7 @@
|
|
|
37169
37564
|
break;
|
|
37170
37565
|
}
|
|
37171
37566
|
const { seq: sequence } = await backendDriver.getSequence(region);
|
|
37172
|
-
handle.
|
|
37567
|
+
handle.worker.postMessage({
|
|
37173
37568
|
apollo,
|
|
37174
37569
|
messageId,
|
|
37175
37570
|
sequence,
|
|
@@ -37187,7 +37582,7 @@
|
|
|
37187
37582
|
break;
|
|
37188
37583
|
}
|
|
37189
37584
|
const regions = await backendDriver.getRegions(assembly);
|
|
37190
|
-
handle.
|
|
37585
|
+
handle.worker.postMessage({
|
|
37191
37586
|
apollo,
|
|
37192
37587
|
messageId,
|
|
37193
37588
|
regions,
|
|
@@ -37205,7 +37600,7 @@
|
|
|
37205
37600
|
break;
|
|
37206
37601
|
}
|
|
37207
37602
|
const refNameAliases = await backendDriver.getRefNameAliases(assembly);
|
|
37208
|
-
handle.
|
|
37603
|
+
handle.worker.postMessage({
|
|
37209
37604
|
apollo,
|
|
37210
37605
|
messageId,
|
|
37211
37606
|
refNameAliases,
|