@opencloning/ui 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -0
- package/package.json +37 -0
- package/src/components/AppAlerts.jsx +19 -0
- package/src/components/CloningHistory.jsx +40 -0
- package/src/components/DataModelDisplayer.jsx +30 -0
- package/src/components/DescriptionEditor.jsx +68 -0
- package/src/components/DownloadCloningStrategyDialog.jsx +84 -0
- package/src/components/DownloadSequenceFileDialog.jsx +90 -0
- package/src/components/DragAndDropCloningHistoryWrapper.jsx +39 -0
- package/src/components/DraggableDialogPaper.jsx +16 -0
- package/src/components/EditSequenceNameDialog.jsx +90 -0
- package/src/components/ExternalServicesStatusCheck.jsx +92 -0
- package/src/components/HistoryLoadedDialog.jsx +49 -0
- package/src/components/LoadCloningHistoryWrapper.jsx +166 -0
- package/src/components/MainSequenceCheckBox.jsx +83 -0
- package/src/components/MainSequenceEditor.jsx +165 -0
- package/src/components/NetworkNode.jsx +159 -0
- package/src/components/NetworkTree.css +127 -0
- package/src/components/ObjectTable.jsx +24 -0
- package/src/components/OpenCloning.jsx +102 -0
- package/src/components/OverhangsDisplay.jsx +25 -0
- package/src/components/SequenceEditor.jsx +120 -0
- package/src/components/SequenceTab.jsx +14 -0
- package/src/components/TemplateSequence.jsx +38 -0
- package/src/components/annotation/PlannotateAnnotationReport.jsx +33 -0
- package/src/components/annotation/useUpdateAnnotationInMainSequence.js +39 -0
- package/src/components/assembler/AssemblePartWidget.jsx +252 -0
- package/src/components/assembler/Assembler.jsx +273 -0
- package/src/components/assembler/AssemblerPart.jsx +99 -0
- package/src/components/assembler/StopIcon.jsx +34 -0
- package/src/components/assembler/assembler_data2.json +50 -0
- package/src/components/assembler/assembly_component.module.css +81 -0
- package/src/components/assembler/moclo.json +110 -0
- package/src/components/assembler/sbol_visual_glyphs/LICENSE.html +21 -0
- package/src/components/assembler/sbol_visual_glyphs/assembly-scar.svg +63 -0
- package/src/components/assembler/sbol_visual_glyphs/cds-stop.svg +85 -0
- package/src/components/assembler/sbol_visual_glyphs/cds.svg +60 -0
- package/src/components/assembler/sbol_visual_glyphs/chromosomal-locus.svg +78 -0
- package/src/components/assembler/sbol_visual_glyphs/engineered-region.svg +56 -0
- package/src/components/assembler/sbol_visual_glyphs/five-prime-sticky-restriction-site.svg +56 -0
- package/src/components/assembler/sbol_visual_glyphs/origin-of-replication.svg +57 -0
- package/src/components/assembler/sbol_visual_glyphs/primer-binding-site.svg +59 -0
- package/src/components/assembler/sbol_visual_glyphs/promoter.svg +60 -0
- package/src/components/assembler/sbol_visual_glyphs/ribosome-entry-site.svg +56 -0
- package/src/components/assembler/sbol_visual_glyphs/specific-recombination-site.svg +59 -0
- package/src/components/assembler/sbol_visual_glyphs/terminator.svg +60 -0
- package/src/components/assembler/sbol_visual_glyphs/three-prime-sticky-restriction-site.svg +56 -0
- package/src/components/assembler/sbol_visual_glyphs.js +36 -0
- package/src/components/assembler/useAssembler.js +71 -0
- package/src/components/dummy/DummyInterface.js +41 -0
- package/src/components/dummy/GetSequenceFileAndDatabaseIdComponent.jsx +59 -0
- package/src/components/eLabFTW/ELabFTWCategorySelect.cy.jsx +86 -0
- package/src/components/eLabFTW/ELabFTWCategorySelect.jsx +43 -0
- package/src/components/eLabFTW/ELabFTWFileSelect.cy.jsx +43 -0
- package/src/components/eLabFTW/ELabFTWFileSelect.jsx +29 -0
- package/src/components/eLabFTW/ELabFTWResourceSelect.cy.jsx +107 -0
- package/src/components/eLabFTW/ELabFTWResourceSelect.jsx +23 -0
- package/src/components/eLabFTW/GetPrimerComponent.cy.jsx +261 -0
- package/src/components/eLabFTW/GetPrimerComponent.jsx +55 -0
- package/src/components/eLabFTW/GetSequenceFileAndDatabaseIdComponent.cy.jsx +184 -0
- package/src/components/eLabFTW/GetSequenceFileAndDatabaseIdComponent.jsx +62 -0
- package/src/components/eLabFTW/LoadHistoryComponent.cy.jsx +235 -0
- package/src/components/eLabFTW/LoadHistoryComponent.jsx +51 -0
- package/src/components/eLabFTW/PrimersNotInDatabaseComponent.cy.jsx +159 -0
- package/src/components/eLabFTW/PrimersNotInDatabaseComponent.jsx +54 -0
- package/src/components/eLabFTW/SubmitToDatabaseComponent.cy.jsx +185 -0
- package/src/components/eLabFTW/SubmitToDatabaseComponent.jsx +51 -0
- package/src/components/eLabFTW/common.js +26 -0
- package/src/components/eLabFTW/eLabFTWInterface.js +294 -0
- package/src/components/eLabFTW/eLabFTWInterface.test.js +839 -0
- package/src/components/eLabFTW/envValues.js +7 -0
- package/src/components/eLabFTW/utils.js +39 -0
- package/src/components/form/CustomFormHelperText.jsx +10 -0
- package/src/components/form/EnzymeMultiSelect.cy.jsx +61 -0
- package/src/components/form/EnzymeMultiSelect.jsx +34 -0
- package/src/components/form/GetRequestMultiSelect.jsx +107 -0
- package/src/components/form/LabelWithTooltip.jsx +16 -0
- package/src/components/form/PostRequestSelect.cy.jsx +70 -0
- package/src/components/form/PostRequestSelect.jsx +86 -0
- package/src/components/form/RequestStatusWrapper.jsx +17 -0
- package/src/components/form/RetryAlert.jsx +20 -0
- package/src/components/form/ServerErrorMessage.jsx +10 -0
- package/src/components/form/SubmitButtonBackendAPI.jsx +15 -0
- package/src/components/form/SubmitToDatabaseDialog.jsx +133 -0
- package/src/components/form/TextFieldValidate.jsx +67 -0
- package/src/components/form/ValidatedTextField.jsx +33 -0
- package/src/components/form/intermediates_disclaimer.svg +181 -0
- package/src/components/navigation/ButtonWithMenu.jsx +43 -0
- package/src/components/navigation/CustomTab.jsx +14 -0
- package/src/components/navigation/FeedbackDialog.jsx +34 -0
- package/src/components/navigation/GithubCornerRight.jsx +29 -0
- package/src/components/navigation/MainAppBar.css +26 -0
- package/src/components/navigation/MainAppBar.jsx +205 -0
- package/src/components/navigation/SelectExampleDialog.jsx +69 -0
- package/src/components/navigation/SelectTemplateDialog.jsx +107 -0
- package/src/components/navigation/TabPanel.jsx +28 -0
- package/src/components/navigation/VersionDialog.jsx +33 -0
- package/src/components/primers/CreatePrimerFromSequenceForm.jsx +42 -0
- package/src/components/primers/DownloadPrimersButton.jsx +104 -0
- package/src/components/primers/PrimerForm.css +14 -0
- package/src/components/primers/PrimerForm.jsx +107 -0
- package/src/components/primers/PrimerList.css +46 -0
- package/src/components/primers/PrimerList.cy.jsx +95 -0
- package/src/components/primers/PrimerList.jsx +126 -0
- package/src/components/primers/PrimerTableRow.cy.jsx +57 -0
- package/src/components/primers/PrimerTableRow.jsx +84 -0
- package/src/components/primers/SelectPrimerForm.jsx +66 -0
- package/src/components/primers/import_primers/ImportPrimersButton.jsx +101 -0
- package/src/components/primers/import_primers/ImportPrimersTable.jsx +51 -0
- package/src/components/primers/import_primers/PrimerDatabaseImportForm.jsx +107 -0
- package/src/components/primers/import_primers/styles.css +60 -0
- package/src/components/primers/primer_design/SequenceTabComponents/CollapsableLabel.jsx +31 -0
- package/src/components/primers/primer_design/SequenceTabComponents/GatewayRoiSelect.jsx +164 -0
- package/src/components/primers/primer_design/SequenceTabComponents/OrientationPicker.jsx +37 -0
- package/src/components/primers/primer_design/SequenceTabComponents/PrimerDesignContext.jsx +369 -0
- package/src/components/primers/primer_design/SequenceTabComponents/PrimerDesignEBIC.jsx +24 -0
- package/src/components/primers/primer_design/SequenceTabComponents/PrimerDesignForm.jsx +29 -0
- package/src/components/primers/primer_design/SequenceTabComponents/PrimerDesignGatewayBP.jsx +36 -0
- package/src/components/primers/primer_design/SequenceTabComponents/PrimerDesignGibsonAssembly.jsx +26 -0
- package/src/components/primers/primer_design/SequenceTabComponents/PrimerDesignHomologousRecombination.jsx +32 -0
- package/src/components/primers/primer_design/SequenceTabComponents/PrimerDesignRestriction.jsx +25 -0
- package/src/components/primers/primer_design/SequenceTabComponents/PrimerDesignSimplePair.jsx +25 -0
- package/src/components/primers/primer_design/SequenceTabComponents/PrimerDesignStepper.jsx +53 -0
- package/src/components/primers/primer_design/SequenceTabComponents/PrimerDesigner.jsx +80 -0
- package/src/components/primers/primer_design/SequenceTabComponents/PrimerResultForm.jsx +49 -0
- package/src/components/primers/primer_design/SequenceTabComponents/PrimerSettingsForm.jsx +68 -0
- package/src/components/primers/primer_design/SequenceTabComponents/PrimerSpacerForm.jsx +84 -0
- package/src/components/primers/primer_design/SequenceTabComponents/RestrictionSpacerForm.jsx +85 -0
- package/src/components/primers/primer_design/SequenceTabComponents/StepNavigation.jsx +48 -0
- package/src/components/primers/primer_design/SequenceTabComponents/TabPanelEBICSettings.jsx +216 -0
- package/src/components/primers/primer_design/SequenceTabComponents/TabPanelResults.jsx +42 -0
- package/src/components/primers/primer_design/SequenceTabComponents/TabPanelSelectRoi.jsx +61 -0
- package/src/components/primers/primer_design/SequenceTabComponents/TabPannelSettings.jsx +59 -0
- package/src/components/primers/primer_design/SequenceTabComponents/primerDesignMinimalValues.json +5 -0
- package/src/components/primers/primer_design/SequenceTabComponents/useEBICPrimerDesignSettings.js +31 -0
- package/src/components/primers/primer_design/SequenceTabComponents/useEnzymePrimerDesignSettings.js +57 -0
- package/src/components/primers/primer_design/SequenceTabComponents/useGatewayPrimerDesignSettings.js +18 -0
- package/src/components/primers/primer_design/SequenceTabComponents/usePrimerDesignSettings.js +31 -0
- package/src/components/primers/primer_design/SourceComponents/PrimerDesignGatewayBP.jsx +88 -0
- package/src/components/primers/primer_design/SourceComponents/PrimerDesignGibsonAssembly.jsx +65 -0
- package/src/components/primers/primer_design/SourceComponents/PrimerDesignHomologousRecombination.jsx +84 -0
- package/src/components/primers/primer_design/SourceComponents/PrimerDesignSourceForm.jsx +74 -0
- package/src/components/primers/primer_design/common/NoAttPSitesError.jsx +31 -0
- package/src/components/primers/primer_details/PCRTable.cy.jsx +51 -0
- package/src/components/primers/primer_details/PCRTable.jsx +35 -0
- package/src/components/primers/primer_details/Primer3Figure.jsx +25 -0
- package/src/components/primers/primer_details/PrimerDetailsTds.jsx +39 -0
- package/src/components/primers/primer_details/PrimerInfoIcon.cy.jsx +137 -0
- package/src/components/primers/primer_details/PrimerInfoIcon.jsx +132 -0
- package/src/components/primers/primer_details/TableSection.jsx +17 -0
- package/src/components/primers/primer_details/primerDetailsFormatting.js +3 -0
- package/src/components/primers/primer_details/useMultiplePrimerDetails.js +29 -0
- package/src/components/primers/primer_details/usePCRDetails.js +47 -0
- package/src/components/primers/primer_details/usePrimerDetailsEndpoints.js +49 -0
- package/src/components/primers/primer_details/useSinglePrimerSequenceDetails.js +25 -0
- package/src/components/primers/primersToTabularFile.js +49 -0
- package/src/components/primers/primersToTabularFile.test.js +108 -0
- package/src/components/settings/SettingsTab.cy.jsx +267 -0
- package/src/components/settings/SettingsTab.jsx +170 -0
- package/src/components/sources/AssemblyPlanDisplayer.cy.jsx +22 -0
- package/src/components/sources/AssemblyPlanDisplayer.jsx +27 -0
- package/src/components/sources/CollectionSource.jsx +97 -0
- package/src/components/sources/FinishedSource.jsx +397 -0
- package/src/components/sources/KnownSourceErrors.jsx +50 -0
- package/src/components/sources/MultipleInputsSelector.jsx +63 -0
- package/src/components/sources/MultipleOutputsSelector.jsx +63 -0
- package/src/components/sources/NewSourceBox.jsx +37 -0
- package/src/components/sources/PCRUnitForm.jsx +102 -0
- package/src/components/sources/SingleInputSelector.jsx +36 -0
- package/src/components/sources/Source.jsx +125 -0
- package/src/components/sources/SourceAnnotation.jsx +44 -0
- package/src/components/sources/SourceAssembly.jsx +201 -0
- package/src/components/sources/SourceBox.css +18 -0
- package/src/components/sources/SourceBox.jsx +60 -0
- package/src/components/sources/SourceCopySequence.jsx +38 -0
- package/src/components/sources/SourceDatabase.jsx +28 -0
- package/src/components/sources/SourceFile.jsx +188 -0
- package/src/components/sources/SourceGenomeRegion.cy.jsx +131 -0
- package/src/components/sources/SourceGenomeRegion.jsx +486 -0
- package/src/components/sources/SourceHomologousRecombination.jsx +125 -0
- package/src/components/sources/SourceKnownGenomeRegion.jsx +60 -0
- package/src/components/sources/SourceManuallyTyped.jsx +116 -0
- package/src/components/sources/SourcePCRorHybridization.jsx +165 -0
- package/src/components/sources/SourcePolymeraseExtension.jsx +44 -0
- package/src/components/sources/SourceRepositoryId.jsx +409 -0
- package/src/components/sources/SourceRestriction.jsx +41 -0
- package/src/components/sources/SourceReverseComplement.jsx +33 -0
- package/src/components/sources/SourceTypeSelector.jsx +94 -0
- package/src/components/sources/SubSequenceDisplayer.jsx +70 -0
- package/src/components/sources/VerifyDeleteDialog.jsx +23 -0
- package/src/components/sources/repositoryMetadata.js +14 -0
- package/src/components/verification/LoadFromDatabaseButton.jsx +90 -0
- package/src/components/verification/SequencingFileRow.jsx +34 -0
- package/src/components/verification/VerificationFileDialog.cy.jsx +176 -0
- package/src/components/verification/VerificationFileDialog.jsx +248 -0
- package/src/config/defaultMainEditorProps.js +44 -0
- package/src/hooks/useAlerts.js +16 -0
- package/src/hooks/useBackendAPI.js +51 -0
- package/src/hooks/useBackendRoute.js +22 -0
- package/src/hooks/useDatabase.js +18 -0
- package/src/hooks/useDragAndDropFile.js +31 -0
- package/src/hooks/useGatewaySites.js +40 -0
- package/src/hooks/useHttpClient.js +12 -0
- package/src/hooks/useLoadDatabaseFile.js +108 -0
- package/src/hooks/useStoreEditor.js +101 -0
- package/src/hooks/useValidateState.js +43 -0
- package/vitest.config.js +18 -0
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import FormHelperText from '@mui/material/FormHelperText';
|
|
3
|
+
import { Alert, Checkbox, FormControl, FormControlLabel, InputLabel, MenuItem, Select, TextField } from '@mui/material';
|
|
4
|
+
import { useDispatch, batch, useStore, useSelector } from 'react-redux';
|
|
5
|
+
import SubmitButtonBackendAPI from '../form/SubmitButtonBackendAPI';
|
|
6
|
+
import LabelWithTooltip from '../form/LabelWithTooltip';
|
|
7
|
+
import { cloningActions } from '@opencloning/store/cloning';
|
|
8
|
+
import { loadFilesToSessionStorage, loadHistoryFile, updateVerificationFileNames } from '@opencloning/utils/readNwrite';
|
|
9
|
+
import useValidateState from '../../hooks/useValidateState';
|
|
10
|
+
import { mergeStates, getGraftSequenceId, graftState } from '@opencloning/utils/network';
|
|
11
|
+
|
|
12
|
+
const { deleteSourceAndItsChildren, restoreSource, setState: setCloningState } = cloningActions;
|
|
13
|
+
|
|
14
|
+
const fileFormatToExtension = {
|
|
15
|
+
genbank: 'gb',
|
|
16
|
+
fasta: 'fasta',
|
|
17
|
+
snapgene: 'dna',
|
|
18
|
+
embl: 'embl',
|
|
19
|
+
json: 'json',
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
// A component providing an interface to import a file
|
|
23
|
+
function SourceFile({ source, requestStatus, sendPostRequest }) {
|
|
24
|
+
const [circularize, setCircularize] = React.useState(false);
|
|
25
|
+
const [showCoordinates, setShowCoordinates] = React.useState(false);
|
|
26
|
+
const [coordinates, setCoordinates] = React.useState({ start: null, end: null });
|
|
27
|
+
const [fileFormat, setFileFormat] = React.useState('');
|
|
28
|
+
const hasOutput = useSelector((state) => state.cloning.sequences.some((s) => s.id === source.id));
|
|
29
|
+
// Error message for json only
|
|
30
|
+
const [alert, setAlert] = React.useState(null);
|
|
31
|
+
const dispatch = useDispatch();
|
|
32
|
+
const validateState = useValidateState();
|
|
33
|
+
const store = useStore();
|
|
34
|
+
|
|
35
|
+
const onChange = async (event) => {
|
|
36
|
+
setAlert(null);
|
|
37
|
+
const files = Array.from(event.target.files);
|
|
38
|
+
if (files.length === 0) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
event.target.value = null;
|
|
42
|
+
// If the file is a history file, we load it
|
|
43
|
+
if (
|
|
44
|
+
fileFormat === 'json' || fileFormat === 'zip'
|
|
45
|
+
|| (fileFormat === '' && (files[0].name.endsWith('.json') || files[0].name.endsWith('.zip')))
|
|
46
|
+
) {
|
|
47
|
+
// If file format is explicitly set, rename file to match that extension
|
|
48
|
+
if (fileFormat) {
|
|
49
|
+
files[0] = new File([files[0]], files[0].name.replace(/\.[^/.]+$/, `.${fileFormatToExtension[fileFormat]}`), {
|
|
50
|
+
type: fileFormat === 'json' ? 'application/json' : files[0].type,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
let cloningStrategy;
|
|
54
|
+
let verificationFiles;
|
|
55
|
+
try {
|
|
56
|
+
({ cloningStrategy, verificationFiles } = await loadHistoryFile(files[0]));
|
|
57
|
+
} catch (e) {
|
|
58
|
+
console.error(e);
|
|
59
|
+
setAlert({ message: e.message, severity: 'error' });
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const validatedCloningStrategy = await validateState(cloningStrategy);
|
|
64
|
+
// Update the verificationFiles names if needed
|
|
65
|
+
const updatedVerificationFiles = updateVerificationFileNames(verificationFiles, cloningStrategy.files, validatedCloningStrategy.files);
|
|
66
|
+
|
|
67
|
+
const canGraft = getGraftSequenceId(validatedCloningStrategy) !== null;
|
|
68
|
+
const graft = hasOutput && canGraft;
|
|
69
|
+
|
|
70
|
+
if (hasOutput && !canGraft) {
|
|
71
|
+
setAlert({ message: 'Cannot graft cloning strategy as it does not converge on a single sequence, you can load it on a source without outputs', severity: 'error' });
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
batch(async () => {
|
|
76
|
+
if (!graft) {
|
|
77
|
+
// Replace the source with the new one
|
|
78
|
+
dispatch(deleteSourceAndItsChildren(source.id));
|
|
79
|
+
}
|
|
80
|
+
try {
|
|
81
|
+
const cloningState = store.getState().cloning;
|
|
82
|
+
let mergedState;
|
|
83
|
+
let idShift;
|
|
84
|
+
if (graft) {
|
|
85
|
+
({ mergedState, idShift } = graftState(validatedCloningStrategy, cloningState, source.id));
|
|
86
|
+
} else {
|
|
87
|
+
({ mergedState, idShift } = mergeStates(validatedCloningStrategy, cloningState));
|
|
88
|
+
}
|
|
89
|
+
dispatch(setCloningState(mergedState));
|
|
90
|
+
await loadFilesToSessionStorage(updatedVerificationFiles, idShift);
|
|
91
|
+
} catch (e) {
|
|
92
|
+
setAlert({ message: e.message, severity: 'error' });
|
|
93
|
+
dispatch(restoreSource({ ...source, type: 'UploadedFileSource' }));
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
const requestData = new FormData();
|
|
99
|
+
requestData.append('file', files[0]);
|
|
100
|
+
const config = {
|
|
101
|
+
headers: {
|
|
102
|
+
'content-type': 'multipart/form-data',
|
|
103
|
+
},
|
|
104
|
+
params: { circularize, sequence_file_format: fileFormat || null, ...coordinates },
|
|
105
|
+
};
|
|
106
|
+
sendPostRequest({ endpoint: 'read_from_file', requestData, config, source });
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
const updateCoordinates = (value, isStart) => {
|
|
110
|
+
setCoordinates((prev) => ({ ...prev, [isStart ? 'start' : 'end']: value }));
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
const onShowCoordinatesChange = () => {
|
|
114
|
+
const newShowCoordinates = !showCoordinates;
|
|
115
|
+
setShowCoordinates(newShowCoordinates);
|
|
116
|
+
if (!newShowCoordinates) {
|
|
117
|
+
setCoordinates({ start: null, end: null });
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
return (
|
|
122
|
+
<form className="submit-sequence-file" onSubmit={(e) => e.preventDefault()}>
|
|
123
|
+
<FormControl fullWidth>
|
|
124
|
+
<InputLabel id="select-file-format" shrink>File format</InputLabel>
|
|
125
|
+
<Select
|
|
126
|
+
labelId="select-file-format"
|
|
127
|
+
id="select-file-format"
|
|
128
|
+
value={fileFormat}
|
|
129
|
+
onChange={(e) => setFileFormat(e.target.value)}
|
|
130
|
+
label="File format"
|
|
131
|
+
displayEmpty
|
|
132
|
+
>
|
|
133
|
+
<MenuItem value="">Guess from extension</MenuItem>
|
|
134
|
+
<MenuItem value="genbank">Genbank / Ape</MenuItem>
|
|
135
|
+
<MenuItem value="fasta">FASTA</MenuItem>
|
|
136
|
+
<MenuItem value="snapgene">SnapGene (.dna)</MenuItem>
|
|
137
|
+
<MenuItem value="embl">EMBL</MenuItem>
|
|
138
|
+
<MenuItem value="json">JSON (history file)</MenuItem>
|
|
139
|
+
<MenuItem value="zip">Zip (history folder)</MenuItem>
|
|
140
|
+
</Select>
|
|
141
|
+
</FormControl>
|
|
142
|
+
|
|
143
|
+
<FormControl fullWidth>
|
|
144
|
+
<FormControlLabel
|
|
145
|
+
control={<Checkbox checked={circularize} onChange={() => setCircularize(!circularize)} />}
|
|
146
|
+
label={<LabelWithTooltip label="Circularize" tooltip="Make the sequence circular (for GenBank or Snapgene files, it will override the topology indicated in the file)" />}
|
|
147
|
+
/>
|
|
148
|
+
<FormControlLabel
|
|
149
|
+
control={<Checkbox checked={showCoordinates} onChange={onShowCoordinatesChange} />}
|
|
150
|
+
label={<LabelWithTooltip label="Extract subsequence" tooltip="Does not work with JSON or Zip files" />}
|
|
151
|
+
/>
|
|
152
|
+
{showCoordinates && (
|
|
153
|
+
<FormControl fullWidth className="extract-subsequence">
|
|
154
|
+
<TextField
|
|
155
|
+
label="Start"
|
|
156
|
+
value={coordinates.start}
|
|
157
|
+
onChange={(e) => updateCoordinates(e.target.value, true)}
|
|
158
|
+
type="number"
|
|
159
|
+
/>
|
|
160
|
+
<TextField
|
|
161
|
+
label="End"
|
|
162
|
+
value={coordinates.end}
|
|
163
|
+
onChange={(e) => updateCoordinates(e.target.value, false)}
|
|
164
|
+
type="number"
|
|
165
|
+
/>
|
|
166
|
+
</FormControl>
|
|
167
|
+
)}
|
|
168
|
+
</FormControl>
|
|
169
|
+
|
|
170
|
+
{alert && (<Alert sx={{ marginTop: '10px' }} severity={alert.severity}>{alert.message}</Alert>)}
|
|
171
|
+
<SubmitButtonBackendAPI
|
|
172
|
+
component="label"
|
|
173
|
+
requestStatus={requestStatus}
|
|
174
|
+
{...(import.meta.env.VITE_UMAMI_WEBSITE_ID && { "data-umami-event": "submit-file" })}
|
|
175
|
+
>
|
|
176
|
+
Select File
|
|
177
|
+
<input
|
|
178
|
+
type="file"
|
|
179
|
+
hidden
|
|
180
|
+
onChange={onChange}
|
|
181
|
+
/>
|
|
182
|
+
</SubmitButtonBackendAPI>
|
|
183
|
+
<FormHelperText>Supports .gb, .dna, .embl, .fasta, .fa, .ape</FormHelperText>
|
|
184
|
+
</form>
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
export default SourceFile;
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { AssemblyIdSelector, SpeciesPicker, SequenceAccessionPicker, } from './SourceGenomeRegion';
|
|
3
|
+
|
|
4
|
+
describe('<AssemblyIdSelector />', () => {
|
|
5
|
+
it('can propose a paired accession if the assembly has no annotation', () => {
|
|
6
|
+
const setAssemblyId = cy.spy().as('setAssemblyId');
|
|
7
|
+
const setHasAnnotation = cy.spy().as('setHasAnnotation');
|
|
8
|
+
const onAssemblyIdChange = cy.spy().as('onAssemblyIdChange');
|
|
9
|
+
|
|
10
|
+
cy.intercept('GET', 'https://api.ncbi.nlm.nih.gov/datasets/v2alpha/genome/accession/GCA_000002945.3/dataset_report*', {
|
|
11
|
+
statusCode: 200,
|
|
12
|
+
body: {
|
|
13
|
+
reports: [{
|
|
14
|
+
accession: 'GCA_000002945.3',
|
|
15
|
+
organism: {
|
|
16
|
+
tax_id: 559292,
|
|
17
|
+
organism_name: 'Saccharomyces cerevisiae'
|
|
18
|
+
},
|
|
19
|
+
annotation_info: undefined,
|
|
20
|
+
paired_accession: 'GCF_000002945.3',
|
|
21
|
+
assembly_info: {
|
|
22
|
+
assembly_status: 'current'
|
|
23
|
+
}
|
|
24
|
+
}]
|
|
25
|
+
}
|
|
26
|
+
}).as('getAssemblyInfo');
|
|
27
|
+
|
|
28
|
+
cy.intercept('GET', 'https://api.ncbi.nlm.nih.gov/datasets/v2alpha/genome/accession/GCF_000002945.3/dataset_report*', {
|
|
29
|
+
statusCode: 200,
|
|
30
|
+
body: {
|
|
31
|
+
reports: [{
|
|
32
|
+
accession: 'GCF_000002945.3',
|
|
33
|
+
organism: {
|
|
34
|
+
tax_id: 559292,
|
|
35
|
+
organism_name: 'Saccharomyces cerevisiae'
|
|
36
|
+
},
|
|
37
|
+
annotation_info: {},
|
|
38
|
+
assembly_info: {
|
|
39
|
+
assembly_status: 'current'
|
|
40
|
+
}
|
|
41
|
+
}]
|
|
42
|
+
}
|
|
43
|
+
}).as('getPairedAssemblyInfo');
|
|
44
|
+
|
|
45
|
+
cy.mount(
|
|
46
|
+
<AssemblyIdSelector
|
|
47
|
+
setAssemblyId={setAssemblyId}
|
|
48
|
+
setHasAnnotation={setHasAnnotation}
|
|
49
|
+
onAssemblyIdChange={onAssemblyIdChange}
|
|
50
|
+
/>
|
|
51
|
+
);
|
|
52
|
+
cy.get('input').type('GCA_000002945.3');
|
|
53
|
+
cy.wait('@getAssemblyInfo');
|
|
54
|
+
|
|
55
|
+
cy.wait('@getPairedAssemblyInfo');
|
|
56
|
+
cy.contains('Equivalent assembly GCF_000002945.3 has annotation').should('exist');
|
|
57
|
+
});
|
|
58
|
+
it('handles NCBI being down displaying the right error', () => {
|
|
59
|
+
cy.intercept('GET', 'https://api.ncbi.nlm.nih.gov/datasets/v2alpha/genome/accession/GCA_000002945.3/dataset_report*', {
|
|
60
|
+
statusCode: 500,
|
|
61
|
+
body: {}
|
|
62
|
+
}).as('getAssemblyInfo');
|
|
63
|
+
|
|
64
|
+
cy.mount(
|
|
65
|
+
<AssemblyIdSelector setAssemblyId={cy.spy()} setHasAnnotation={cy.spy()} onAssemblyIdChange={cy.spy()} />
|
|
66
|
+
);
|
|
67
|
+
cy.get('input').type('GCA_000002945.3', { delay: 0});
|
|
68
|
+
cy.wait('@getAssemblyInfo');
|
|
69
|
+
cy.contains('Could not connect to server for validation.').should('exist');
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
describe('<SpeciesPicker />', () => {
|
|
74
|
+
it('handles NCBI being down displaying the right error', () => {
|
|
75
|
+
const setSpecies = cy.spy().as('setSpecies');
|
|
76
|
+
const setAssemblyId = cy.spy().as('setAssemblyId');
|
|
77
|
+
|
|
78
|
+
cy.mount(
|
|
79
|
+
<SpeciesPicker setSpecies={setSpecies} setAssemblyId={setAssemblyId} />
|
|
80
|
+
);
|
|
81
|
+
cy.intercept('GET', 'https://api.ncbi.nlm.nih.gov/datasets/v2alpha/taxonomy/taxon_suggest/**', {
|
|
82
|
+
statusCode: 500,
|
|
83
|
+
body: {}
|
|
84
|
+
}).as('getTaxonSuggest');
|
|
85
|
+
|
|
86
|
+
cy.get('input').type('Saccharomyces cerevisiae', { delay: 0});
|
|
87
|
+
cy.wait('@getTaxonSuggest');
|
|
88
|
+
cy.contains('Could not retrieve data').should('exist');
|
|
89
|
+
// cy.get('li').contains('Saccharomyces cerevisiae - 559292').click();
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
describe('<SequenceAccessionPicker />', () => {
|
|
94
|
+
it('handles NCBI being down displaying the right error', () => {
|
|
95
|
+
const setSequenceAccession = cy.spy().as('setSequenceAccession');
|
|
96
|
+
const assemblyAccession = 'GCA_000002945.3';
|
|
97
|
+
|
|
98
|
+
cy.intercept('GET', 'https://api.ncbi.nlm.nih.gov/datasets/v2alpha/genome/accession/GCA_000002945.3/sequence_reports*', {
|
|
99
|
+
statusCode: 500,
|
|
100
|
+
body: {}
|
|
101
|
+
}).as('getSequenceReports');
|
|
102
|
+
|
|
103
|
+
cy.mount(
|
|
104
|
+
<SequenceAccessionPicker assemblyAccession={assemblyAccession} sequenceAccession={''} setSequenceAccession={setSequenceAccession} />
|
|
105
|
+
);
|
|
106
|
+
cy.contains('Could not load chromosomes').should('exist');
|
|
107
|
+
});
|
|
108
|
+
it('displays the chromosomes', () => {
|
|
109
|
+
const setSequenceAccession = cy.spy().as('setSequenceAccession');
|
|
110
|
+
const assemblyAccession = 'GCA_000002945.3';
|
|
111
|
+
|
|
112
|
+
cy.intercept('GET', 'https://api.ncbi.nlm.nih.gov/datasets/v2alpha/genome/accession/GCA_000002945.3/sequence_reports*', {
|
|
113
|
+
statusCode: 200,
|
|
114
|
+
body: { reports: [{ chr_name: 'chr1', refseq_accession: 'NC_000001.10' }, { chr_name: 'chr2', refseq_accession: 'NC_000002.11' }] }
|
|
115
|
+
}).as('getSequenceReports');
|
|
116
|
+
|
|
117
|
+
cy.mount(
|
|
118
|
+
<SequenceAccessionPicker assemblyAccession={assemblyAccession} setSequenceAccession={setSequenceAccession} />
|
|
119
|
+
);
|
|
120
|
+
cy.wait('@getSequenceReports');
|
|
121
|
+
cy.get('label').siblings('div').first().click();
|
|
122
|
+
cy.contains('chr1 - NC_000001.10').should('exist');
|
|
123
|
+
cy.contains('chr2 - NC_000002.11').should('exist');
|
|
124
|
+
cy.get('div[role="presentation"]').contains('chr1 - NC_000001.10').click();
|
|
125
|
+
// Check that the spy was called with the expected value
|
|
126
|
+
cy.get('@setSequenceAccession').should('have.been.calledWith', 'NC_000001.10');
|
|
127
|
+
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
|