@apollo-annotation/jbrowse-plugin-apollo 1.0.1 → 1.1.1
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 +835 -434
- package/dist/index.esm.js.map +1 -1
- package/dist/jbrowse-plugin-apollo.cjs.development.js +830 -429
- package/dist/jbrowse-plugin-apollo.cjs.development.js.map +1 -1
- package/dist/jbrowse-plugin-apollo.cjs.production.min.js +1 -1
- package/dist/jbrowse-plugin-apollo.cjs.production.min.js.map +1 -1
- package/dist/jbrowse-plugin-apollo.umd.development.js +868 -468
- package/dist/jbrowse-plugin-apollo.umd.development.js.map +1 -1
- package/dist/jbrowse-plugin-apollo.umd.production.min.js +1 -1
- package/dist/jbrowse-plugin-apollo.umd.production.min.js.map +1 -1
- package/dist/session/ClientDataStore.d.ts +2194 -0
- package/dist/session/ClientDataStore.d.ts.map +1 -0
- package/dist/session/handleApolloFeaturesUrlParam.d.ts +8 -0
- package/dist/session/handleApolloFeaturesUrlParam.d.ts.map +1 -0
- package/dist/session/session.d.ts +6788 -0
- package/dist/session/session.d.ts.map +1 -0
- package/dist/util/displayUtils.d.ts +36 -0
- package/dist/util/displayUtils.d.ts.map +1 -0
- package/dist/util/sequenceUtils.d.ts +2 -0
- package/dist/util/sequenceUtils.d.ts.map +1 -0
- package/package.json +14 -14
- package/src/ApolloInternetAccount/components/AuthTypeSelector.tsx +73 -38
- package/src/ApolloInternetAccount/components/LoginButtons.tsx +31 -10
- package/src/ApolloInternetAccount/model.ts +8 -5
- package/src/ApolloJobModel.ts +3 -8
- package/src/ApolloTextSearchAdapter/ApolloTextSearchAdapter.ts +1 -1
- package/src/BackendDrivers/CollaborationServerDriver.ts +7 -11
- package/src/BackendDrivers/LocalDriver/LocalDriver.ts +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 +366 -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 +32 -24
- package/src/components/DeleteAssembly.tsx +2 -2
- package/src/components/DeleteFeature.tsx +1 -4
- package/src/components/DownloadGFF3.tsx +4 -3
- package/src/components/DuplicateFeatureDialog.tsx +154 -0
- package/src/components/DuplicateTranscript.tsx +1 -1
- package/src/components/FilterTranscripts.tsx +1 -1
- package/src/components/ImportAnnotations.tsx +108 -0
- package/src/components/ManageUsers.tsx +1 -2
- package/src/components/OntologyTermAutocomplete.tsx +1 -3
- package/src/components/OntologyTermMultiSelect.tsx +3 -1
- package/src/components/ViewChangeLog.tsx +2 -1
- package/src/components/index.ts +2 -0
- package/src/extensions/annotationFromPileup.ts +34 -26
- package/src/index.ts +9 -8
- package/src/session/ClientDataStore.ts +16 -21
- package/src/session/handleApolloFeaturesUrlParam.ts +122 -0
- package/src/session/session.ts +49 -9
- package/src/util/annotationFeatureUtils.ts +1 -1
- package/src/util/displayUtils.ts +1 -1
- package/src/util/glyphUtils.ts +3 -3
- package/src/util/sequenceUtils.ts +29 -0
|
@@ -3107,12 +3107,10 @@
|
|
|
3107
3107
|
}, {
|
|
3108
3108
|
key: "addChild",
|
|
3109
3109
|
value: function addChild(parentFeature, child) {
|
|
3110
|
-
var _parentFeature$attrib;
|
|
3110
|
+
var _parentFeature$attrib, _parentFeature$childr;
|
|
3111
3111
|
if (!((_parentFeature$attrib = parentFeature.attributes) !== null && _parentFeature$attrib !== void 0 && _parentFeature$attrib._id)) {
|
|
3112
|
-
var
|
|
3113
|
-
|
|
3114
|
-
attributes = {};
|
|
3115
|
-
}
|
|
3112
|
+
var _parentFeature$attrib2 = parentFeature.attributes,
|
|
3113
|
+
attributes = _parentFeature$attrib2 === void 0 ? {} : _parentFeature$attrib2;
|
|
3116
3114
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
3117
3115
|
attributes = _objectSpread2({
|
|
3118
3116
|
_id: [parentFeature._id.toString()]
|
|
@@ -3120,9 +3118,7 @@
|
|
|
3120
3118
|
parentFeature.attributes = attributes;
|
|
3121
3119
|
}
|
|
3122
3120
|
var _id = child._id;
|
|
3123
|
-
|
|
3124
|
-
parentFeature.children = new Map();
|
|
3125
|
-
}
|
|
3121
|
+
(_parentFeature$childr = parentFeature.children) !== null && _parentFeature$childr !== void 0 ? _parentFeature$childr : parentFeature.children = new Map();
|
|
3126
3122
|
parentFeature.children.set(_id, _objectSpread2(_objectSpread2({
|
|
3127
3123
|
allIds: []
|
|
3128
3124
|
}, child), {}, {
|
|
@@ -4284,10 +4280,9 @@
|
|
|
4284
4280
|
}, {
|
|
4285
4281
|
key: "mergeFeatureIntoTranscriptOnServer",
|
|
4286
4282
|
value: function mergeFeatureIntoTranscriptOnServer(secondFeatureChild, firstTranscript) {
|
|
4287
|
-
var
|
|
4288
|
-
|
|
4289
|
-
|
|
4290
|
-
}
|
|
4283
|
+
var _firstTranscript$chil,
|
|
4284
|
+
_this2 = this;
|
|
4285
|
+
(_firstTranscript$chil = firstTranscript.children) !== null && _firstTranscript$chil !== void 0 ? _firstTranscript$chil : firstTranscript.children = new Map();
|
|
4291
4286
|
var merged = false;
|
|
4292
4287
|
var mrgChild;
|
|
4293
4288
|
var toDelete;
|
|
@@ -4304,11 +4299,10 @@
|
|
|
4304
4299
|
toDelete = true;
|
|
4305
4300
|
}
|
|
4306
4301
|
if (mrgChild.type === secondFeatureChild.type && mrgChild.type === firstFeatureChild.type && util$1.doesIntersect2(secondFeatureChild.min, secondFeatureChild.max, mrgChild.min, mrgChild.max) && util$1.doesIntersect2(firstFeatureChild.min, firstFeatureChild.max, mrgChild.min, mrgChild.max)) {
|
|
4302
|
+
var _mrgChild, _mrgChild$attributes;
|
|
4307
4303
|
mrgChild.min = Math.min(secondFeatureChild.min, mrgChild.min, firstFeatureChild.min);
|
|
4308
4304
|
mrgChild.max = Math.max(secondFeatureChild.max, mrgChild.max, firstFeatureChild.max);
|
|
4309
|
-
|
|
4310
|
-
mrgChild.attributes = {};
|
|
4311
|
-
}
|
|
4305
|
+
(_mrgChild$attributes = (_mrgChild = mrgChild).attributes) !== null && _mrgChild$attributes !== void 0 ? _mrgChild$attributes : _mrgChild.attributes = {};
|
|
4312
4306
|
var mrgChildAttr = JSON.parse(JSON.stringify(mrgChild.attributes));
|
|
4313
4307
|
if (!Object.keys(mrgChildAttr).includes('merged_with')) {
|
|
4314
4308
|
mrgChildAttr.merged_with = [];
|
|
@@ -4371,9 +4365,8 @@
|
|
|
4371
4365
|
}, {
|
|
4372
4366
|
key: "mergeFeatureIntoTranscriptOnClient",
|
|
4373
4367
|
value: function mergeFeatureIntoTranscriptOnClient(secondFeatureChild, firstTranscript) {
|
|
4374
|
-
|
|
4375
|
-
|
|
4376
|
-
}
|
|
4368
|
+
var _firstTranscript$chil2;
|
|
4369
|
+
(_firstTranscript$chil2 = firstTranscript.children) !== null && _firstTranscript$chil2 !== void 0 ? _firstTranscript$chil2 : firstTranscript.children = new Map();
|
|
4377
4370
|
var merged = false;
|
|
4378
4371
|
var mrgChild;
|
|
4379
4372
|
var toDelete;
|
|
@@ -5633,21 +5626,21 @@
|
|
|
5633
5626
|
var _feature$attributes, _feature$attributes2;
|
|
5634
5627
|
var gff_id = (_feature$attributes = feature.attributes) === null || _feature$attributes === void 0 || (_feature$attributes = _feature$attributes.gff_id) === null || _feature$attributes === void 0 ? void 0 : _feature$attributes.join(', ');
|
|
5635
5628
|
if (gff_id) {
|
|
5636
|
-
return "".concat(gff_id, " (_id: ").concat(feature._id
|
|
5629
|
+
return "".concat(gff_id, " (_id: ").concat(feature._id, ")");
|
|
5637
5630
|
}
|
|
5638
5631
|
var gff_name = (_feature$attributes2 = feature.attributes) === null || _feature$attributes2 === void 0 || (_feature$attributes2 = _feature$attributes2.gff_name) === null || _feature$attributes2 === void 0 ? void 0 : _feature$attributes2.join(', ');
|
|
5639
5632
|
if (gff_name) {
|
|
5640
|
-
return "".concat(gff_name, " (_id: ").concat(feature._id
|
|
5633
|
+
return "".concat(gff_name, " (_id: ").concat(feature._id, ")");
|
|
5641
5634
|
}
|
|
5642
|
-
return "_id: ".concat(feature._id
|
|
5635
|
+
return "_id: ".concat(feature._id);
|
|
5643
5636
|
}
|
|
5644
5637
|
|
|
5645
|
-
var STOP_CODONS;
|
|
5638
|
+
var STOP_CODONS$1;
|
|
5646
5639
|
(function (STOP_CODONS) {
|
|
5647
5640
|
STOP_CODONS[STOP_CODONS["TAG"] = 0] = "TAG";
|
|
5648
5641
|
STOP_CODONS[STOP_CODONS["TAA"] = 1] = "TAA";
|
|
5649
5642
|
STOP_CODONS[STOP_CODONS["TGA"] = 2] = "TGA";
|
|
5650
|
-
})(STOP_CODONS || (STOP_CODONS = {}));
|
|
5643
|
+
})(STOP_CODONS$1 || (STOP_CODONS$1 = {}));
|
|
5651
5644
|
var START_CODONS;
|
|
5652
5645
|
(function (START_CODONS) {
|
|
5653
5646
|
START_CODONS[START_CODONS["ATG"] = 0] = "ATG";
|
|
@@ -5748,8 +5741,8 @@
|
|
|
5748
5741
|
return a.min < b.min ? -1 : 1;
|
|
5749
5742
|
});
|
|
5750
5743
|
var i = 0;
|
|
5751
|
-
var currentStart
|
|
5752
|
-
var currentEnd
|
|
5744
|
+
var currentStart;
|
|
5745
|
+
var currentEnd;
|
|
5753
5746
|
for (var iloc = 0; iloc < sortedLocation.length; iloc++) {
|
|
5754
5747
|
var loc = sortedLocation[iloc];
|
|
5755
5748
|
var phase = loc.phase;
|
|
@@ -5819,20 +5812,20 @@
|
|
|
5819
5812
|
name: CHECK_NAME$1,
|
|
5820
5813
|
cause: CAUSES$1[CAUSES$1.MissingStartCodon],
|
|
5821
5814
|
ids: ids,
|
|
5822
|
-
refSeq: refSeq
|
|
5815
|
+
refSeq: refSeq,
|
|
5823
5816
|
start: cdsStart,
|
|
5824
5817
|
end: cdsStart,
|
|
5825
5818
|
message: "Unexpected start codon \"".concat(start_codon, "\" in feature \"").concat(getPrintableId(feature), "\": ")
|
|
5826
5819
|
});
|
|
5827
5820
|
}
|
|
5828
5821
|
lastCodon = codons.at(-1); // Last codon is supposed to be a stop
|
|
5829
|
-
if (lastCodon && !(lastCodon.toUpperCase() in STOP_CODONS)) {
|
|
5822
|
+
if (lastCodon && !(lastCodon.toUpperCase() in STOP_CODONS$1)) {
|
|
5830
5823
|
checkResults.push({
|
|
5831
5824
|
_id: new ObjectID().toHexString(),
|
|
5832
5825
|
name: CHECK_NAME$1,
|
|
5833
5826
|
cause: CAUSES$1[CAUSES$1.MissingStopCodon],
|
|
5834
5827
|
ids: ids,
|
|
5835
|
-
refSeq: refSeq
|
|
5828
|
+
refSeq: refSeq,
|
|
5836
5829
|
start: cdsEnd,
|
|
5837
5830
|
end: cdsEnd,
|
|
5838
5831
|
message: "Missing stop codon in feature \"".concat(getPrintableId(feature), "\"")
|
|
@@ -5844,7 +5837,7 @@
|
|
|
5844
5837
|
name: CHECK_NAME$1,
|
|
5845
5838
|
cause: CAUSES$1[CAUSES$1.MissingStopCodon],
|
|
5846
5839
|
ids: ids,
|
|
5847
|
-
refSeq: refSeq
|
|
5840
|
+
refSeq: refSeq,
|
|
5848
5841
|
start: cdsEnd,
|
|
5849
5842
|
end: cdsEnd,
|
|
5850
5843
|
message: "Missing stop codon in feature \"".concat(getPrintableId(feature), "\"")
|
|
@@ -5866,14 +5859,14 @@
|
|
|
5866
5859
|
return _context3.a(3, 9);
|
|
5867
5860
|
case 7:
|
|
5868
5861
|
location = getOriginalCodonLocation(cdsLocation, strand, idx);
|
|
5869
|
-
if (location && codon.toUpperCase() in STOP_CODONS) {
|
|
5862
|
+
if (location && codon.toUpperCase() in STOP_CODONS$1) {
|
|
5870
5863
|
_location = _slicedToArray(location, 2), codonStart = _location[0], codonEnd = _location[1];
|
|
5871
5864
|
checkResults.push({
|
|
5872
5865
|
_id: new ObjectID().toHexString(),
|
|
5873
5866
|
name: CHECK_NAME$1,
|
|
5874
5867
|
cause: CAUSES$1[CAUSES$1.InternalStopCodon],
|
|
5875
5868
|
ids: ids,
|
|
5876
|
-
refSeq: refSeq
|
|
5869
|
+
refSeq: refSeq,
|
|
5877
5870
|
start: codonStart,
|
|
5878
5871
|
end: codonEnd,
|
|
5879
5872
|
message: "Internal stop codon in feature \"".concat(getPrintableId(feature), "\"")
|
|
@@ -6171,7 +6164,7 @@
|
|
|
6171
6164
|
name: CHECK_NAME,
|
|
6172
6165
|
cause: CAUSES[CAUSES.NonCanonicalSpliceSiteAtFivePrime],
|
|
6173
6166
|
ids: [feature._id],
|
|
6174
|
-
refSeq: feature.refSeq
|
|
6167
|
+
refSeq: feature.refSeq,
|
|
6175
6168
|
start: spliceSequence.fivePrimeMin,
|
|
6176
6169
|
end: spliceSequence.fivePrimeMin + 2,
|
|
6177
6170
|
message: "Unexpected 5\u2032 splice site in \"".concat(getPrintableId(feature), "\". Expected: ").concat(_toConsumableArray(VALID_FIVE_PRIME_SEQ).join('|'), ", got: ").concat(spliceSequence.fivePrimeSeq)
|
|
@@ -6183,7 +6176,7 @@
|
|
|
6183
6176
|
name: CHECK_NAME,
|
|
6184
6177
|
cause: CAUSES[CAUSES.NonCanonicalSpliceSiteAtThreePrime],
|
|
6185
6178
|
ids: [feature._id],
|
|
6186
|
-
refSeq: feature.refSeq
|
|
6179
|
+
refSeq: feature.refSeq,
|
|
6187
6180
|
start: spliceSequence.threePrimeMin,
|
|
6188
6181
|
end: spliceSequence.threePrimeMin + 2,
|
|
6189
6182
|
message: "Unexpected 3\u2032 splice site in \"".concat(getPrintableId(feature), "\". Expected: ").concat(_toConsumableArray(VALID_THREE_PRIME_SEQ).join('|'), ", got: ").concat(spliceSequence.threePrimeSeq)
|
|
@@ -6351,8 +6344,8 @@
|
|
|
6351
6344
|
delete attributes.gff_score;
|
|
6352
6345
|
}
|
|
6353
6346
|
return {
|
|
6354
|
-
start:
|
|
6355
|
-
end:
|
|
6347
|
+
start: featureLoc.min + 1,
|
|
6348
|
+
end: featureLoc.max,
|
|
6356
6349
|
seq_id: featureLoc.refSeq,
|
|
6357
6350
|
source: source,
|
|
6358
6351
|
type: featureLoc.type,
|
|
@@ -6557,7 +6550,7 @@
|
|
|
6557
6550
|
return transcriptParts;
|
|
6558
6551
|
}
|
|
6559
6552
|
function getCdsLocations(feature) {
|
|
6560
|
-
var transcriptParts
|
|
6553
|
+
var transcriptParts;
|
|
6561
6554
|
try {
|
|
6562
6555
|
transcriptParts = getTranscriptParts(feature);
|
|
6563
6556
|
} catch (_unused) {
|
|
@@ -7122,7 +7115,7 @@
|
|
|
7122
7115
|
d: "M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6z"
|
|
7123
7116
|
}), 'Add');
|
|
7124
7117
|
|
|
7125
|
-
var version = "1.
|
|
7118
|
+
var version = "1.1.1";
|
|
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,195 @@
|
|
|
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
|
+
if (startCodonIndex === -1) {
|
|
29819
|
+
notify('Start codon not found', 'error');
|
|
29820
|
+
return;
|
|
29821
|
+
}
|
|
29822
|
+
const stopCodonIndex = proteinSequence.indexOf('*', startCodonIndex);
|
|
29823
|
+
if (stopCodonIndex === -1) {
|
|
29824
|
+
notify('Stop codon not found', 'error');
|
|
29825
|
+
return;
|
|
29826
|
+
}
|
|
29827
|
+
const startCodonPos = startCodonIndex * 3;
|
|
29828
|
+
const stopCodonPos = stopCodonIndex * 3;
|
|
29829
|
+
const startCodonGenomicLoc = getCodonGenomicLocation(startCodonPos);
|
|
29830
|
+
let stopCodonGenomicLoc = getCodonGenomicLocation(stopCodonPos);
|
|
29831
|
+
if (strand === 1) {
|
|
29832
|
+
if (startCodonGenomicLoc > stopCodonGenomicLoc) {
|
|
29833
|
+
notify('Start codon genomic location should be less than stop codon genomic location', 'error');
|
|
29834
|
+
return;
|
|
29835
|
+
}
|
|
29836
|
+
let promise;
|
|
29837
|
+
stopCodonGenomicLoc += 3; // move to end of stop codon
|
|
29838
|
+
if (startCodonGenomicLoc !== cdsMin) {
|
|
29839
|
+
promise = new Promise((resolve) => {
|
|
29840
|
+
updateCDSLocation(cdsMin, startCodonGenomicLoc, feature, true, () => {
|
|
29841
|
+
resolve(true);
|
|
29842
|
+
});
|
|
29843
|
+
});
|
|
29844
|
+
}
|
|
29845
|
+
if (stopCodonGenomicLoc !== cdsMax) {
|
|
29846
|
+
if (promise) {
|
|
29847
|
+
void promise.then(() => {
|
|
29848
|
+
updateCDSLocation(cdsMax, stopCodonGenomicLoc, feature, false);
|
|
29849
|
+
});
|
|
29850
|
+
}
|
|
29851
|
+
else {
|
|
29852
|
+
updateCDSLocation(cdsMax, stopCodonGenomicLoc, feature, false);
|
|
29853
|
+
}
|
|
29854
|
+
}
|
|
29855
|
+
}
|
|
29856
|
+
if (strand === -1) {
|
|
29857
|
+
// reverse strand
|
|
29858
|
+
if (startCodonGenomicLoc < stopCodonGenomicLoc) {
|
|
29859
|
+
notify('Start codon genomic location should be less than stop codon genomic location', 'error');
|
|
29860
|
+
return;
|
|
29861
|
+
}
|
|
29862
|
+
let promise;
|
|
29863
|
+
stopCodonGenomicLoc -= 3; // move to end of stop codon
|
|
29864
|
+
if (startCodonGenomicLoc !== cdsMax) {
|
|
29865
|
+
promise = new Promise((resolve) => {
|
|
29866
|
+
updateCDSLocation(cdsMax, startCodonGenomicLoc, feature, false, () => {
|
|
29867
|
+
resolve(true);
|
|
29868
|
+
});
|
|
29869
|
+
});
|
|
29870
|
+
}
|
|
29871
|
+
if (stopCodonGenomicLoc !== cdsMin) {
|
|
29872
|
+
if (promise) {
|
|
29873
|
+
void promise.then(() => {
|
|
29874
|
+
updateCDSLocation(cdsMin, stopCodonGenomicLoc, feature, true);
|
|
29875
|
+
});
|
|
29876
|
+
}
|
|
29877
|
+
else {
|
|
29878
|
+
updateCDSLocation(cdsMin, stopCodonGenomicLoc, feature, true);
|
|
29879
|
+
}
|
|
29880
|
+
}
|
|
29881
|
+
}
|
|
29882
|
+
notify('Translation sequence trimmed to start and stop codons', 'success');
|
|
29883
|
+
};
|
|
29884
|
+
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) => {
|
|
29885
|
+
const codonGenomicPos = idx * 3;
|
|
29886
|
+
if (protein === 'M') {
|
|
29887
|
+
return (jsxRuntime.jsx(material.Typography, { component: 'span', style: {
|
|
29888
|
+
backgroundColor: changeInProgress
|
|
29889
|
+
? 'lightgray'
|
|
29890
|
+
: 'yellow',
|
|
29891
|
+
cursor: 'pointer',
|
|
29892
|
+
border: '1px solid black',
|
|
29893
|
+
}, onClick: () => {
|
|
29894
|
+
if (changeInProgress) {
|
|
29895
|
+
return;
|
|
29896
|
+
}
|
|
29897
|
+
// NOTE: codonGenomicPos is important here for calculating the genomic location
|
|
29898
|
+
// of the start codon. We are using the codonGenomicPos as the key in the typography
|
|
29899
|
+
// elements to maintain the genomic postion of the codon start
|
|
29900
|
+
const startCodonGenomicLocation = getCodonGenomicLocation(codonGenomicPos);
|
|
29901
|
+
if (startCodonGenomicLocation !== cdsMin &&
|
|
29902
|
+
strand === 1) {
|
|
29903
|
+
updateCDSLocation(cdsMin, startCodonGenomicLocation, feature, true);
|
|
29904
|
+
}
|
|
29905
|
+
if (startCodonGenomicLocation !== cdsMax &&
|
|
29906
|
+
strand === -1) {
|
|
29907
|
+
updateCDSLocation(cdsMax, startCodonGenomicLocation, feature, false);
|
|
29908
|
+
}
|
|
29909
|
+
}, children: protein }, codonGenomicPos));
|
|
29910
|
+
}
|
|
29911
|
+
if (protein === '*') {
|
|
29912
|
+
return (jsxRuntime.jsx(material.Typography, { style: { backgroundColor: 'red', color: 'white' }, component: 'span', children: protein }, codonGenomicPos));
|
|
29913
|
+
}
|
|
29914
|
+
// Pass the codonGenomicPos as the key to maintain the genomic position of the codon
|
|
29915
|
+
return (jsxRuntime.jsx(material.Typography, { component: 'span', children: protein }, codonGenomicPos));
|
|
29916
|
+
}) }) }), jsxRuntime.jsxs("div", { style: {
|
|
29917
|
+
marginTop: 10,
|
|
29918
|
+
display: 'flex',
|
|
29919
|
+
flexDirection: 'row',
|
|
29920
|
+
alignItems: 'center',
|
|
29921
|
+
gap: 10,
|
|
29922
|
+
}, 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 } }) }) })] })] })] }) }));
|
|
29923
|
+
}
|
|
29924
|
+
|
|
29925
|
+
const StyledTextField = newStyled(NumberTextField)(() => ({
|
|
29926
|
+
'&.MuiFormControl-root': {
|
|
29927
|
+
marginTop: 0,
|
|
29928
|
+
marginBottom: 0,
|
|
29929
|
+
width: '100%',
|
|
29930
|
+
},
|
|
29931
|
+
'& .MuiInputBase-input': {
|
|
29932
|
+
fontSize: 12,
|
|
29933
|
+
height: 20,
|
|
29934
|
+
padding: 1,
|
|
29935
|
+
paddingLeft: 10,
|
|
29936
|
+
},
|
|
29937
|
+
}));
|
|
29555
29938
|
const Strand = (props) => {
|
|
29556
29939
|
const { strand } = props;
|
|
29557
29940
|
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 +29953,6 @@
|
|
|
29570
29953
|
const currentAssembly = session.apolloDataStore.assemblies.get(assembly);
|
|
29571
29954
|
const refData = currentAssembly?.getByRefName(refName);
|
|
29572
29955
|
const { changeManager } = session.apolloDataStore;
|
|
29573
|
-
const seqRef = React.useRef(null);
|
|
29574
29956
|
const { changeInProgress } = session;
|
|
29575
29957
|
if (!refData) {
|
|
29576
29958
|
return null;
|
|
@@ -29997,184 +30379,6 @@
|
|
|
29997
30379
|
},
|
|
29998
30380
|
];
|
|
29999
30381
|
};
|
|
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
30382
|
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
30383
|
return updateCDSLocation(cdsMin, newLocation - 1, feature, true);
|
|
30180
30384
|
}, 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 +30388,12 @@
|
|
|
30184
30388
|
}, 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
30389
|
return updateCDSLocation(cdsMin, newLocation - 1, feature, true);
|
|
30186
30390
|
}, 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
|
-
|
|
30391
|
+
return (
|
|
30392
|
+
// eslint-disable-next-line @eslint-react/no-array-index-key
|
|
30393
|
+
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 &&
|
|
30394
|
+
getFivePrimeSpliceSite(loc, index).map((site, idx) => (jsxRuntime.jsx(material.Typography
|
|
30395
|
+
// eslint-disable-next-line @eslint-react/no-array-index-key
|
|
30396
|
+
, { 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
30397
|
return handleExonLocationChange(loc.min, newLocation - 1, feature, true);
|
|
30190
30398
|
}, 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
30399
|
return handleExonLocationChange(loc.max, newLocation, feature, false);
|
|
@@ -30194,14 +30402,10 @@
|
|
|
30194
30402
|
}, 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
30403
|
return handleExonLocationChange(loc.min, newLocation - 1, feature, true);
|
|
30196
30404
|
}, 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 } }) }) })] })] })] }) }))] }));
|
|
30405
|
+
getThreePrimeSpliceSite(loc, index).map((site, idx) => (jsxRuntime.jsx(material.Typography
|
|
30406
|
+
// eslint-disable-next-line @eslint-react/no-array-index-key
|
|
30407
|
+
, { component: 'span', color: site.color, children: site.spliceSite }, idx))) })] })) }, index));
|
|
30408
|
+
})] }), cdsPresent && (jsxRuntime.jsx(Translation, { changeInProgress: changeInProgress, cdsLocations: cdsLocations, refData: refData, strand: strand, updateCDSLocation: updateCDSLocation, cdsMin: cdsMin, cdsMax: cdsMax, feature: feature, session: session }))] }));
|
|
30205
30409
|
});
|
|
30206
30410
|
|
|
30207
30411
|
const HeaderTableCell = newStyled(material.TableCell)(() => ({
|
|
@@ -30238,7 +30442,7 @@
|
|
|
30238
30442
|
const { assembly, feature, refName } = model;
|
|
30239
30443
|
React.useEffect(() => {
|
|
30240
30444
|
setPanelState(DEFAULT_PANELS);
|
|
30241
|
-
// eslint-disable-next-line react
|
|
30445
|
+
// eslint-disable-next-line @eslint-react/exhaustive-deps
|
|
30242
30446
|
}, [feature]);
|
|
30243
30447
|
const session = util$1.getSession(model);
|
|
30244
30448
|
const { pluginManager } = util$1.getEnv(session);
|
|
@@ -30297,8 +30501,8 @@
|
|
|
30297
30501
|
typeName: 'TypeChange',
|
|
30298
30502
|
changedIds: [featureId],
|
|
30299
30503
|
featureId,
|
|
30300
|
-
oldType
|
|
30301
|
-
newType
|
|
30504
|
+
oldType,
|
|
30505
|
+
newType,
|
|
30302
30506
|
assembly: feature.assemblyId,
|
|
30303
30507
|
});
|
|
30304
30508
|
return changeManager.submit(change);
|
|
@@ -30394,7 +30598,7 @@
|
|
|
30394
30598
|
if (initialValue !== value) {
|
|
30395
30599
|
setValue(initialValue);
|
|
30396
30600
|
}
|
|
30397
|
-
// eslint-disable-next-line react
|
|
30601
|
+
// eslint-disable-next-line @eslint-react/exhaustive-deps
|
|
30398
30602
|
}, [initialValue]);
|
|
30399
30603
|
React.useEffect(() => {
|
|
30400
30604
|
if (blur) {
|
|
@@ -31243,8 +31447,9 @@
|
|
|
31243
31447
|
const [top, left, width] = getFeatureBox(display, gene, row, block);
|
|
31244
31448
|
const height = getRowCount$2(display, gene) * apolloRowHeight;
|
|
31245
31449
|
if (width > 2) {
|
|
31246
|
-
|
|
31247
|
-
|
|
31450
|
+
const selectedColor = configuration.readConfObject(session.getPluginConfiguration(), 'geneBackgroundColor', {
|
|
31451
|
+
featureType: gene.type,
|
|
31452
|
+
}) ?? material.alpha(theme.palette.background.paper, 0.6);
|
|
31248
31453
|
ctx.fillStyle = selectedColor;
|
|
31249
31454
|
ctx.fillRect(left, top, width, height);
|
|
31250
31455
|
}
|
|
@@ -31517,7 +31722,7 @@
|
|
|
31517
31722
|
}
|
|
31518
31723
|
return layout;
|
|
31519
31724
|
}
|
|
31520
|
-
function getContextMenuItems$1(display,
|
|
31725
|
+
function getContextMenuItems$1(display, transcript) {
|
|
31521
31726
|
const { changeManager, regions, selectedFeature, session } = display;
|
|
31522
31727
|
const [region] = regions;
|
|
31523
31728
|
const currentAssemblyId = display.getAssemblyId(region.assemblyName);
|
|
@@ -31527,7 +31732,7 @@
|
|
|
31527
31732
|
label: 'Open transcript editor',
|
|
31528
31733
|
onClick: () => {
|
|
31529
31734
|
const apolloTranscriptWidget = session.addWidget('ApolloTranscriptDetails', 'apolloTranscriptDetails', {
|
|
31530
|
-
feature,
|
|
31735
|
+
feature: transcript,
|
|
31531
31736
|
assembly: currentAssemblyId,
|
|
31532
31737
|
changeManager,
|
|
31533
31738
|
refName: region.refName,
|
|
@@ -31547,7 +31752,7 @@
|
|
|
31547
31752
|
doneCallback();
|
|
31548
31753
|
},
|
|
31549
31754
|
changeManager,
|
|
31550
|
-
sourceFeature:
|
|
31755
|
+
sourceFeature: transcript,
|
|
31551
31756
|
sourceAssemblyId: currentAssemblyId,
|
|
31552
31757
|
selectedFeature,
|
|
31553
31758
|
setSelectedFeature: (feature) => {
|
|
@@ -31567,7 +31772,7 @@
|
|
|
31567
31772
|
doneCallback();
|
|
31568
31773
|
},
|
|
31569
31774
|
changeManager,
|
|
31570
|
-
sourceFeature:
|
|
31775
|
+
sourceFeature: transcript,
|
|
31571
31776
|
sourceAssemblyId: currentAssemblyId,
|
|
31572
31777
|
selectedFeature,
|
|
31573
31778
|
setSelectedFeature: (feature) => {
|
|
@@ -31577,6 +31782,31 @@
|
|
|
31577
31782
|
]);
|
|
31578
31783
|
},
|
|
31579
31784
|
});
|
|
31785
|
+
const { children } = transcript;
|
|
31786
|
+
if (!children) {
|
|
31787
|
+
return [];
|
|
31788
|
+
}
|
|
31789
|
+
const cdsChildren = [...children.values()].filter((child) => isCDSFeature(child, session));
|
|
31790
|
+
if (cdsChildren.length === 0) {
|
|
31791
|
+
menuItems.push({
|
|
31792
|
+
label: 'Add coding sequence',
|
|
31793
|
+
onClick: () => {
|
|
31794
|
+
session.queueDialog((doneCallback) => [
|
|
31795
|
+
AddCodingSequence,
|
|
31796
|
+
{
|
|
31797
|
+
session,
|
|
31798
|
+
handleClose: () => {
|
|
31799
|
+
doneCallback();
|
|
31800
|
+
},
|
|
31801
|
+
changeManager,
|
|
31802
|
+
sourceFeature: transcript,
|
|
31803
|
+
sourceAssemblyId: currentAssemblyId,
|
|
31804
|
+
refName: region.refName,
|
|
31805
|
+
},
|
|
31806
|
+
]);
|
|
31807
|
+
},
|
|
31808
|
+
});
|
|
31809
|
+
}
|
|
31580
31810
|
return menuItems;
|
|
31581
31811
|
}
|
|
31582
31812
|
// False positive here, none of these functions use "this"
|
|
@@ -31763,7 +31993,7 @@
|
|
|
31763
31993
|
letterUpper === 'C' ||
|
|
31764
31994
|
letterUpper === 'G' ||
|
|
31765
31995
|
letterUpper === 'T') {
|
|
31766
|
-
return theme.palette.bases[letterUpper].main
|
|
31996
|
+
return theme.palette.bases[letterUpper].main;
|
|
31767
31997
|
}
|
|
31768
31998
|
return 'lightgray';
|
|
31769
31999
|
}
|
|
@@ -31860,8 +32090,7 @@
|
|
|
31860
32090
|
return internetAccounts.find((ia) => configuration.getConf(ia, 'internetAccountId') === internetAccountConfigId);
|
|
31861
32091
|
},
|
|
31862
32092
|
get changeManager() {
|
|
31863
|
-
return self.session.apolloDataStore
|
|
31864
|
-
.changeManager;
|
|
32093
|
+
return self.session.apolloDataStore.changeManager;
|
|
31865
32094
|
},
|
|
31866
32095
|
getAssemblyId(assemblyName) {
|
|
31867
32096
|
const { assemblyManager } = self.session;
|
|
@@ -31872,12 +32101,10 @@
|
|
|
31872
32101
|
return assembly.name;
|
|
31873
32102
|
},
|
|
31874
32103
|
get selectedFeature() {
|
|
31875
|
-
return self.session
|
|
31876
|
-
.apolloSelectedFeature;
|
|
32104
|
+
return self.session.apolloSelectedFeature;
|
|
31877
32105
|
},
|
|
31878
32106
|
get hoveredFeature() {
|
|
31879
|
-
return self.session
|
|
31880
|
-
.apolloHoveredFeature;
|
|
32107
|
+
return self.session.apolloHoveredFeature;
|
|
31881
32108
|
},
|
|
31882
32109
|
}))
|
|
31883
32110
|
.actions((self) => ({
|
|
@@ -31922,8 +32149,11 @@
|
|
|
31922
32149
|
const { filteredFeatureTypes, trackMenuItems: superTrackMenuItems } = self;
|
|
31923
32150
|
return {
|
|
31924
32151
|
trackMenuItems() {
|
|
31925
|
-
const { graphical, table, showCheckResults } = self;
|
|
31926
|
-
|
|
32152
|
+
const { graphical, table, showCheckResults, session } = self;
|
|
32153
|
+
const [region] = self.regions;
|
|
32154
|
+
const { assemblyName } = region;
|
|
32155
|
+
const backendDriver = session.apolloDataStore.getBackendDriver(assemblyName);
|
|
32156
|
+
const items = [
|
|
31927
32157
|
...superTrackMenuItems(),
|
|
31928
32158
|
{
|
|
31929
32159
|
type: 'subMenu',
|
|
@@ -31975,7 +32205,7 @@
|
|
|
31975
32205
|
{
|
|
31976
32206
|
label: 'Filter features by type',
|
|
31977
32207
|
onClick: () => {
|
|
31978
|
-
const session = self
|
|
32208
|
+
const { session } = self;
|
|
31979
32209
|
self.session.queueDialog((doneCallback) => [
|
|
31980
32210
|
FilterFeatures,
|
|
31981
32211
|
{
|
|
@@ -31991,76 +32221,93 @@
|
|
|
31991
32221
|
]);
|
|
31992
32222
|
},
|
|
31993
32223
|
},
|
|
31994
|
-
|
|
31995
|
-
|
|
31996
|
-
|
|
32224
|
+
];
|
|
32225
|
+
if (backendDriver instanceof LocalDriver) {
|
|
32226
|
+
items.push({
|
|
32227
|
+
label: 'Import annotations',
|
|
32228
|
+
icon: InputIcon,
|
|
31997
32229
|
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
32230
|
session.queueDialog((doneCallback) => [
|
|
32006
|
-
|
|
32231
|
+
ImportAnnotations,
|
|
32007
32232
|
{
|
|
32008
32233
|
session,
|
|
32234
|
+
assemblyName,
|
|
32009
32235
|
handleClose: () => {
|
|
32010
32236
|
doneCallback();
|
|
32011
32237
|
},
|
|
32012
|
-
assembly,
|
|
32013
32238
|
},
|
|
32014
32239
|
]);
|
|
32015
32240
|
},
|
|
32241
|
+
});
|
|
32242
|
+
}
|
|
32243
|
+
items.push({
|
|
32244
|
+
label: 'Export annotations',
|
|
32245
|
+
icon: Export,
|
|
32246
|
+
onClick: () => {
|
|
32247
|
+
const [region] = self.regions;
|
|
32248
|
+
const { assemblyName } = region;
|
|
32249
|
+
const assembly = self.getAssemblyId(assemblyName);
|
|
32250
|
+
if (!assembly) {
|
|
32251
|
+
return;
|
|
32252
|
+
}
|
|
32253
|
+
const { session } = self;
|
|
32254
|
+
session.queueDialog((doneCallback) => [
|
|
32255
|
+
DownloadGFF3,
|
|
32256
|
+
{
|
|
32257
|
+
session,
|
|
32258
|
+
handleClose: () => {
|
|
32259
|
+
doneCallback();
|
|
32260
|
+
},
|
|
32261
|
+
assembly,
|
|
32262
|
+
},
|
|
32263
|
+
]);
|
|
32016
32264
|
},
|
|
32017
|
-
|
|
32018
|
-
|
|
32019
|
-
|
|
32020
|
-
|
|
32021
|
-
|
|
32022
|
-
|
|
32023
|
-
|
|
32024
|
-
|
|
32025
|
-
|
|
32026
|
-
|
|
32027
|
-
|
|
32028
|
-
|
|
32029
|
-
|
|
32030
|
-
|
|
32031
|
-
|
|
32032
|
-
|
|
32033
|
-
|
|
32034
|
-
},
|
|
32035
|
-
assembly,
|
|
32265
|
+
}, {
|
|
32266
|
+
label: 'View Change Log',
|
|
32267
|
+
icon: TrackChangesIcon,
|
|
32268
|
+
onClick: () => {
|
|
32269
|
+
const [region] = self.regions;
|
|
32270
|
+
const { assemblyName } = region;
|
|
32271
|
+
const assembly = self.getAssemblyId(assemblyName);
|
|
32272
|
+
if (!assembly) {
|
|
32273
|
+
return;
|
|
32274
|
+
}
|
|
32275
|
+
const { session } = self;
|
|
32276
|
+
session.queueDialog((doneCallback) => [
|
|
32277
|
+
ViewChangeLog,
|
|
32278
|
+
{
|
|
32279
|
+
session,
|
|
32280
|
+
handleClose: () => {
|
|
32281
|
+
doneCallback();
|
|
32036
32282
|
},
|
|
32037
|
-
|
|
32038
|
-
|
|
32283
|
+
assembly,
|
|
32284
|
+
},
|
|
32285
|
+
]);
|
|
32039
32286
|
},
|
|
32040
|
-
|
|
32041
|
-
|
|
32042
|
-
|
|
32043
|
-
|
|
32044
|
-
|
|
32045
|
-
|
|
32046
|
-
|
|
32047
|
-
|
|
32048
|
-
|
|
32049
|
-
|
|
32050
|
-
|
|
32051
|
-
|
|
32052
|
-
|
|
32053
|
-
|
|
32054
|
-
|
|
32055
|
-
|
|
32056
|
-
|
|
32057
|
-
},
|
|
32058
|
-
assembly,
|
|
32287
|
+
}, {
|
|
32288
|
+
label: 'View Check Results',
|
|
32289
|
+
icon: FactCheckIcon,
|
|
32290
|
+
onClick: () => {
|
|
32291
|
+
const [region] = self.regions;
|
|
32292
|
+
const { assemblyName } = region;
|
|
32293
|
+
const assembly = self.getAssemblyId(assemblyName);
|
|
32294
|
+
if (!assembly) {
|
|
32295
|
+
return;
|
|
32296
|
+
}
|
|
32297
|
+
const { session } = self;
|
|
32298
|
+
session.queueDialog((doneCallback) => [
|
|
32299
|
+
ViewCheckResults,
|
|
32300
|
+
{
|
|
32301
|
+
session,
|
|
32302
|
+
handleClose: () => {
|
|
32303
|
+
doneCallback();
|
|
32059
32304
|
},
|
|
32060
|
-
|
|
32061
|
-
|
|
32305
|
+
assembly,
|
|
32306
|
+
},
|
|
32307
|
+
]);
|
|
32062
32308
|
},
|
|
32063
|
-
|
|
32309
|
+
});
|
|
32310
|
+
return items;
|
|
32064
32311
|
},
|
|
32065
32312
|
};
|
|
32066
32313
|
})
|
|
@@ -33126,8 +33373,7 @@
|
|
|
33126
33373
|
return internetAccounts.find((ia) => configuration.getConf(ia, 'internetAccountId') === internetAccountConfigId);
|
|
33127
33374
|
},
|
|
33128
33375
|
get changeManager() {
|
|
33129
|
-
return self.session.apolloDataStore
|
|
33130
|
-
.changeManager;
|
|
33376
|
+
return self.session.apolloDataStore.changeManager;
|
|
33131
33377
|
},
|
|
33132
33378
|
getAssemblyId(assemblyName) {
|
|
33133
33379
|
const { assemblyManager } = self.session;
|
|
@@ -33138,12 +33384,10 @@
|
|
|
33138
33384
|
return assembly.name;
|
|
33139
33385
|
},
|
|
33140
33386
|
get selectedFeature() {
|
|
33141
|
-
return self.session
|
|
33142
|
-
.apolloSelectedFeature;
|
|
33387
|
+
return self.session.apolloSelectedFeature;
|
|
33143
33388
|
},
|
|
33144
33389
|
get hoveredFeature() {
|
|
33145
|
-
return self.session
|
|
33146
|
-
.apolloHoveredFeature;
|
|
33390
|
+
return self.session.apolloHoveredFeature;
|
|
33147
33391
|
},
|
|
33148
33392
|
get height() {
|
|
33149
33393
|
const { sequenceRowHeight } = self;
|
|
@@ -33355,11 +33599,9 @@
|
|
|
33355
33599
|
onUpdate(newForms);
|
|
33356
33600
|
setExcludedTranscripts(newForms);
|
|
33357
33601
|
};
|
|
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: () => {
|
|
33602
|
+
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
33603
|
handleChange(item);
|
|
33362
|
-
}, slotProps: { input: { 'aria-label': 'controlled' } } }), label: item }))) }) }) })] }) }));
|
|
33604
|
+
}, slotProps: { input: { 'aria-label': 'controlled' } } }), label: item }, item))) }) }) })] }) }));
|
|
33363
33605
|
});
|
|
33364
33606
|
|
|
33365
33607
|
let forwardFillLight = null;
|
|
@@ -34205,8 +34447,7 @@
|
|
|
34205
34447
|
return internetAccounts.find((ia) => configuration.getConf(ia, 'internetAccountId') === internetAccountConfigId);
|
|
34206
34448
|
},
|
|
34207
34449
|
get changeManager() {
|
|
34208
|
-
return self.session.apolloDataStore
|
|
34209
|
-
.changeManager;
|
|
34450
|
+
return self.session.apolloDataStore.changeManager;
|
|
34210
34451
|
},
|
|
34211
34452
|
getAssemblyId(assemblyName) {
|
|
34212
34453
|
const { assemblyManager } = self.session;
|
|
@@ -34217,12 +34458,10 @@
|
|
|
34217
34458
|
return assembly.name;
|
|
34218
34459
|
},
|
|
34219
34460
|
get selectedFeature() {
|
|
34220
|
-
return self.session
|
|
34221
|
-
.apolloSelectedFeature;
|
|
34461
|
+
return self.session.apolloSelectedFeature;
|
|
34222
34462
|
},
|
|
34223
34463
|
get hoveredFeature() {
|
|
34224
|
-
return self.session
|
|
34225
|
-
.apolloHoveredFeature;
|
|
34464
|
+
return self.session.apolloHoveredFeature;
|
|
34226
34465
|
},
|
|
34227
34466
|
}))
|
|
34228
34467
|
.actions((self) => ({
|
|
@@ -34350,7 +34589,7 @@
|
|
|
34350
34589
|
{
|
|
34351
34590
|
label: 'Filter features by type',
|
|
34352
34591
|
onClick: () => {
|
|
34353
|
-
const session = self
|
|
34592
|
+
const { session } = self;
|
|
34354
34593
|
self.session.queueDialog((doneCallback) => [
|
|
34355
34594
|
FilterFeatures,
|
|
34356
34595
|
{
|
|
@@ -34788,17 +35027,12 @@
|
|
|
34788
35027
|
if (!featureTypeOntology) {
|
|
34789
35028
|
throw new Error('featureTypeOntology is undefined');
|
|
34790
35029
|
}
|
|
34791
|
-
|
|
34792
|
-
|
|
34793
|
-
foundFeature = layoutRow.find((f) => f.feature.type == 'exon' &&
|
|
35030
|
+
const foundFeature = self.geneTrackRowNums.includes(row)
|
|
35031
|
+
? layoutRow.find((f) => f.feature.type == 'exon' &&
|
|
34794
35032
|
bp >= f.feature.min &&
|
|
34795
|
-
bp <= f.feature.max)
|
|
34796
|
-
|
|
34797
|
-
|
|
34798
|
-
}
|
|
34799
|
-
}
|
|
34800
|
-
else {
|
|
34801
|
-
foundFeature = layoutRow.find((f) => {
|
|
35033
|
+
bp <= f.feature.max) ??
|
|
35034
|
+
layoutRow.find((f) => bp >= f.feature.min && bp <= f.feature.max)
|
|
35035
|
+
: layoutRow.find((f) => {
|
|
34802
35036
|
const { feature } = f;
|
|
34803
35037
|
const featureID = feature.attributes.get('gff_id')?.toString();
|
|
34804
35038
|
const isTranscript = featureTypeOntology.isTypeOf(feature.type, 'transcript');
|
|
@@ -34820,7 +35054,6 @@
|
|
|
34820
35054
|
}
|
|
34821
35055
|
return false;
|
|
34822
35056
|
});
|
|
34823
|
-
}
|
|
34824
35057
|
if (!foundFeature) {
|
|
34825
35058
|
return mousePosition;
|
|
34826
35059
|
}
|
|
@@ -35143,27 +35376,33 @@
|
|
|
35143
35376
|
const [selectedDestinationFeature, setSelectedDestinationFeature] = React.useState();
|
|
35144
35377
|
const apolloAssembly = apolloSessionModel.apolloDataStore.assemblies.get(assembly.name);
|
|
35145
35378
|
const refSeq = apolloAssembly?.refSeqs.get(refSeqId);
|
|
35146
|
-
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
|
-
};
|
|
35379
|
+
const features = React.useMemo(() => refSeq?.getFeatures(region.start, region.end), [refSeq, region.start, region.end]);
|
|
35161
35380
|
React.useEffect(() => {
|
|
35381
|
+
const getDestinationFeatures = () => {
|
|
35382
|
+
const filteredFeatures = [];
|
|
35383
|
+
for (const f of features ?? []) {
|
|
35384
|
+
if (f.min > region.end || f.max < region.start) {
|
|
35385
|
+
continue;
|
|
35386
|
+
}
|
|
35387
|
+
// Destination feature should be of type gene
|
|
35388
|
+
if (featureTypeOntology?.isTypeOf(f.type, 'gene')) {
|
|
35389
|
+
const featureSnapshot = mobxStateTree.getSnapshot(f);
|
|
35390
|
+
filteredFeatures.push(featureSnapshot);
|
|
35391
|
+
}
|
|
35392
|
+
}
|
|
35393
|
+
return filteredFeatures;
|
|
35394
|
+
};
|
|
35162
35395
|
setErrorMessage('');
|
|
35163
|
-
const
|
|
35164
|
-
setDestinationFeatures(
|
|
35165
|
-
setSelectedDestinationFeature(
|
|
35166
|
-
}, [
|
|
35396
|
+
const destinationFeatures = getDestinationFeatures();
|
|
35397
|
+
setDestinationFeatures(destinationFeatures);
|
|
35398
|
+
setSelectedDestinationFeature(destinationFeatures[0]);
|
|
35399
|
+
}, [
|
|
35400
|
+
checkedChildrens,
|
|
35401
|
+
featureTypeOntology,
|
|
35402
|
+
features,
|
|
35403
|
+
parentFeatureChecked,
|
|
35404
|
+
region,
|
|
35405
|
+
]);
|
|
35167
35406
|
const handleParentFeatureCheck = (event) => {
|
|
35168
35407
|
const isChecked = event.target.checked;
|
|
35169
35408
|
setParentFeatureChecked(isChecked);
|
|
@@ -35443,8 +35682,21 @@
|
|
|
35443
35682
|
getAnnotationFeature(jbrowseFeature, refSeqId) {
|
|
35444
35683
|
const start = jbrowseFeature.get('start');
|
|
35445
35684
|
const end = jbrowseFeature.get('end');
|
|
35446
|
-
const strand = jbrowseFeature.get('strand');
|
|
35447
35685
|
const name = jbrowseFeature.get('name');
|
|
35686
|
+
let strand;
|
|
35687
|
+
const tags = jbrowseFeature.get('tags');
|
|
35688
|
+
const { ts, TS, XS } = tags;
|
|
35689
|
+
for (const tag of [ts, TS, XS]) {
|
|
35690
|
+
if (!strand && tag) {
|
|
35691
|
+
if ([1, '1', '+'].includes(tag)) {
|
|
35692
|
+
strand = 1;
|
|
35693
|
+
}
|
|
35694
|
+
else if ([-1, '-1', '-'].includes(tag)) {
|
|
35695
|
+
strand = -1;
|
|
35696
|
+
}
|
|
35697
|
+
}
|
|
35698
|
+
}
|
|
35699
|
+
strand ??= jbrowseFeature.get('strand');
|
|
35448
35700
|
const cigarData = jbrowseFeature.get('CIGAR');
|
|
35449
35701
|
const ops = parseCigar(cigarData);
|
|
35450
35702
|
let position = start;
|
|
@@ -35460,9 +35712,7 @@
|
|
|
35460
35712
|
case 'M':
|
|
35461
35713
|
case '=':
|
|
35462
35714
|
case 'X': {
|
|
35463
|
-
|
|
35464
|
-
currentExonStart = position;
|
|
35465
|
-
}
|
|
35715
|
+
currentExonStart ??= position;
|
|
35466
35716
|
position += len;
|
|
35467
35717
|
break;
|
|
35468
35718
|
}
|
|
@@ -35888,7 +36138,7 @@
|
|
|
35888
36138
|
: undefined, menuItems: contextMenuItems })] }))] }));
|
|
35889
36139
|
});
|
|
35890
36140
|
|
|
35891
|
-
const TrackLines = mobxReact.observer(function TrackLines({ model, hrStyle = { margin: 0, top: 0, color: 'black' }, idx
|
|
36141
|
+
const TrackLines = mobxReact.observer(function TrackLines({ model, hrStyle = { margin: 0, top: 0, color: 'black' }, idx, }) {
|
|
35892
36142
|
const { apolloRowHeight, highestRow, showFeatureLabels } = model;
|
|
35893
36143
|
const featureLabelSpacer = showFeatureLabels ? 2 : 1;
|
|
35894
36144
|
return (jsxRuntime.jsx("div", { style: {
|
|
@@ -35960,8 +36210,7 @@
|
|
|
35960
36210
|
regionNumber: idx,
|
|
35961
36211
|
})?.offsetPx ?? 0) - lgv.offsetPx;
|
|
35962
36212
|
const [feature] = checkResult.featureIds;
|
|
35963
|
-
if (!feature ||
|
|
35964
|
-
!feature.parent ||
|
|
36213
|
+
if (!feature?.parent ||
|
|
35965
36214
|
!looksLikeGene(feature.parent, session)) {
|
|
35966
36215
|
return null;
|
|
35967
36216
|
}
|
|
@@ -36229,18 +36478,15 @@
|
|
|
36229
36478
|
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
36479
|
}), 'Save');
|
|
36231
36480
|
|
|
36232
|
-
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
|
36233
36481
|
/* eslint-disable @typescript-eslint/no-confusing-void-expression */
|
|
36234
36482
|
const ApolloJobModel = mobxStateTree.types
|
|
36235
36483
|
.model('JobsManager', {})
|
|
36236
36484
|
.views((self) => ({
|
|
36237
36485
|
get jobStatusWidget() {
|
|
36238
36486
|
const { widgets } = util$1.getSession(self);
|
|
36239
|
-
|
|
36240
|
-
if (!jobStatusWidget) {
|
|
36487
|
+
const jobStatusWidget = widgets.get('JobsList') ??
|
|
36241
36488
|
// @ts-expect-error: addWidget function not detected on the session
|
|
36242
|
-
|
|
36243
|
-
}
|
|
36489
|
+
util$1.getSession(self).addWidget('JobsListWidget', 'JobsList');
|
|
36244
36490
|
return jobStatusWidget;
|
|
36245
36491
|
},
|
|
36246
36492
|
}))
|
|
@@ -36519,19 +36765,15 @@
|
|
|
36519
36765
|
continue;
|
|
36520
36766
|
}
|
|
36521
36767
|
const { assemblyName, refName } = region;
|
|
36522
|
-
|
|
36523
|
-
|
|
36524
|
-
assembly = self.assemblies.put({ _id: assemblyName, refSeqs: {} });
|
|
36525
|
-
}
|
|
36768
|
+
const assembly = self.assemblies.get(assemblyName) ??
|
|
36769
|
+
self.assemblies.put({ _id: assemblyName, refSeqs: {} });
|
|
36526
36770
|
const [firstFeature] = features;
|
|
36527
|
-
|
|
36528
|
-
|
|
36529
|
-
ref = assembly.refSeqs.put({
|
|
36771
|
+
const ref = assembly.refSeqs.get(firstFeature.refSeq) ??
|
|
36772
|
+
assembly.refSeqs.put({
|
|
36530
36773
|
_id: firstFeature.refSeq,
|
|
36531
36774
|
name: refName,
|
|
36532
36775
|
features: {},
|
|
36533
36776
|
});
|
|
36534
|
-
}
|
|
36535
36777
|
for (const feature of features) {
|
|
36536
36778
|
if (!ref.features.has(feature._id)) {
|
|
36537
36779
|
ref.features.put(feature);
|
|
@@ -36548,24 +36790,153 @@
|
|
|
36548
36790
|
}
|
|
36549
36791
|
const { refSeq, seq } = yield backendDriver.getSequence(region);
|
|
36550
36792
|
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
|
-
}
|
|
36793
|
+
const assembly = self.assemblies.get(assemblyName) ??
|
|
36794
|
+
self.assemblies.put({ _id: assemblyName, refSeqs: {} });
|
|
36795
|
+
const ref = assembly.refSeqs.get(refSeq) ??
|
|
36796
|
+
assembly.refSeqs.put({ _id: refSeq, name: refName, sequence: [] });
|
|
36563
36797
|
ref.addSequence({ start, stop: end, sequence: seq });
|
|
36564
36798
|
}
|
|
36565
36799
|
}),
|
|
36566
36800
|
}));
|
|
36567
36801
|
}
|
|
36568
36802
|
|
|
36803
|
+
function reassignIds(feature) {
|
|
36804
|
+
const newChildren = {};
|
|
36805
|
+
if (feature.children) {
|
|
36806
|
+
for (const child of Object.values(feature.children)) {
|
|
36807
|
+
const newChild = reassignIds(child);
|
|
36808
|
+
newChildren[newChild._id] = newChild;
|
|
36809
|
+
}
|
|
36810
|
+
}
|
|
36811
|
+
return {
|
|
36812
|
+
...feature,
|
|
36813
|
+
_id: new ObjectID().toHexString(),
|
|
36814
|
+
children: feature.children ? newChildren : undefined,
|
|
36815
|
+
};
|
|
36816
|
+
}
|
|
36817
|
+
function DuplicateFeatureDialog({ assemblyName, changeManager, existingFeature, featureSnapshot, handleClose, }) {
|
|
36818
|
+
const [choice, setChoice] = React.useState('keepExisting');
|
|
36819
|
+
const [errorMessage, setErrorMessage] = React.useState('');
|
|
36820
|
+
const [submitted, setSubmitted] = React.useState(false);
|
|
36821
|
+
const handleSubmit = async () => {
|
|
36822
|
+
setErrorMessage('');
|
|
36823
|
+
setSubmitted(true);
|
|
36824
|
+
try {
|
|
36825
|
+
if (choice === 'useNew') {
|
|
36826
|
+
const deleteChange = new DeleteFeatureChange({
|
|
36827
|
+
typeName: 'DeleteFeatureChange',
|
|
36828
|
+
assembly: assemblyName,
|
|
36829
|
+
changedIds: [existingFeature._id],
|
|
36830
|
+
deletedFeature: existingFeature,
|
|
36831
|
+
});
|
|
36832
|
+
await changeManager.submit(deleteChange);
|
|
36833
|
+
const addChange = new AddFeatureChange({
|
|
36834
|
+
typeName: 'AddFeatureChange',
|
|
36835
|
+
assembly: assemblyName,
|
|
36836
|
+
changedIds: [featureSnapshot._id],
|
|
36837
|
+
addedFeature: featureSnapshot,
|
|
36838
|
+
});
|
|
36839
|
+
await changeManager.submit(addChange);
|
|
36840
|
+
}
|
|
36841
|
+
else if (choice === 'keepBoth') {
|
|
36842
|
+
const newSnapshot = reassignIds(featureSnapshot);
|
|
36843
|
+
const addChange = new AddFeatureChange({
|
|
36844
|
+
typeName: 'AddFeatureChange',
|
|
36845
|
+
assembly: assemblyName,
|
|
36846
|
+
changedIds: [newSnapshot._id],
|
|
36847
|
+
addedFeature: newSnapshot,
|
|
36848
|
+
});
|
|
36849
|
+
await changeManager.submit(addChange);
|
|
36850
|
+
}
|
|
36851
|
+
handleClose();
|
|
36852
|
+
}
|
|
36853
|
+
catch (error) {
|
|
36854
|
+
setErrorMessage(String(error));
|
|
36855
|
+
setSubmitted(false);
|
|
36856
|
+
}
|
|
36857
|
+
};
|
|
36858
|
+
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) => {
|
|
36859
|
+
setChoice(e.target.value);
|
|
36860
|
+
}, 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" })] })] }));
|
|
36861
|
+
}
|
|
36862
|
+
|
|
36863
|
+
function fromUrlSafeBase64(urlSafeBase64) {
|
|
36864
|
+
let base64 = urlSafeBase64.replaceAll('-', '+').replaceAll('_', '/');
|
|
36865
|
+
const pad = base64.length % 4;
|
|
36866
|
+
if (pad) {
|
|
36867
|
+
base64 += '='.repeat(4 - pad);
|
|
36868
|
+
}
|
|
36869
|
+
return base64;
|
|
36870
|
+
}
|
|
36871
|
+
// Base64 decode + decompress
|
|
36872
|
+
async function decompress(encoded) {
|
|
36873
|
+
const binaryString = atob(encoded);
|
|
36874
|
+
// eslint-disable-next-line unicorn/prefer-code-point
|
|
36875
|
+
const bytes = Uint8Array.from(binaryString, (char) => char.charCodeAt(0));
|
|
36876
|
+
const stream = new Blob([bytes]).stream();
|
|
36877
|
+
const decompressionStream = new DecompressionStream('gzip');
|
|
36878
|
+
const decompressedStream = stream.pipeThrough(decompressionStream);
|
|
36879
|
+
const response = new Response(decompressedStream);
|
|
36880
|
+
const decompressed = await response.arrayBuffer();
|
|
36881
|
+
return JSON.parse(new TextDecoder().decode(decompressed));
|
|
36882
|
+
}
|
|
36883
|
+
async function handleApolloFeaturesUrlParam(encodedFeatures, apolloDataStore, assemblyManager, session) {
|
|
36884
|
+
const base64 = fromUrlSafeBase64(encodedFeatures);
|
|
36885
|
+
const decompressed = await decompress(base64);
|
|
36886
|
+
const featuresData = decompressed;
|
|
36887
|
+
for (const [assemblyName, featureSnapshots] of Object.entries(featuresData)) {
|
|
36888
|
+
const backendDriver = apolloDataStore.getBackendDriver(assemblyName);
|
|
36889
|
+
if (!(backendDriver instanceof LocalDriver)) {
|
|
36890
|
+
continue;
|
|
36891
|
+
}
|
|
36892
|
+
const assembly = (await assemblyManager.waitForAssembly(assemblyName));
|
|
36893
|
+
if (!assembly) {
|
|
36894
|
+
throw new Error(`Assembly not found: "${assemblyName}"`);
|
|
36895
|
+
}
|
|
36896
|
+
const { regions } = assembly;
|
|
36897
|
+
if (!regions) {
|
|
36898
|
+
throw new Error(`Assembly not found: "${assemblyName}"`);
|
|
36899
|
+
}
|
|
36900
|
+
const refNames = regions.map((r) => r.refName);
|
|
36901
|
+
const db = await openDb(assemblyName, refNames);
|
|
36902
|
+
for (const featureSnapshot of featureSnapshots) {
|
|
36903
|
+
const storeName = `features-${featureSnapshot.refSeq}`;
|
|
36904
|
+
const existing = (await db.get(storeName, featureSnapshot._id));
|
|
36905
|
+
if (existing === undefined) {
|
|
36906
|
+
const change = new AddFeatureChange({
|
|
36907
|
+
typeName: 'AddFeatureChange',
|
|
36908
|
+
assembly: assemblyName,
|
|
36909
|
+
changedIds: [featureSnapshot._id],
|
|
36910
|
+
addedFeature: featureSnapshot,
|
|
36911
|
+
});
|
|
36912
|
+
await apolloDataStore.changeManager.submit(change);
|
|
36913
|
+
}
|
|
36914
|
+
else {
|
|
36915
|
+
// get rid of undefined values in JSON
|
|
36916
|
+
// eslint-disable-next-line unicorn/prefer-structured-clone
|
|
36917
|
+
const existingFeature = JSON.parse(JSON.stringify(existing));
|
|
36918
|
+
if (!equal(featureSnapshot, existingFeature)) {
|
|
36919
|
+
await new Promise((resolve) => {
|
|
36920
|
+
session.queueDialog((doneCallback) => [
|
|
36921
|
+
DuplicateFeatureDialog,
|
|
36922
|
+
{
|
|
36923
|
+
featureSnapshot,
|
|
36924
|
+
existingFeature,
|
|
36925
|
+
assemblyName,
|
|
36926
|
+
changeManager: apolloDataStore.changeManager,
|
|
36927
|
+
handleClose: () => {
|
|
36928
|
+
doneCallback();
|
|
36929
|
+
resolve();
|
|
36930
|
+
},
|
|
36931
|
+
},
|
|
36932
|
+
]);
|
|
36933
|
+
});
|
|
36934
|
+
}
|
|
36935
|
+
}
|
|
36936
|
+
}
|
|
36937
|
+
}
|
|
36938
|
+
}
|
|
36939
|
+
|
|
36569
36940
|
/* eslint-disable @typescript-eslint/no-unnecessary-condition */
|
|
36570
36941
|
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
|
36571
36942
|
function extendSession(pluginManager, sessionModel) {
|
|
@@ -36651,8 +37022,7 @@
|
|
|
36651
37022
|
for (const block of dynamicBlocks.contentBlocks) {
|
|
36652
37023
|
const { assemblyName, end, refName, start } = block;
|
|
36653
37024
|
const assembly = self.apolloDataStore.assemblies.get(assemblyName);
|
|
36654
|
-
if (assembly
|
|
36655
|
-
assembly.backendDriverType === 'CollaborationServerDriver') {
|
|
37025
|
+
if (assembly?.backendDriverType === 'CollaborationServerDriver') {
|
|
36656
37026
|
locations.push({ assemblyName, refName, start, end });
|
|
36657
37027
|
}
|
|
36658
37028
|
}
|
|
@@ -36711,8 +37081,8 @@
|
|
|
36711
37081
|
for (const block of dynamicBlocks.contentBlocks) {
|
|
36712
37082
|
const { assemblyName, end, refName, start } = block;
|
|
36713
37083
|
const assembly = self.apolloDataStore.assemblies.get(assemblyName);
|
|
36714
|
-
if (assembly
|
|
36715
|
-
|
|
37084
|
+
if (assembly?.backendDriverType ===
|
|
37085
|
+
'CollaborationServerDriver') {
|
|
36716
37086
|
locations.push({ assemblyName, refName, start, end });
|
|
36717
37087
|
}
|
|
36718
37088
|
}
|
|
@@ -36832,6 +37202,37 @@
|
|
|
36832
37202
|
beforeDestroy() {
|
|
36833
37203
|
self.abortController.abort(new DOMException('Clean up Apollo session', 'AbortError'));
|
|
36834
37204
|
},
|
|
37205
|
+
}))
|
|
37206
|
+
.actions((self) => ({
|
|
37207
|
+
async afterCreate() {
|
|
37208
|
+
if (util$1.isElectron) {
|
|
37209
|
+
return;
|
|
37210
|
+
}
|
|
37211
|
+
const url = new URL(globalThis.location.href);
|
|
37212
|
+
const apolloFeatures = url.searchParams.get('apolloFeatures');
|
|
37213
|
+
if (!apolloFeatures) {
|
|
37214
|
+
return;
|
|
37215
|
+
}
|
|
37216
|
+
const { assemblyManager } = self;
|
|
37217
|
+
await handleApolloFeaturesUrlParam(apolloFeatures, self.apolloDataStore, assemblyManager, self);
|
|
37218
|
+
await new Promise((resolve) => setTimeout(resolve, 2000));
|
|
37219
|
+
const updatedURL = new URL(globalThis.location.href);
|
|
37220
|
+
updatedURL.searchParams.delete('apolloFeatures');
|
|
37221
|
+
globalThis.history.replaceState(null, '', updatedURL.toString());
|
|
37222
|
+
},
|
|
37223
|
+
afterAttach() {
|
|
37224
|
+
mobxStateTree.addDisposer(self, mobx.autorun((reaction) => {
|
|
37225
|
+
const { focusedViewId, activeWidgets } = self;
|
|
37226
|
+
if (!(focusedViewId && activeWidgets)) {
|
|
37227
|
+
return;
|
|
37228
|
+
}
|
|
37229
|
+
const trackSelector = activeWidgets.get('hierarchicalTrackSelector');
|
|
37230
|
+
// @ts-expect-error Don't have type for track selector
|
|
37231
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
|
37232
|
+
trackSelector?.setView(focusedViewId);
|
|
37233
|
+
reaction.dispose();
|
|
37234
|
+
}));
|
|
37235
|
+
},
|
|
36835
37236
|
}))
|
|
36836
37237
|
.views((self) => {
|
|
36837
37238
|
const superTrackActions = self
|
|
@@ -36963,7 +37364,6 @@
|
|
|
36963
37364
|
}
|
|
36964
37365
|
|
|
36965
37366
|
/* eslint-disable @typescript-eslint/unbound-method */
|
|
36966
|
-
/* eslint-disable @typescript-eslint/no-unnecessary-condition */
|
|
36967
37367
|
/* eslint-disable @typescript-eslint/no-misused-promises */
|
|
36968
37368
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
36969
37369
|
function isApolloMessageData(data) {
|
|
@@ -37151,10 +37551,10 @@
|
|
|
37151
37551
|
});
|
|
37152
37552
|
if (!inWebWorker) {
|
|
37153
37553
|
pluginManager.addToExtensionPoint('Core-extendWorker', (handle) => {
|
|
37154
|
-
if (!('on' in handle && handle.on)) {
|
|
37554
|
+
if (!('on' in handle.client && handle.client.on)) {
|
|
37155
37555
|
return handle;
|
|
37156
37556
|
}
|
|
37157
|
-
handle.on('apollo', async (event) => {
|
|
37557
|
+
handle.client.on('apollo', async (event) => {
|
|
37158
37558
|
if (!isApolloMessageData(event)) {
|
|
37159
37559
|
return;
|
|
37160
37560
|
}
|
|
@@ -37172,7 +37572,7 @@
|
|
|
37172
37572
|
break;
|
|
37173
37573
|
}
|
|
37174
37574
|
const { seq: sequence } = await backendDriver.getSequence(region);
|
|
37175
|
-
handle.
|
|
37575
|
+
handle.worker.postMessage({
|
|
37176
37576
|
apollo,
|
|
37177
37577
|
messageId,
|
|
37178
37578
|
sequence,
|
|
@@ -37190,7 +37590,7 @@
|
|
|
37190
37590
|
break;
|
|
37191
37591
|
}
|
|
37192
37592
|
const regions = await backendDriver.getRegions(assembly);
|
|
37193
|
-
handle.
|
|
37593
|
+
handle.worker.postMessage({
|
|
37194
37594
|
apollo,
|
|
37195
37595
|
messageId,
|
|
37196
37596
|
regions,
|
|
@@ -37208,7 +37608,7 @@
|
|
|
37208
37608
|
break;
|
|
37209
37609
|
}
|
|
37210
37610
|
const refNameAliases = await backendDriver.getRefNameAliases(assembly);
|
|
37211
|
-
handle.
|
|
37611
|
+
handle.worker.postMessage({
|
|
37212
37612
|
apollo,
|
|
37213
37613
|
messageId,
|
|
37214
37614
|
refNameAliases,
|