@apollo-annotation/jbrowse-plugin-apollo 1.0.1 → 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 +826 -433
- package/dist/index.esm.js.map +1 -1
- package/dist/jbrowse-plugin-apollo.cjs.development.js +821 -428
- 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 +859 -467
- 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 +9 -3
- 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.0
|
|
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
|
}
|
|
@@ -23328,7 +23465,7 @@
|
|
|
23328
23465
|
async getRegions(assemblyName) {
|
|
23329
23466
|
const session = util$1.getSession(this.clientStore);
|
|
23330
23467
|
const { assemblyManager } = session;
|
|
23331
|
-
const assembly = await assemblyManager.waitForAssembly(assemblyName);
|
|
23468
|
+
const assembly = (await assemblyManager.waitForAssembly(assemblyName));
|
|
23332
23469
|
if (!assembly) {
|
|
23333
23470
|
throw new Error(`Assembly not found: "${assemblyName}"`);
|
|
23334
23471
|
}
|
|
@@ -23344,7 +23481,7 @@
|
|
|
23344
23481
|
async getRefNameAliases(assemblyName) {
|
|
23345
23482
|
const session = util$1.getSession(this.clientStore);
|
|
23346
23483
|
const { assemblyManager } = session;
|
|
23347
|
-
const assembly = await assemblyManager.waitForAssembly(assemblyName);
|
|
23484
|
+
const assembly = (await assemblyManager.waitForAssembly(assemblyName));
|
|
23348
23485
|
if (!assembly) {
|
|
23349
23486
|
throw new Error(`Assembly not found: "${assemblyName}"`);
|
|
23350
23487
|
}
|
|
@@ -24003,7 +24140,7 @@
|
|
|
24003
24140
|
const localSessionId = makeUserSessionId(token);
|
|
24004
24141
|
const changeManager = new ChangeManager(this.clientStore);
|
|
24005
24142
|
// Save server last change sequence into session storage
|
|
24006
|
-
internetAccount.setLastChangeSequenceNumber(
|
|
24143
|
+
internetAccount.setLastChangeSequenceNumber(message.changeSequence);
|
|
24007
24144
|
if (message.userSessionId === localSessionId) {
|
|
24008
24145
|
return; // we did this change, no need to apply it again
|
|
24009
24146
|
}
|
|
@@ -24051,14 +24188,10 @@
|
|
|
24051
24188
|
const seq = await inFlightPromise;
|
|
24052
24189
|
return { seq, refSeq };
|
|
24053
24190
|
}
|
|
24054
|
-
|
|
24055
|
-
|
|
24056
|
-
|
|
24057
|
-
|
|
24058
|
-
let apolloRefSeq = apolloAssembly.refSeqs.get(refSeq);
|
|
24059
|
-
if (!apolloRefSeq) {
|
|
24060
|
-
apolloRefSeq = apolloAssembly.addRefSeq(refSeq, refName);
|
|
24061
|
-
}
|
|
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);
|
|
24062
24195
|
const clientStoreSequence = apolloRefSeq.getSequence(start, end);
|
|
24063
24196
|
if (clientStoreSequence.length === end - start) {
|
|
24064
24197
|
return { seq: clientStoreSequence, refSeq };
|
|
@@ -24415,7 +24548,7 @@
|
|
|
24415
24548
|
setType(NewFeature[value]);
|
|
24416
24549
|
}
|
|
24417
24550
|
};
|
|
24418
|
-
let submitDisabled =
|
|
24551
|
+
let submitDisabled = error || !(start && end && type);
|
|
24419
24552
|
if ((type === NewFeature.CUSTOM && !customType) ||
|
|
24420
24553
|
(!strand && type === NewFeature.GENE_AND_SUBFEATURES) ||
|
|
24421
24554
|
(!strand && type === NewFeature.TRANSCRIPT_AND_SUBFEATURES)) {
|
|
@@ -24436,7 +24569,7 @@
|
|
|
24436
24569
|
function DeleteAssembly({ changeManager, handleClose, session, }) {
|
|
24437
24570
|
const { internetAccounts } = mobxStateTree.getRoot(session);
|
|
24438
24571
|
const [errorMessage, setErrorMessage] = React.useState('');
|
|
24439
|
-
const [confirmDelete,
|
|
24572
|
+
const [confirmDelete, setConfirmDelete] = React.useState(false);
|
|
24440
24573
|
const [submitted, setSubmitted] = React.useState(false);
|
|
24441
24574
|
const apolloInternetAccounts = internetAccounts.filter((ia) => ia.type === 'ApolloInternetAccount');
|
|
24442
24575
|
if (apolloInternetAccounts.length === 0) {
|
|
@@ -24477,7 +24610,7 @@
|
|
|
24477
24610
|
event.preventDefault();
|
|
24478
24611
|
}
|
|
24479
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: () => {
|
|
24480
|
-
|
|
24613
|
+
setConfirmDelete(!confirmDelete);
|
|
24481
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] }));
|
|
24482
24615
|
}
|
|
24483
24616
|
|
|
@@ -25558,7 +25691,7 @@
|
|
|
25558
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" }) }));
|
|
25559
25692
|
}
|
|
25560
25693
|
function DownloadGFF3({ handleClose, session, assembly: assemblyName, }) {
|
|
25561
|
-
const [includeFASTA,
|
|
25694
|
+
const [includeFASTA, setIncludeFASTA] = React.useState(false);
|
|
25562
25695
|
const [errorMessage, setErrorMessage] = React.useState('');
|
|
25563
25696
|
const { getInternetAccount } = session.apolloDataStore;
|
|
25564
25697
|
const { assemblyManager } = session;
|
|
@@ -25607,7 +25740,7 @@
|
|
|
25607
25740
|
window.open(exportUri, '_blank');
|
|
25608
25741
|
}
|
|
25609
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: () => {
|
|
25610
|
-
|
|
25743
|
+
setIncludeFASTA(!includeFASTA);
|
|
25611
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] }));
|
|
25612
25745
|
}
|
|
25613
25746
|
function getAssemblyGFF3Stream(assemblyName) {
|
|
@@ -25646,6 +25779,49 @@
|
|
|
25646
25779
|
db.close();
|
|
25647
25780
|
}
|
|
25648
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
|
+
|
|
25649
25825
|
function ImportFeatures({ changeManager, handleClose, session, }) {
|
|
25650
25826
|
const { apolloDataStore } = session;
|
|
25651
25827
|
const [file, setFile] = React.useState();
|
|
@@ -26049,7 +26225,7 @@
|
|
|
26049
26225
|
});
|
|
26050
26226
|
return newRow;
|
|
26051
26227
|
}
|
|
26052
|
-
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) => {
|
|
26053
26229
|
setErrorMessage(String(error));
|
|
26054
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] }));
|
|
26055
26231
|
}
|
|
@@ -26359,12 +26535,13 @@
|
|
|
26359
26535
|
const [enableSubmit, setEnableSubmit] = React.useState(false);
|
|
26360
26536
|
const [selectedAssembly, setSelectedAssembly] = React.useState();
|
|
26361
26537
|
const [selectedRows, setSelectedRows] = React.useState([]);
|
|
26362
|
-
const [refNameAliasMap, setRefNameAliasMap] = React.useState(new Map());
|
|
26538
|
+
const [refNameAliasMap, setRefNameAliasMap] = React.useState(() => new Map());
|
|
26363
26539
|
const { apolloDataStore } = session;
|
|
26364
26540
|
const { collaborationServerDriver } = apolloDataStore;
|
|
26365
26541
|
const assemblies = collaborationServerDriver.getAssemblies();
|
|
26366
26542
|
React.useEffect(() => {
|
|
26367
26543
|
if (assemblies.length > 0) {
|
|
26544
|
+
// eslint-disable-next-line @eslint-react/set-state-in-effect
|
|
26368
26545
|
setSelectedAssembly(assemblies[0]);
|
|
26369
26546
|
collaborationServerDriver
|
|
26370
26547
|
.getRefNameAliases(assemblies[0].name)
|
|
@@ -26376,7 +26553,7 @@
|
|
|
26376
26553
|
setErrorMessage('Error fetching refName aliases for assembly');
|
|
26377
26554
|
});
|
|
26378
26555
|
}
|
|
26379
|
-
// eslint-disable-next-line react
|
|
26556
|
+
// eslint-disable-next-line @eslint-react/exhaustive-deps
|
|
26380
26557
|
}, []);
|
|
26381
26558
|
const initializeRefNameAliasMap = (refNameAliasesList) => {
|
|
26382
26559
|
const initialMap = new Map();
|
|
@@ -26761,6 +26938,10 @@
|
|
|
26761
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"
|
|
26762
26939
|
}), 'AccountCircle');
|
|
26763
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
|
+
|
|
26764
26945
|
// Icon source: https://developers.google.com/identity/branding-guidelines
|
|
26765
26946
|
function Google(props) {
|
|
26766
26947
|
const { color } = props;
|
|
@@ -26785,17 +26966,23 @@
|
|
|
26785
26966
|
}));
|
|
26786
26967
|
function GoogleButton(props) {
|
|
26787
26968
|
const { classes } = useStyles$d();
|
|
26788
|
-
const {
|
|
26789
|
-
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 }));
|
|
26790
26971
|
}
|
|
26791
26972
|
function MicrosoftButton(props) {
|
|
26792
26973
|
const { classes } = useStyles$d();
|
|
26793
|
-
const {
|
|
26794
|
-
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 }));
|
|
26795
26976
|
}
|
|
26796
26977
|
function GuestButton(props) {
|
|
26797
26978
|
const { classes } = useStyles$d();
|
|
26798
|
-
|
|
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 }));
|
|
26799
26986
|
}
|
|
26800
26987
|
|
|
26801
26988
|
const useStyles$c = makeStyles()((theme) => ({
|
|
@@ -26807,7 +26994,7 @@
|
|
|
26807
26994
|
const AuthTypeSelector = ({ baseURL, handleClose, name, }) => {
|
|
26808
26995
|
const { classes } = useStyles$c();
|
|
26809
26996
|
const [errorMessage, setErrorMessage] = React.useState('');
|
|
26810
|
-
const [loginTypes, setLoginTypes] = React.useState(
|
|
26997
|
+
const [loginTypes, setLoginTypes] = React.useState(null);
|
|
26811
26998
|
React.useEffect(() => {
|
|
26812
26999
|
const controller = new AbortController();
|
|
26813
27000
|
const { signal } = controller;
|
|
@@ -26821,6 +27008,9 @@
|
|
|
26821
27008
|
}
|
|
26822
27009
|
const data = (await response.json());
|
|
26823
27010
|
setLoginTypes(data);
|
|
27011
|
+
if (data.length === 0) {
|
|
27012
|
+
setErrorMessage('No login types configured');
|
|
27013
|
+
}
|
|
26824
27014
|
}
|
|
26825
27015
|
getAuthTypes().catch((error) => {
|
|
26826
27016
|
if (!isAbortException(error)) {
|
|
@@ -26832,26 +27022,35 @@
|
|
|
26832
27022
|
};
|
|
26833
27023
|
}, [baseURL]);
|
|
26834
27024
|
function handleClick(authType) {
|
|
26835
|
-
|
|
26836
|
-
|
|
26837
|
-
|
|
26838
|
-
|
|
26839
|
-
|
|
26840
|
-
|
|
26841
|
-
|
|
26842
|
-
|
|
26843
|
-
|
|
26844
|
-
}
|
|
26845
|
-
|
|
26846
|
-
|
|
26847
|
-
|
|
26848
|
-
|
|
26849
|
-
|
|
26850
|
-
|
|
26851
|
-
|
|
26852
|
-
|
|
26853
|
-
|
|
26854
|
-
|
|
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: () => {
|
|
26855
27054
|
handleClose();
|
|
26856
27055
|
}, children: "Cancel" }) }), errorMessage ? (jsxRuntime.jsx(material.DialogContent, { children: jsxRuntime.jsx(material.DialogContentText, { color: "error", children: errorMessage }) })) : null] }));
|
|
26857
27056
|
};
|
|
@@ -27047,13 +27246,13 @@
|
|
|
27047
27246
|
},
|
|
27048
27247
|
]);
|
|
27049
27248
|
});
|
|
27050
|
-
if (authType
|
|
27249
|
+
if (authType.needsPopup) {
|
|
27051
27250
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
27052
|
-
self.openAuthWindow(authType, resolve, reject);
|
|
27251
|
+
self.openAuthWindow(authType.name, resolve, reject);
|
|
27053
27252
|
return;
|
|
27054
27253
|
}
|
|
27055
27254
|
const url = new URL('auth/login', baseURL);
|
|
27056
|
-
const searchParams = new URLSearchParams({ type: authType });
|
|
27255
|
+
const searchParams = new URLSearchParams({ type: authType.name });
|
|
27057
27256
|
url.search = searchParams.toString();
|
|
27058
27257
|
const uri = url.toString();
|
|
27059
27258
|
const response = await fetch(uri, { signal: self.controller.signal });
|
|
@@ -27174,7 +27373,7 @@
|
|
|
27174
27373
|
socket.on('COMMON', (message) => {
|
|
27175
27374
|
if ('checkResult' in message) {
|
|
27176
27375
|
if (message.deleted) {
|
|
27177
|
-
deleteCheckResult(message.checkResult._id
|
|
27376
|
+
deleteCheckResult(message.checkResult._id);
|
|
27178
27377
|
}
|
|
27179
27378
|
else {
|
|
27180
27379
|
addCheckResult(message.checkResult);
|
|
@@ -28001,7 +28200,9 @@
|
|
|
28001
28200
|
return newValues;
|
|
28002
28201
|
});
|
|
28003
28202
|
}
|
|
28004
|
-
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) => {
|
|
28005
28206
|
updateValue(idx, editedValue);
|
|
28006
28207
|
}, variant: "outlined", fullWidth: true }), jsxRuntime.jsx(material.IconButton, { "aria-label": "delete", size: "medium", edge: "end", onClick: () => {
|
|
28007
28208
|
deleteValue(idx);
|
|
@@ -28013,7 +28214,9 @@
|
|
|
28013
28214
|
});
|
|
28014
28215
|
|
|
28015
28216
|
function DefaultAttributeViewer({ values }) {
|
|
28016
|
-
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}`))) }));
|
|
28017
28220
|
}
|
|
28018
28221
|
|
|
28019
28222
|
const useStyles$a = makeStyles()((theme) => ({
|
|
@@ -28319,6 +28522,7 @@
|
|
|
28319
28522
|
const { classes } = useStyles$8();
|
|
28320
28523
|
const [panelState, setPanelState] = React.useState(['attributes']);
|
|
28321
28524
|
React.useEffect(() => {
|
|
28525
|
+
// eslint-disable-next-line @eslint-react/set-state-in-effect
|
|
28322
28526
|
setPanelState(['attributes']);
|
|
28323
28527
|
}, [feature]);
|
|
28324
28528
|
if (!(feature && currentAssembly)) {
|
|
@@ -28405,6 +28609,7 @@
|
|
|
28405
28609
|
*/
|
|
28406
28610
|
get minWithChildren() {
|
|
28407
28611
|
var min = self.min;
|
|
28612
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
|
28408
28613
|
var children = self.children;
|
|
28409
28614
|
if (!children) {
|
|
28410
28615
|
return min;
|
|
@@ -28431,6 +28636,7 @@
|
|
|
28431
28636
|
*/
|
|
28432
28637
|
get maxWithChildren() {
|
|
28433
28638
|
var max = self.max;
|
|
28639
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
|
28434
28640
|
var children = self.children;
|
|
28435
28641
|
if (!children) {
|
|
28436
28642
|
return max;
|
|
@@ -28539,6 +28745,7 @@
|
|
|
28539
28745
|
if (!featureTypeOntology.isTypeOf(self.type, 'transcript') && !featureTypeOntology.isTypeOf(self.type, 'pseudogenic_transcript')) {
|
|
28540
28746
|
throw new Error('Only features of type "transcript" or equivalent can calculate CDS locations');
|
|
28541
28747
|
}
|
|
28748
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
|
28542
28749
|
var children = self.children;
|
|
28543
28750
|
if (!children) {
|
|
28544
28751
|
throw new Error('no CDS or exons in transcript');
|
|
@@ -29443,7 +29650,7 @@
|
|
|
29443
29650
|
else {
|
|
29444
29651
|
setSequenceOptions(defaultSequenceOptions);
|
|
29445
29652
|
}
|
|
29446
|
-
// eslint-disable-next-line react
|
|
29653
|
+
// eslint-disable-next-line @eslint-react/exhaustive-deps
|
|
29447
29654
|
}, [feature]);
|
|
29448
29655
|
if (!(currentAssembly && refData)) {
|
|
29449
29656
|
return null;
|
|
@@ -29506,6 +29713,10 @@
|
|
|
29506
29713
|
.join(';'), "(strand=", feature.strand === 1 ? '+' : '-', ";length=", getSequenceLength(sequenceSegments), ")", jsxRuntime.jsx("br", {}), wrapSequence(sequenceSegments, SEQUENCE_WRAP_LENGTH)] })] }));
|
|
29507
29714
|
});
|
|
29508
29715
|
|
|
29716
|
+
var RemoveIcon = /*#__PURE__*/utils.createSvgIcon(/*#__PURE__*/jsxRuntime.jsx("path", {
|
|
29717
|
+
d: "M19 13H5v-2h14z"
|
|
29718
|
+
}), 'Remove');
|
|
29719
|
+
|
|
29509
29720
|
var ContentCopyIcon = /*#__PURE__*/utils.createSvgIcon(/*#__PURE__*/jsxRuntime.jsx("path", {
|
|
29510
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"
|
|
29511
29722
|
}), 'ContentCopy');
|
|
@@ -29514,23 +29725,6 @@
|
|
|
29514
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"
|
|
29515
29726
|
}), 'ContentCut');
|
|
29516
29727
|
|
|
29517
|
-
var RemoveIcon = /*#__PURE__*/utils.createSvgIcon(/*#__PURE__*/jsxRuntime.jsx("path", {
|
|
29518
|
-
d: "M19 13H5v-2h14z"
|
|
29519
|
-
}), 'Remove');
|
|
29520
|
-
|
|
29521
|
-
const StyledTextField = newStyled(NumberTextField)(() => ({
|
|
29522
|
-
'&.MuiFormControl-root': {
|
|
29523
|
-
marginTop: 0,
|
|
29524
|
-
marginBottom: 0,
|
|
29525
|
-
width: '100%',
|
|
29526
|
-
},
|
|
29527
|
-
'& .MuiInputBase-input': {
|
|
29528
|
-
fontSize: 12,
|
|
29529
|
-
height: 20,
|
|
29530
|
-
padding: 1,
|
|
29531
|
-
paddingLeft: 10,
|
|
29532
|
-
},
|
|
29533
|
-
}));
|
|
29534
29728
|
const SequenceContainer = newStyled('div')({
|
|
29535
29729
|
display: 'flex',
|
|
29536
29730
|
justifyContent: 'center',
|
|
@@ -29552,6 +29746,187 @@
|
|
|
29552
29746
|
maxHeight: 30,
|
|
29553
29747
|
},
|
|
29554
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
|
+
}));
|
|
29555
29930
|
const Strand = (props) => {
|
|
29556
29931
|
const { strand } = props;
|
|
29557
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" })) }));
|
|
@@ -29570,7 +29945,6 @@
|
|
|
29570
29945
|
const currentAssembly = session.apolloDataStore.assemblies.get(assembly);
|
|
29571
29946
|
const refData = currentAssembly?.getByRefName(refName);
|
|
29572
29947
|
const { changeManager } = session.apolloDataStore;
|
|
29573
|
-
const seqRef = React.useRef(null);
|
|
29574
29948
|
const { changeInProgress } = session;
|
|
29575
29949
|
if (!refData) {
|
|
29576
29950
|
return null;
|
|
@@ -29997,184 +30371,6 @@
|
|
|
29997
30371
|
},
|
|
29998
30372
|
];
|
|
29999
30373
|
};
|
|
30000
|
-
const getTranslationSequence = () => {
|
|
30001
|
-
let wholeSequence = '';
|
|
30002
|
-
const [firstLocation] = cdsLocations;
|
|
30003
|
-
const sortedCDSLocations = firstLocation.toSorted(({ min: a }, { min: b }) => a - b);
|
|
30004
|
-
for (const loc of sortedCDSLocations) {
|
|
30005
|
-
wholeSequence += refData.getSequence(loc.min, loc.max);
|
|
30006
|
-
}
|
|
30007
|
-
if (strand === -1) {
|
|
30008
|
-
// Original: ACGCAT
|
|
30009
|
-
// Complement: TGCGTA
|
|
30010
|
-
// Reverse complement: ATGCGT
|
|
30011
|
-
wholeSequence = util$1.revcom(wholeSequence);
|
|
30012
|
-
}
|
|
30013
|
-
const elements = [];
|
|
30014
|
-
for (let codonGenomicPos = 0; codonGenomicPos < wholeSequence.length; codonGenomicPos += 3) {
|
|
30015
|
-
const codonSeq = wholeSequence
|
|
30016
|
-
.slice(codonGenomicPos, codonGenomicPos + 3)
|
|
30017
|
-
.toUpperCase();
|
|
30018
|
-
const protein = util$1.defaultCodonTable[codonSeq] || '&';
|
|
30019
|
-
// highlight start codon and stop codons
|
|
30020
|
-
if (codonSeq === 'ATG') {
|
|
30021
|
-
elements.push(jsxRuntime.jsx(material.Typography, { component: 'span', style: {
|
|
30022
|
-
backgroundColor: changeInProgress ? 'lightgray' : 'yellow',
|
|
30023
|
-
cursor: 'pointer',
|
|
30024
|
-
border: '1px solid black',
|
|
30025
|
-
}, onClick: () => {
|
|
30026
|
-
if (changeInProgress) {
|
|
30027
|
-
return;
|
|
30028
|
-
}
|
|
30029
|
-
// NOTE: codonGenomicPos is important here for calculating the genomic location
|
|
30030
|
-
// of the start codon. We are using the codonGenomicPos as the key in the typography
|
|
30031
|
-
// elements to maintain the genomic postion of the codon start
|
|
30032
|
-
const startCodonGenomicLocation = getCodonGenomicLocation(codonGenomicPos);
|
|
30033
|
-
if (startCodonGenomicLocation !== cdsMin && strand === 1) {
|
|
30034
|
-
updateCDSLocation(cdsMin, startCodonGenomicLocation, feature, true);
|
|
30035
|
-
}
|
|
30036
|
-
if (startCodonGenomicLocation !== cdsMax && strand === -1) {
|
|
30037
|
-
updateCDSLocation(cdsMax, startCodonGenomicLocation, feature, false);
|
|
30038
|
-
}
|
|
30039
|
-
}, children: protein }, codonGenomicPos));
|
|
30040
|
-
}
|
|
30041
|
-
else if (['TAA', 'TAG', 'TGA'].includes(codonSeq)) {
|
|
30042
|
-
elements.push(jsxRuntime.jsx(material.Typography, { style: { backgroundColor: 'red', color: 'white' }, component: 'span', children: protein }, codonGenomicPos));
|
|
30043
|
-
}
|
|
30044
|
-
else {
|
|
30045
|
-
elements.push(
|
|
30046
|
-
// Pass the codonGenomicPos as the key to maintain the genomic position of the codon
|
|
30047
|
-
jsxRuntime.jsx(material.Typography, { component: 'span', children: protein }, codonGenomicPos));
|
|
30048
|
-
}
|
|
30049
|
-
}
|
|
30050
|
-
return elements;
|
|
30051
|
-
};
|
|
30052
|
-
// Codon position is the index of the start codon in the CDS genomic sequence
|
|
30053
|
-
// Calculate the genomic location of the start codon based on the codon position in the CDS
|
|
30054
|
-
const getCodonGenomicLocation = (codonGenomicPosition) => {
|
|
30055
|
-
const [firstLocation] = cdsLocations;
|
|
30056
|
-
let cdsLen = 0;
|
|
30057
|
-
const sortedCDSLocations = firstLocation.toSorted(({ min: a }, { min: b }) => a - b);
|
|
30058
|
-
// Suppose CDS locations are [{min: 0, max: 10}, {min: 20, max: 30}, {min: 40, max: 50}]
|
|
30059
|
-
// and codonGenomicPosition is 25
|
|
30060
|
-
// ((10 - 0) + (30 - 20) + (50 - 40)) > 25
|
|
30061
|
-
// So, start codon is in (40, 50)
|
|
30062
|
-
// 40 + (25-20) = 45 is the genomic location of the start codon
|
|
30063
|
-
if (strand === 1) {
|
|
30064
|
-
for (const loc of sortedCDSLocations) {
|
|
30065
|
-
const locLength = loc.max - loc.min;
|
|
30066
|
-
if (cdsLen + locLength > codonGenomicPosition) {
|
|
30067
|
-
return loc.min + (codonGenomicPosition - cdsLen);
|
|
30068
|
-
}
|
|
30069
|
-
cdsLen += locLength;
|
|
30070
|
-
}
|
|
30071
|
-
}
|
|
30072
|
-
else if (strand === -1) {
|
|
30073
|
-
for (let i = sortedCDSLocations.length - 1; i >= 0; i--) {
|
|
30074
|
-
const loc = sortedCDSLocations[i];
|
|
30075
|
-
const locLength = loc.max - loc.min;
|
|
30076
|
-
if (cdsLen + locLength > codonGenomicPosition) {
|
|
30077
|
-
return loc.max - (codonGenomicPosition - cdsLen);
|
|
30078
|
-
}
|
|
30079
|
-
cdsLen += locLength;
|
|
30080
|
-
}
|
|
30081
|
-
}
|
|
30082
|
-
if (strand === 1) {
|
|
30083
|
-
return cdsMin;
|
|
30084
|
-
}
|
|
30085
|
-
return cdsMax;
|
|
30086
|
-
};
|
|
30087
|
-
const trimTranslationSequence = () => {
|
|
30088
|
-
const sequenceElements = getTranslationSequence();
|
|
30089
|
-
const translationSequence = sequenceElements
|
|
30090
|
-
.map((el) => el.props.children)
|
|
30091
|
-
.join('');
|
|
30092
|
-
if (translationSequence.startsWith('M') &&
|
|
30093
|
-
translationSequence.endsWith('*')) {
|
|
30094
|
-
return;
|
|
30095
|
-
}
|
|
30096
|
-
// NOTE: We are maintaining the genomic location of the codon start as the "key"
|
|
30097
|
-
// in typography elements. See getTranslationSequence function
|
|
30098
|
-
const translSeqCodonStartGenomicPosArr = [];
|
|
30099
|
-
for (const el of sequenceElements) {
|
|
30100
|
-
translSeqCodonStartGenomicPosArr.push({
|
|
30101
|
-
codonGenomicPos: el.key,
|
|
30102
|
-
sequenceLetter: el.props.children,
|
|
30103
|
-
});
|
|
30104
|
-
}
|
|
30105
|
-
if (translSeqCodonStartGenomicPosArr.length === 0) {
|
|
30106
|
-
return;
|
|
30107
|
-
}
|
|
30108
|
-
// Trim any sequence before first start codon and after stop codon
|
|
30109
|
-
const startCodonIndex = translationSequence.indexOf('M');
|
|
30110
|
-
const stopCodonIndex = translationSequence.indexOf('*');
|
|
30111
|
-
const startCodonPos = translSeqCodonStartGenomicPosArr[startCodonIndex].codonGenomicPos;
|
|
30112
|
-
const stopCodonPos = translSeqCodonStartGenomicPosArr[stopCodonIndex].codonGenomicPos;
|
|
30113
|
-
if (!startCodonPos || !stopCodonPos) {
|
|
30114
|
-
return;
|
|
30115
|
-
}
|
|
30116
|
-
const startCodonGenomicLoc = getCodonGenomicLocation(startCodonPos);
|
|
30117
|
-
let stopCodonGenomicLoc = getCodonGenomicLocation(stopCodonPos);
|
|
30118
|
-
if (strand === 1) {
|
|
30119
|
-
if (startCodonGenomicLoc > stopCodonGenomicLoc) {
|
|
30120
|
-
notify('Start codon genomic location should be less than stop codon genomic location', 'error');
|
|
30121
|
-
return;
|
|
30122
|
-
}
|
|
30123
|
-
let promise;
|
|
30124
|
-
stopCodonGenomicLoc += 3; // move to end of stop codon
|
|
30125
|
-
if (startCodonGenomicLoc !== cdsMin) {
|
|
30126
|
-
promise = new Promise((resolve) => {
|
|
30127
|
-
updateCDSLocation(cdsMin, startCodonGenomicLoc, feature, true, () => {
|
|
30128
|
-
resolve(true);
|
|
30129
|
-
});
|
|
30130
|
-
});
|
|
30131
|
-
}
|
|
30132
|
-
if (stopCodonGenomicLoc !== cdsMax) {
|
|
30133
|
-
if (promise) {
|
|
30134
|
-
void promise.then(() => {
|
|
30135
|
-
updateCDSLocation(cdsMax, stopCodonGenomicLoc, feature, false);
|
|
30136
|
-
});
|
|
30137
|
-
}
|
|
30138
|
-
else {
|
|
30139
|
-
updateCDSLocation(cdsMax, stopCodonGenomicLoc, feature, false);
|
|
30140
|
-
}
|
|
30141
|
-
}
|
|
30142
|
-
}
|
|
30143
|
-
if (strand === -1) {
|
|
30144
|
-
// reverse strand
|
|
30145
|
-
if (startCodonGenomicLoc < stopCodonGenomicLoc) {
|
|
30146
|
-
notify('Start codon genomic location should be less than stop codon genomic location', 'error');
|
|
30147
|
-
return;
|
|
30148
|
-
}
|
|
30149
|
-
let promise;
|
|
30150
|
-
stopCodonGenomicLoc -= 3; // move to end of stop codon
|
|
30151
|
-
if (startCodonGenomicLoc !== cdsMax) {
|
|
30152
|
-
promise = new Promise((resolve) => {
|
|
30153
|
-
updateCDSLocation(cdsMax, startCodonGenomicLoc, feature, false, () => {
|
|
30154
|
-
resolve(true);
|
|
30155
|
-
});
|
|
30156
|
-
});
|
|
30157
|
-
}
|
|
30158
|
-
if (stopCodonGenomicLoc !== cdsMin) {
|
|
30159
|
-
if (promise) {
|
|
30160
|
-
void promise.then(() => {
|
|
30161
|
-
updateCDSLocation(cdsMin, stopCodonGenomicLoc, feature, true);
|
|
30162
|
-
});
|
|
30163
|
-
}
|
|
30164
|
-
else {
|
|
30165
|
-
updateCDSLocation(cdsMin, stopCodonGenomicLoc, feature, true);
|
|
30166
|
-
}
|
|
30167
|
-
}
|
|
30168
|
-
}
|
|
30169
|
-
notify('Translation sequence trimmed to start and stop codons', 'success');
|
|
30170
|
-
};
|
|
30171
|
-
const onCopyClick = () => {
|
|
30172
|
-
const seqDiv = seqRef.current;
|
|
30173
|
-
if (!seqDiv) {
|
|
30174
|
-
return;
|
|
30175
|
-
}
|
|
30176
|
-
void copyToClipboard(seqDiv);
|
|
30177
|
-
};
|
|
30178
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) => {
|
|
30179
30375
|
return updateCDSLocation(cdsMin, newLocation - 1, feature, true);
|
|
30180
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) => {
|
|
@@ -30184,8 +30380,12 @@
|
|
|
30184
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) => {
|
|
30185
30381
|
return updateCDSLocation(cdsMin, newLocation - 1, feature, true);
|
|
30186
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) => {
|
|
30187
|
-
return (
|
|
30188
|
-
|
|
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) => {
|
|
30189
30389
|
return handleExonLocationChange(loc.min, newLocation - 1, feature, true);
|
|
30190
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) => {
|
|
30191
30391
|
return handleExonLocationChange(loc.max, newLocation, feature, false);
|
|
@@ -30194,14 +30394,10 @@
|
|
|
30194
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) => {
|
|
30195
30395
|
return handleExonLocationChange(loc.min, newLocation - 1, feature, true);
|
|
30196
30396
|
}, disabled: changeInProgress }) })), jsxRuntime.jsx(material.Grid, { size: 1, children: index !== transcriptExonParts.length - 1 &&
|
|
30197
|
-
getThreePrimeSpliceSite(loc, index).map((site, idx) => (jsxRuntime.jsx(material.Typography
|
|
30198
|
-
|
|
30199
|
-
|
|
30200
|
-
|
|
30201
|
-
flexDirection: 'row',
|
|
30202
|
-
alignItems: 'center',
|
|
30203
|
-
gap: 10,
|
|
30204
|
-
}, 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 }))] }));
|
|
30205
30401
|
});
|
|
30206
30402
|
|
|
30207
30403
|
const HeaderTableCell = newStyled(material.TableCell)(() => ({
|
|
@@ -30238,7 +30434,7 @@
|
|
|
30238
30434
|
const { assembly, feature, refName } = model;
|
|
30239
30435
|
React.useEffect(() => {
|
|
30240
30436
|
setPanelState(DEFAULT_PANELS);
|
|
30241
|
-
// eslint-disable-next-line react
|
|
30437
|
+
// eslint-disable-next-line @eslint-react/exhaustive-deps
|
|
30242
30438
|
}, [feature]);
|
|
30243
30439
|
const session = util$1.getSession(model);
|
|
30244
30440
|
const { pluginManager } = util$1.getEnv(session);
|
|
@@ -30297,8 +30493,8 @@
|
|
|
30297
30493
|
typeName: 'TypeChange',
|
|
30298
30494
|
changedIds: [featureId],
|
|
30299
30495
|
featureId,
|
|
30300
|
-
oldType
|
|
30301
|
-
newType
|
|
30496
|
+
oldType,
|
|
30497
|
+
newType,
|
|
30302
30498
|
assembly: feature.assemblyId,
|
|
30303
30499
|
});
|
|
30304
30500
|
return changeManager.submit(change);
|
|
@@ -30394,7 +30590,7 @@
|
|
|
30394
30590
|
if (initialValue !== value) {
|
|
30395
30591
|
setValue(initialValue);
|
|
30396
30592
|
}
|
|
30397
|
-
// eslint-disable-next-line react
|
|
30593
|
+
// eslint-disable-next-line @eslint-react/exhaustive-deps
|
|
30398
30594
|
}, [initialValue]);
|
|
30399
30595
|
React.useEffect(() => {
|
|
30400
30596
|
if (blur) {
|
|
@@ -31243,8 +31439,9 @@
|
|
|
31243
31439
|
const [top, left, width] = getFeatureBox(display, gene, row, block);
|
|
31244
31440
|
const height = getRowCount$2(display, gene) * apolloRowHeight;
|
|
31245
31441
|
if (width > 2) {
|
|
31246
|
-
|
|
31247
|
-
|
|
31442
|
+
const selectedColor = configuration.readConfObject(session.getPluginConfiguration(), 'geneBackgroundColor', {
|
|
31443
|
+
featureType: gene.type,
|
|
31444
|
+
}) ?? material.alpha(theme.palette.background.paper, 0.6);
|
|
31248
31445
|
ctx.fillStyle = selectedColor;
|
|
31249
31446
|
ctx.fillRect(left, top, width, height);
|
|
31250
31447
|
}
|
|
@@ -31517,7 +31714,7 @@
|
|
|
31517
31714
|
}
|
|
31518
31715
|
return layout;
|
|
31519
31716
|
}
|
|
31520
|
-
function getContextMenuItems$1(display,
|
|
31717
|
+
function getContextMenuItems$1(display, transcript) {
|
|
31521
31718
|
const { changeManager, regions, selectedFeature, session } = display;
|
|
31522
31719
|
const [region] = regions;
|
|
31523
31720
|
const currentAssemblyId = display.getAssemblyId(region.assemblyName);
|
|
@@ -31527,7 +31724,7 @@
|
|
|
31527
31724
|
label: 'Open transcript editor',
|
|
31528
31725
|
onClick: () => {
|
|
31529
31726
|
const apolloTranscriptWidget = session.addWidget('ApolloTranscriptDetails', 'apolloTranscriptDetails', {
|
|
31530
|
-
feature,
|
|
31727
|
+
feature: transcript,
|
|
31531
31728
|
assembly: currentAssemblyId,
|
|
31532
31729
|
changeManager,
|
|
31533
31730
|
refName: region.refName,
|
|
@@ -31547,7 +31744,7 @@
|
|
|
31547
31744
|
doneCallback();
|
|
31548
31745
|
},
|
|
31549
31746
|
changeManager,
|
|
31550
|
-
sourceFeature:
|
|
31747
|
+
sourceFeature: transcript,
|
|
31551
31748
|
sourceAssemblyId: currentAssemblyId,
|
|
31552
31749
|
selectedFeature,
|
|
31553
31750
|
setSelectedFeature: (feature) => {
|
|
@@ -31567,7 +31764,7 @@
|
|
|
31567
31764
|
doneCallback();
|
|
31568
31765
|
},
|
|
31569
31766
|
changeManager,
|
|
31570
|
-
sourceFeature:
|
|
31767
|
+
sourceFeature: transcript,
|
|
31571
31768
|
sourceAssemblyId: currentAssemblyId,
|
|
31572
31769
|
selectedFeature,
|
|
31573
31770
|
setSelectedFeature: (feature) => {
|
|
@@ -31577,6 +31774,31 @@
|
|
|
31577
31774
|
]);
|
|
31578
31775
|
},
|
|
31579
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
|
+
}
|
|
31580
31802
|
return menuItems;
|
|
31581
31803
|
}
|
|
31582
31804
|
// False positive here, none of these functions use "this"
|
|
@@ -31763,7 +31985,7 @@
|
|
|
31763
31985
|
letterUpper === 'C' ||
|
|
31764
31986
|
letterUpper === 'G' ||
|
|
31765
31987
|
letterUpper === 'T') {
|
|
31766
|
-
return theme.palette.bases[letterUpper].main
|
|
31988
|
+
return theme.palette.bases[letterUpper].main;
|
|
31767
31989
|
}
|
|
31768
31990
|
return 'lightgray';
|
|
31769
31991
|
}
|
|
@@ -31860,8 +32082,7 @@
|
|
|
31860
32082
|
return internetAccounts.find((ia) => configuration.getConf(ia, 'internetAccountId') === internetAccountConfigId);
|
|
31861
32083
|
},
|
|
31862
32084
|
get changeManager() {
|
|
31863
|
-
return self.session.apolloDataStore
|
|
31864
|
-
.changeManager;
|
|
32085
|
+
return self.session.apolloDataStore.changeManager;
|
|
31865
32086
|
},
|
|
31866
32087
|
getAssemblyId(assemblyName) {
|
|
31867
32088
|
const { assemblyManager } = self.session;
|
|
@@ -31872,12 +32093,10 @@
|
|
|
31872
32093
|
return assembly.name;
|
|
31873
32094
|
},
|
|
31874
32095
|
get selectedFeature() {
|
|
31875
|
-
return self.session
|
|
31876
|
-
.apolloSelectedFeature;
|
|
32096
|
+
return self.session.apolloSelectedFeature;
|
|
31877
32097
|
},
|
|
31878
32098
|
get hoveredFeature() {
|
|
31879
|
-
return self.session
|
|
31880
|
-
.apolloHoveredFeature;
|
|
32099
|
+
return self.session.apolloHoveredFeature;
|
|
31881
32100
|
},
|
|
31882
32101
|
}))
|
|
31883
32102
|
.actions((self) => ({
|
|
@@ -31922,8 +32141,11 @@
|
|
|
31922
32141
|
const { filteredFeatureTypes, trackMenuItems: superTrackMenuItems } = self;
|
|
31923
32142
|
return {
|
|
31924
32143
|
trackMenuItems() {
|
|
31925
|
-
const { graphical, table, showCheckResults } = self;
|
|
31926
|
-
|
|
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 = [
|
|
31927
32149
|
...superTrackMenuItems(),
|
|
31928
32150
|
{
|
|
31929
32151
|
type: 'subMenu',
|
|
@@ -31975,7 +32197,7 @@
|
|
|
31975
32197
|
{
|
|
31976
32198
|
label: 'Filter features by type',
|
|
31977
32199
|
onClick: () => {
|
|
31978
|
-
const session = self
|
|
32200
|
+
const { session } = self;
|
|
31979
32201
|
self.session.queueDialog((doneCallback) => [
|
|
31980
32202
|
FilterFeatures,
|
|
31981
32203
|
{
|
|
@@ -31991,76 +32213,93 @@
|
|
|
31991
32213
|
]);
|
|
31992
32214
|
},
|
|
31993
32215
|
},
|
|
31994
|
-
|
|
31995
|
-
|
|
31996
|
-
|
|
32216
|
+
];
|
|
32217
|
+
if (backendDriver instanceof LocalDriver) {
|
|
32218
|
+
items.push({
|
|
32219
|
+
label: 'Import annotations',
|
|
32220
|
+
icon: InputIcon,
|
|
31997
32221
|
onClick: () => {
|
|
31998
|
-
const [region] = self.regions;
|
|
31999
|
-
const { assemblyName } = region;
|
|
32000
|
-
const assembly = self.getAssemblyId(assemblyName);
|
|
32001
|
-
if (!assembly) {
|
|
32002
|
-
return;
|
|
32003
|
-
}
|
|
32004
|
-
const session = self.session;
|
|
32005
32222
|
session.queueDialog((doneCallback) => [
|
|
32006
|
-
|
|
32223
|
+
ImportAnnotations,
|
|
32007
32224
|
{
|
|
32008
32225
|
session,
|
|
32226
|
+
assemblyName,
|
|
32009
32227
|
handleClose: () => {
|
|
32010
32228
|
doneCallback();
|
|
32011
32229
|
},
|
|
32012
|
-
assembly,
|
|
32013
32230
|
},
|
|
32014
32231
|
]);
|
|
32015
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
|
+
]);
|
|
32016
32256
|
},
|
|
32017
|
-
|
|
32018
|
-
|
|
32019
|
-
|
|
32020
|
-
|
|
32021
|
-
|
|
32022
|
-
|
|
32023
|
-
|
|
32024
|
-
|
|
32025
|
-
|
|
32026
|
-
|
|
32027
|
-
|
|
32028
|
-
|
|
32029
|
-
|
|
32030
|
-
|
|
32031
|
-
|
|
32032
|
-
|
|
32033
|
-
|
|
32034
|
-
},
|
|
32035
|
-
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();
|
|
32036
32274
|
},
|
|
32037
|
-
|
|
32038
|
-
|
|
32275
|
+
assembly,
|
|
32276
|
+
},
|
|
32277
|
+
]);
|
|
32039
32278
|
},
|
|
32040
|
-
|
|
32041
|
-
|
|
32042
|
-
|
|
32043
|
-
|
|
32044
|
-
|
|
32045
|
-
|
|
32046
|
-
|
|
32047
|
-
|
|
32048
|
-
|
|
32049
|
-
|
|
32050
|
-
|
|
32051
|
-
|
|
32052
|
-
|
|
32053
|
-
|
|
32054
|
-
|
|
32055
|
-
|
|
32056
|
-
|
|
32057
|
-
},
|
|
32058
|
-
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();
|
|
32059
32296
|
},
|
|
32060
|
-
|
|
32061
|
-
|
|
32297
|
+
assembly,
|
|
32298
|
+
},
|
|
32299
|
+
]);
|
|
32062
32300
|
},
|
|
32063
|
-
|
|
32301
|
+
});
|
|
32302
|
+
return items;
|
|
32064
32303
|
},
|
|
32065
32304
|
};
|
|
32066
32305
|
})
|
|
@@ -33126,8 +33365,7 @@
|
|
|
33126
33365
|
return internetAccounts.find((ia) => configuration.getConf(ia, 'internetAccountId') === internetAccountConfigId);
|
|
33127
33366
|
},
|
|
33128
33367
|
get changeManager() {
|
|
33129
|
-
return self.session.apolloDataStore
|
|
33130
|
-
.changeManager;
|
|
33368
|
+
return self.session.apolloDataStore.changeManager;
|
|
33131
33369
|
},
|
|
33132
33370
|
getAssemblyId(assemblyName) {
|
|
33133
33371
|
const { assemblyManager } = self.session;
|
|
@@ -33138,12 +33376,10 @@
|
|
|
33138
33376
|
return assembly.name;
|
|
33139
33377
|
},
|
|
33140
33378
|
get selectedFeature() {
|
|
33141
|
-
return self.session
|
|
33142
|
-
.apolloSelectedFeature;
|
|
33379
|
+
return self.session.apolloSelectedFeature;
|
|
33143
33380
|
},
|
|
33144
33381
|
get hoveredFeature() {
|
|
33145
|
-
return self.session
|
|
33146
|
-
.apolloHoveredFeature;
|
|
33382
|
+
return self.session.apolloHoveredFeature;
|
|
33147
33383
|
},
|
|
33148
33384
|
get height() {
|
|
33149
33385
|
const { sequenceRowHeight } = self;
|
|
@@ -33355,11 +33591,9 @@
|
|
|
33355
33591
|
onUpdate(newForms);
|
|
33356
33592
|
setExcludedTranscripts(newForms);
|
|
33357
33593
|
};
|
|
33358
|
-
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) => (
|
|
33359
|
-
// eslint-disable-next-line react/jsx-key
|
|
33360
|
-
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: () => {
|
|
33361
33595
|
handleChange(item);
|
|
33362
|
-
}, slotProps: { input: { 'aria-label': 'controlled' } } }), label: item }))) }) }) })] }) }));
|
|
33596
|
+
}, slotProps: { input: { 'aria-label': 'controlled' } } }), label: item }, item))) }) }) })] }) }));
|
|
33363
33597
|
});
|
|
33364
33598
|
|
|
33365
33599
|
let forwardFillLight = null;
|
|
@@ -34205,8 +34439,7 @@
|
|
|
34205
34439
|
return internetAccounts.find((ia) => configuration.getConf(ia, 'internetAccountId') === internetAccountConfigId);
|
|
34206
34440
|
},
|
|
34207
34441
|
get changeManager() {
|
|
34208
|
-
return self.session.apolloDataStore
|
|
34209
|
-
.changeManager;
|
|
34442
|
+
return self.session.apolloDataStore.changeManager;
|
|
34210
34443
|
},
|
|
34211
34444
|
getAssemblyId(assemblyName) {
|
|
34212
34445
|
const { assemblyManager } = self.session;
|
|
@@ -34217,12 +34450,10 @@
|
|
|
34217
34450
|
return assembly.name;
|
|
34218
34451
|
},
|
|
34219
34452
|
get selectedFeature() {
|
|
34220
|
-
return self.session
|
|
34221
|
-
.apolloSelectedFeature;
|
|
34453
|
+
return self.session.apolloSelectedFeature;
|
|
34222
34454
|
},
|
|
34223
34455
|
get hoveredFeature() {
|
|
34224
|
-
return self.session
|
|
34225
|
-
.apolloHoveredFeature;
|
|
34456
|
+
return self.session.apolloHoveredFeature;
|
|
34226
34457
|
},
|
|
34227
34458
|
}))
|
|
34228
34459
|
.actions((self) => ({
|
|
@@ -34350,7 +34581,7 @@
|
|
|
34350
34581
|
{
|
|
34351
34582
|
label: 'Filter features by type',
|
|
34352
34583
|
onClick: () => {
|
|
34353
|
-
const session = self
|
|
34584
|
+
const { session } = self;
|
|
34354
34585
|
self.session.queueDialog((doneCallback) => [
|
|
34355
34586
|
FilterFeatures,
|
|
34356
34587
|
{
|
|
@@ -34788,17 +35019,12 @@
|
|
|
34788
35019
|
if (!featureTypeOntology) {
|
|
34789
35020
|
throw new Error('featureTypeOntology is undefined');
|
|
34790
35021
|
}
|
|
34791
|
-
|
|
34792
|
-
|
|
34793
|
-
foundFeature = layoutRow.find((f) => f.feature.type == 'exon' &&
|
|
35022
|
+
const foundFeature = self.geneTrackRowNums.includes(row)
|
|
35023
|
+
? layoutRow.find((f) => f.feature.type == 'exon' &&
|
|
34794
35024
|
bp >= f.feature.min &&
|
|
34795
|
-
bp <= f.feature.max)
|
|
34796
|
-
|
|
34797
|
-
|
|
34798
|
-
}
|
|
34799
|
-
}
|
|
34800
|
-
else {
|
|
34801
|
-
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) => {
|
|
34802
35028
|
const { feature } = f;
|
|
34803
35029
|
const featureID = feature.attributes.get('gff_id')?.toString();
|
|
34804
35030
|
const isTranscript = featureTypeOntology.isTypeOf(feature.type, 'transcript');
|
|
@@ -34820,7 +35046,6 @@
|
|
|
34820
35046
|
}
|
|
34821
35047
|
return false;
|
|
34822
35048
|
});
|
|
34823
|
-
}
|
|
34824
35049
|
if (!foundFeature) {
|
|
34825
35050
|
return mousePosition;
|
|
34826
35051
|
}
|
|
@@ -35144,26 +35369,32 @@
|
|
|
35144
35369
|
const apolloAssembly = apolloSessionModel.apolloDataStore.assemblies.get(assembly.name);
|
|
35145
35370
|
const refSeq = apolloAssembly?.refSeqs.get(refSeqId);
|
|
35146
35371
|
const features = refSeq?.getFeatures(region.start, region.end);
|
|
35147
|
-
const getDestinationFeatures = () => {
|
|
35148
|
-
const filteredFeatures = [];
|
|
35149
|
-
for (const f of features ?? []) {
|
|
35150
|
-
if (f.min > region.end || f.max < region.start) {
|
|
35151
|
-
continue;
|
|
35152
|
-
}
|
|
35153
|
-
// Destination feature should be of type gene
|
|
35154
|
-
if (featureTypeOntology?.isTypeOf(f.type, 'gene')) {
|
|
35155
|
-
const featureSnapshot = mobxStateTree.getSnapshot(f);
|
|
35156
|
-
filteredFeatures.push(featureSnapshot);
|
|
35157
|
-
}
|
|
35158
|
-
}
|
|
35159
|
-
return filteredFeatures;
|
|
35160
|
-
};
|
|
35161
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
|
+
};
|
|
35162
35387
|
setErrorMessage('');
|
|
35163
|
-
const
|
|
35164
|
-
setDestinationFeatures(
|
|
35165
|
-
setSelectedDestinationFeature(
|
|
35166
|
-
}, [
|
|
35388
|
+
const destinationFeatures = getDestinationFeatures();
|
|
35389
|
+
setDestinationFeatures(destinationFeatures);
|
|
35390
|
+
setSelectedDestinationFeature(destinationFeatures[0]);
|
|
35391
|
+
}, [
|
|
35392
|
+
checkedChildrens,
|
|
35393
|
+
featureTypeOntology,
|
|
35394
|
+
features,
|
|
35395
|
+
parentFeatureChecked,
|
|
35396
|
+
region,
|
|
35397
|
+
]);
|
|
35167
35398
|
const handleParentFeatureCheck = (event) => {
|
|
35168
35399
|
const isChecked = event.target.checked;
|
|
35169
35400
|
setParentFeatureChecked(isChecked);
|
|
@@ -35443,8 +35674,21 @@
|
|
|
35443
35674
|
getAnnotationFeature(jbrowseFeature, refSeqId) {
|
|
35444
35675
|
const start = jbrowseFeature.get('start');
|
|
35445
35676
|
const end = jbrowseFeature.get('end');
|
|
35446
|
-
const strand = jbrowseFeature.get('strand');
|
|
35447
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');
|
|
35448
35692
|
const cigarData = jbrowseFeature.get('CIGAR');
|
|
35449
35693
|
const ops = parseCigar(cigarData);
|
|
35450
35694
|
let position = start;
|
|
@@ -35460,9 +35704,7 @@
|
|
|
35460
35704
|
case 'M':
|
|
35461
35705
|
case '=':
|
|
35462
35706
|
case 'X': {
|
|
35463
|
-
|
|
35464
|
-
currentExonStart = position;
|
|
35465
|
-
}
|
|
35707
|
+
currentExonStart ??= position;
|
|
35466
35708
|
position += len;
|
|
35467
35709
|
break;
|
|
35468
35710
|
}
|
|
@@ -35888,7 +36130,7 @@
|
|
|
35888
36130
|
: undefined, menuItems: contextMenuItems })] }))] }));
|
|
35889
36131
|
});
|
|
35890
36132
|
|
|
35891
|
-
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, }) {
|
|
35892
36134
|
const { apolloRowHeight, highestRow, showFeatureLabels } = model;
|
|
35893
36135
|
const featureLabelSpacer = showFeatureLabels ? 2 : 1;
|
|
35894
36136
|
return (jsxRuntime.jsx("div", { style: {
|
|
@@ -35960,8 +36202,7 @@
|
|
|
35960
36202
|
regionNumber: idx,
|
|
35961
36203
|
})?.offsetPx ?? 0) - lgv.offsetPx;
|
|
35962
36204
|
const [feature] = checkResult.featureIds;
|
|
35963
|
-
if (!feature ||
|
|
35964
|
-
!feature.parent ||
|
|
36205
|
+
if (!feature?.parent ||
|
|
35965
36206
|
!looksLikeGene(feature.parent, session)) {
|
|
35966
36207
|
return null;
|
|
35967
36208
|
}
|
|
@@ -36229,18 +36470,15 @@
|
|
|
36229
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"
|
|
36230
36471
|
}), 'Save');
|
|
36231
36472
|
|
|
36232
|
-
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
|
36233
36473
|
/* eslint-disable @typescript-eslint/no-confusing-void-expression */
|
|
36234
36474
|
const ApolloJobModel = mobxStateTree.types
|
|
36235
36475
|
.model('JobsManager', {})
|
|
36236
36476
|
.views((self) => ({
|
|
36237
36477
|
get jobStatusWidget() {
|
|
36238
36478
|
const { widgets } = util$1.getSession(self);
|
|
36239
|
-
|
|
36240
|
-
if (!jobStatusWidget) {
|
|
36479
|
+
const jobStatusWidget = widgets.get('JobsList') ??
|
|
36241
36480
|
// @ts-expect-error: addWidget function not detected on the session
|
|
36242
|
-
|
|
36243
|
-
}
|
|
36481
|
+
util$1.getSession(self).addWidget('JobsListWidget', 'JobsList');
|
|
36244
36482
|
return jobStatusWidget;
|
|
36245
36483
|
},
|
|
36246
36484
|
}))
|
|
@@ -36519,19 +36757,15 @@
|
|
|
36519
36757
|
continue;
|
|
36520
36758
|
}
|
|
36521
36759
|
const { assemblyName, refName } = region;
|
|
36522
|
-
|
|
36523
|
-
|
|
36524
|
-
assembly = self.assemblies.put({ _id: assemblyName, refSeqs: {} });
|
|
36525
|
-
}
|
|
36760
|
+
const assembly = self.assemblies.get(assemblyName) ??
|
|
36761
|
+
self.assemblies.put({ _id: assemblyName, refSeqs: {} });
|
|
36526
36762
|
const [firstFeature] = features;
|
|
36527
|
-
|
|
36528
|
-
|
|
36529
|
-
ref = assembly.refSeqs.put({
|
|
36763
|
+
const ref = assembly.refSeqs.get(firstFeature.refSeq) ??
|
|
36764
|
+
assembly.refSeqs.put({
|
|
36530
36765
|
_id: firstFeature.refSeq,
|
|
36531
36766
|
name: refName,
|
|
36532
36767
|
features: {},
|
|
36533
36768
|
});
|
|
36534
|
-
}
|
|
36535
36769
|
for (const feature of features) {
|
|
36536
36770
|
if (!ref.features.has(feature._id)) {
|
|
36537
36771
|
ref.features.put(feature);
|
|
@@ -36548,24 +36782,153 @@
|
|
|
36548
36782
|
}
|
|
36549
36783
|
const { refSeq, seq } = yield backendDriver.getSequence(region);
|
|
36550
36784
|
const { assemblyName, end, refName, start } = region;
|
|
36551
|
-
|
|
36552
|
-
|
|
36553
|
-
|
|
36554
|
-
|
|
36555
|
-
let ref = assembly.refSeqs.get(refSeq);
|
|
36556
|
-
if (!ref) {
|
|
36557
|
-
ref = assembly.refSeqs.put({
|
|
36558
|
-
_id: refSeq,
|
|
36559
|
-
name: refName,
|
|
36560
|
-
sequence: [],
|
|
36561
|
-
});
|
|
36562
|
-
}
|
|
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: [] });
|
|
36563
36789
|
ref.addSequence({ start, stop: end, sequence: seq });
|
|
36564
36790
|
}
|
|
36565
36791
|
}),
|
|
36566
36792
|
}));
|
|
36567
36793
|
}
|
|
36568
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
|
+
|
|
36569
36932
|
/* eslint-disable @typescript-eslint/no-unnecessary-condition */
|
|
36570
36933
|
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
|
36571
36934
|
function extendSession(pluginManager, sessionModel) {
|
|
@@ -36651,8 +37014,7 @@
|
|
|
36651
37014
|
for (const block of dynamicBlocks.contentBlocks) {
|
|
36652
37015
|
const { assemblyName, end, refName, start } = block;
|
|
36653
37016
|
const assembly = self.apolloDataStore.assemblies.get(assemblyName);
|
|
36654
|
-
if (assembly
|
|
36655
|
-
assembly.backendDriverType === 'CollaborationServerDriver') {
|
|
37017
|
+
if (assembly?.backendDriverType === 'CollaborationServerDriver') {
|
|
36656
37018
|
locations.push({ assemblyName, refName, start, end });
|
|
36657
37019
|
}
|
|
36658
37020
|
}
|
|
@@ -36711,8 +37073,8 @@
|
|
|
36711
37073
|
for (const block of dynamicBlocks.contentBlocks) {
|
|
36712
37074
|
const { assemblyName, end, refName, start } = block;
|
|
36713
37075
|
const assembly = self.apolloDataStore.assemblies.get(assemblyName);
|
|
36714
|
-
if (assembly
|
|
36715
|
-
|
|
37076
|
+
if (assembly?.backendDriverType ===
|
|
37077
|
+
'CollaborationServerDriver') {
|
|
36716
37078
|
locations.push({ assemblyName, refName, start, end });
|
|
36717
37079
|
}
|
|
36718
37080
|
}
|
|
@@ -36832,6 +37194,37 @@
|
|
|
36832
37194
|
beforeDestroy() {
|
|
36833
37195
|
self.abortController.abort(new DOMException('Clean up Apollo session', 'AbortError'));
|
|
36834
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
|
+
},
|
|
36835
37228
|
}))
|
|
36836
37229
|
.views((self) => {
|
|
36837
37230
|
const superTrackActions = self
|
|
@@ -36963,7 +37356,6 @@
|
|
|
36963
37356
|
}
|
|
36964
37357
|
|
|
36965
37358
|
/* eslint-disable @typescript-eslint/unbound-method */
|
|
36966
|
-
/* eslint-disable @typescript-eslint/no-unnecessary-condition */
|
|
36967
37359
|
/* eslint-disable @typescript-eslint/no-misused-promises */
|
|
36968
37360
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
36969
37361
|
function isApolloMessageData(data) {
|
|
@@ -37151,10 +37543,10 @@
|
|
|
37151
37543
|
});
|
|
37152
37544
|
if (!inWebWorker) {
|
|
37153
37545
|
pluginManager.addToExtensionPoint('Core-extendWorker', (handle) => {
|
|
37154
|
-
if (!('on' in handle && handle.on)) {
|
|
37546
|
+
if (!('on' in handle.client && handle.client.on)) {
|
|
37155
37547
|
return handle;
|
|
37156
37548
|
}
|
|
37157
|
-
handle.on('apollo', async (event) => {
|
|
37549
|
+
handle.client.on('apollo', async (event) => {
|
|
37158
37550
|
if (!isApolloMessageData(event)) {
|
|
37159
37551
|
return;
|
|
37160
37552
|
}
|
|
@@ -37172,7 +37564,7 @@
|
|
|
37172
37564
|
break;
|
|
37173
37565
|
}
|
|
37174
37566
|
const { seq: sequence } = await backendDriver.getSequence(region);
|
|
37175
|
-
handle.
|
|
37567
|
+
handle.worker.postMessage({
|
|
37176
37568
|
apollo,
|
|
37177
37569
|
messageId,
|
|
37178
37570
|
sequence,
|
|
@@ -37190,7 +37582,7 @@
|
|
|
37190
37582
|
break;
|
|
37191
37583
|
}
|
|
37192
37584
|
const regions = await backendDriver.getRegions(assembly);
|
|
37193
|
-
handle.
|
|
37585
|
+
handle.worker.postMessage({
|
|
37194
37586
|
apollo,
|
|
37195
37587
|
messageId,
|
|
37196
37588
|
regions,
|
|
@@ -37208,7 +37600,7 @@
|
|
|
37208
37600
|
break;
|
|
37209
37601
|
}
|
|
37210
37602
|
const refNameAliases = await backendDriver.getRefNameAliases(assembly);
|
|
37211
|
-
handle.
|
|
37603
|
+
handle.worker.postMessage({
|
|
37212
37604
|
apollo,
|
|
37213
37605
|
messageId,
|
|
37214
37606
|
refNameAliases,
|