@opencloning/ui 1.7.3 → 1.9.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.
Files changed (54) hide show
  1. package/CHANGELOG.md +102 -0
  2. package/package.json +20 -14
  3. package/src/components/AppAlerts.jsx +7 -7
  4. package/src/components/CloningHistory.jsx +2 -0
  5. package/src/components/CloningSpeedDial.jsx +102 -0
  6. package/src/components/DownloadCloningStrategyDialog.jsx +2 -2
  7. package/src/components/LoadCloningHistoryWrapper.jsx +2 -2
  8. package/src/components/MainSequenceEditor.jsx +41 -34
  9. package/src/components/NetworkNode.jsx +35 -33
  10. package/src/components/OpenCloning.jsx +4 -3
  11. package/src/components/SequenceViewer.cy.jsx +27 -0
  12. package/src/components/SequenceViewer.jsx +211 -0
  13. package/src/components/annotation/AnnotationChangedAlert.jsx +26 -0
  14. package/src/components/annotation/useUpdateAnnotationInMainSequence.js +2 -2
  15. package/src/components/assembler/Assembler.jsx +3 -3
  16. package/src/components/domesticate/DomesticateDialog.jsx +274 -0
  17. package/src/components/form/GetRequestMultiSelect.jsx +0 -1
  18. package/src/components/form/PostRequestSelect.jsx +0 -1
  19. package/src/components/form/QuerySelect.jsx +128 -0
  20. package/src/components/form/QueryStatusWrapper.jsx +28 -0
  21. package/src/components/form/SubmitToDatabaseDialog.jsx +63 -58
  22. package/src/components/form/TextFieldQueryValidated.jsx +93 -0
  23. package/src/components/index.js +4 -0
  24. package/src/components/navigation/FeedbackDialog.jsx +1 -1
  25. package/src/components/navigation/MainAppBar.jsx +5 -5
  26. package/src/components/primers/import_primers/ImportPrimersButton.jsx +2 -2
  27. package/src/components/primers/import_primers/PrimerDatabaseImportForm.jsx +6 -3
  28. package/src/components/sources/FinishedSource.jsx +3 -0
  29. package/src/components/sources/MultipleOutputsSelector.cy.jsx +95 -0
  30. package/src/components/sources/MultipleOutputsSelector.jsx +32 -19
  31. package/src/components/sources/RecombinaseList.cy.jsx +1 -1
  32. package/src/components/sources/RecombinaseList.jsx +1 -1
  33. package/src/components/sources/SourceAssembly.jsx +36 -2
  34. package/src/components/sources/SourceRepositoryId.jsx +0 -1
  35. package/src/components/sources/SourceTypeSelector.jsx +1 -1
  36. package/src/components/verification/ImportSequencingFilesInput.jsx +17 -0
  37. package/src/components/verification/LoadFromDatabaseButton.jsx +17 -10
  38. package/src/components/verification/VerificationFileDialog.jsx +16 -22
  39. package/src/components/verification/index.js +1 -0
  40. package/src/config/defaultMainEditorProps.js +1 -0
  41. package/src/hooks/useAlerts.js +3 -4
  42. package/src/hooks/useBackendAPI.js +5 -2
  43. package/src/hooks/useCloningAlerts.js +7 -0
  44. package/src/hooks/useDebouncedSearchQuery.js +42 -0
  45. package/src/hooks/useHttpClient.js +7 -5
  46. package/src/hooks/useLoadDatabaseFile.js +6 -2
  47. package/src/hooks/useSequencingAlignment.js +26 -0
  48. package/src/hooks/useSnapgeneHistoryEndpoint.js +3 -3
  49. package/src/hooks/useStoreEditor.js +10 -68
  50. package/src/hooks/useUrlParamsLoader.js +2 -2
  51. package/src/hooks/useValidateState.js +3 -3
  52. package/src/index.css +3 -11
  53. package/src/providers/ConfigProvider.jsx +1 -0
  54. package/src/version.js +1 -1
@@ -2,8 +2,7 @@ import { useStore } from 'react-redux';
2
2
  import { updateEditor, addAlignment } from '@teselagen/ove';
3
3
  import { getPCRPrimers } from '@opencloning/store/cloning_utils';
4
4
  import { getTeselaJsonFromBase64 } from '@opencloning/utils/readNwrite';
5
- import { findRotation, syncChromatogramDataWithAlignment } from '@opencloning/utils/sequenceManipulation';
6
- import { getReverseComplementSequenceAndAnnotations, getReverseComplementSequenceString, rotateSequenceDataToPosition } from '@teselagen/sequence-utils';
5
+ import { buildAlignmentTrack, buildReferenceTrack, buildAlignmentConfig, removePanelFromShown, updatePanelsShownWithAlignment } from '@opencloning/utils/alignmentUtils';
7
6
 
8
7
  export default function useStoreEditor() {
9
8
  const store = useStore();
@@ -27,74 +26,17 @@ export default function useStoreEditor() {
27
26
  const pcrPrimers = getPCRPrimers(cloning, id);
28
27
  const alignmentFiles = cloning.files.filter((e) => e.sequence_id === id && e.file_type === 'Sequencing file');
29
28
  let { panelsShown } = store.getState().VectorEditor.mainEditor;
30
- panelsShown = [[...panelsShown[0].filter((p) => p.id !== 'simpleAlignment')]]
29
+ panelsShown = removePanelFromShown(panelsShown, 'simpleAlignment');
31
30
 
32
31
  if (alignmentFiles.length > 0) {
33
- addAlignment(store, {
34
- id: 'simpleAlignment',
35
- alignmentType: 'Sequencing alignment',
36
- name: `Seq. ${id}`,
37
- // set the visibilities of the annotations you'd like to see
38
- alignmentAnnotationVisibility: {
39
- features: true,
40
- parts: true,
41
- translations: true,
42
- },
43
- alignmentTracks: [
44
- {
45
- sequenceData,
46
- alignmentData: {
47
- // the alignmentData just needs the sequence < TODO this has to be changed to be the largest ---
48
- sequence: alignmentFiles[0].alignment[0],
49
- name: sequenceData.name
50
- },
51
- },
52
- ...await Promise.all(alignmentFiles.map(async (aln) => {
53
- const fileContent = await getTeselaJsonFromBase64(sessionStorage.getItem(`verification-${id}-${aln.file_name}`), aln.file_name);
54
- let chromatogramData = fileContent.chromatogramData;
55
- let alignmentSequenceData = {
56
- name: aln.file_name,
57
- sequence: aln.alignment[1].replaceAll('-', ''),
58
- };
59
- if (chromatogramData) {
60
- chromatogramData = syncChromatogramDataWithAlignment(chromatogramData, aln.alignment[1]);
61
- }
62
- if (fileContent.features && fileContent.features.length > 0) {
63
- alignmentSequenceData = fileContent;
64
- const alignmentSequence = aln.alignment[1].replaceAll('-', '');
65
- let rotation = findRotation(fileContent.sequence, alignmentSequence);
66
- // If the rotation is -1, it may be reverse complemented
67
- const reverseComplemented = rotation === -1;
68
- if (reverseComplemented) {
69
- rotation = findRotation(fileContent.sequence, getReverseComplementSequenceString(alignmentSequence));
70
- alignmentSequenceData = getReverseComplementSequenceAndAnnotations(fileContent);
71
- }
72
- if (rotation !== -1 && rotation !== 0) {
73
- rotation = reverseComplemented ? fileContent.sequence.length - rotation : rotation;
74
- alignmentSequenceData = rotateSequenceDataToPosition(alignmentSequenceData, rotation);
75
- }
76
- }
77
- return {
78
- sequenceData: {...alignmentSequenceData, name: aln.file_name},
79
- alignmentData: {
80
- sequence: aln.alignment[1],
81
- name: aln.file_name
82
- },
83
- chromatogramData,
84
- };
85
- })),
86
- ],
87
- });
88
- panelsShown = [[
89
- ...panelsShown[0].filter((p) => p.id !== 'simpleAlignment'),
90
- {
91
- id: 'simpleAlignment',
92
- type: 'alignment',
93
- name: 'Alignments',
94
- active: true,
95
- isFullscreen: false,
96
- },
97
- ]];
32
+ const referenceTrack = buildReferenceTrack(sequenceData, alignmentFiles[0].alignment[0]);
33
+ const otherTracks = await Promise.all(alignmentFiles.map(async (aln) => {
34
+ const fileContent = await getTeselaJsonFromBase64(sessionStorage.getItem(`verification-${id}-${aln.file_name}`), aln.file_name);
35
+ return buildAlignmentTrack(fileContent, aln);
36
+ }));
37
+ const alignmentConfig = buildAlignmentConfig(id, sequenceData, [referenceTrack, ...otherTracks]);
38
+ addAlignment(store, alignmentConfig);
39
+ panelsShown = updatePanelsShownWithAlignment(panelsShown);
98
40
  }
99
41
  sequenceData.primers = sequenceData.primers.concat([...pcrPrimers]);
100
42
  updateEditor(store, editorName, { sequenceData, selectionLayer, panelsShown, sequenceDataHistory: {} });
@@ -3,7 +3,7 @@ import { useDispatch } from 'react-redux';
3
3
  import { cloningActions } from '@opencloning/store/cloning';
4
4
  import useDatabase from './useDatabase';
5
5
  import useLoadDatabaseFile from './useLoadDatabaseFile';
6
- import useAlerts from './useAlerts';
6
+ import useCloningAlerts from './useCloningAlerts';
7
7
  import useHttpClient from './useHttpClient';
8
8
  import useValidateState from './useValidateState';
9
9
  import { formatSequenceLocationString, getUrlParameters } from '@opencloning/utils/other';
@@ -18,7 +18,7 @@ const { setState: setCloningState, updateSource } = cloningActions;
18
18
  export default function useUrlParamsLoader() {
19
19
  const dispatch = useDispatch();
20
20
  const database = useDatabase();
21
- const { addAlert } = useAlerts();
21
+ const { addAlert } = useCloningAlerts();
22
22
  const setHistoryFileError = (e) => addAlert({ message: e, severity: 'error' });
23
23
  const { loadDatabaseFile } = useLoadDatabaseFile({ source: { id: 1 }, sendPostRequest: null, setHistoryFileError });
24
24
  const validateState = useValidateState();
@@ -1,11 +1,11 @@
1
1
  import React from 'react';
2
- import useAlerts from './useAlerts';
2
+ import useCloningAlerts from './useCloningAlerts';
3
3
  import useBackendRoute from './useBackendRoute';
4
4
  import useHttpClient from './useHttpClient';
5
5
 
6
6
  export default function useValidateState() {
7
7
  const backendRoute = useBackendRoute();
8
- const { addAlert } = useAlerts();
8
+ const { addAlert } = useCloningAlerts();
9
9
  const httpClient = useHttpClient();
10
10
 
11
11
  const validateState = React.useCallback(async (newState) => {
@@ -37,7 +37,7 @@ export default function useValidateState() {
37
37
  }
38
38
  return newState;
39
39
  }
40
- }, [addAlert, backendRoute]);
40
+ }, [addAlert, backendRoute, httpClient]);
41
41
 
42
42
  return validateState;
43
43
  }
package/src/index.css CHANGED
@@ -7,15 +7,6 @@ button {
7
7
  border-color: rgb(25, 118, 210);
8
8
  }
9
9
 
10
- ul.hidden-ancestors {
11
- display: none;
12
- }
13
-
14
- /* So that the eye icon is visible */
15
- li.hidden-ancestors {
16
- margin-bottom: 30px;
17
- }
18
-
19
10
  .app-container {
20
11
  display: flex;
21
12
  flex-direction: column;
@@ -288,14 +279,15 @@ div.MuiPaper-root[role=alert] {
288
279
  }
289
280
 
290
281
  div#global-error-message-wrapper {
291
- position: fixed;
282
+ position: relative;
292
283
  top: 0;
293
284
  z-index: 999;
294
285
  max-width: 25em;
295
286
  }
296
287
 
297
288
  div#global-error-message-wrapper > div {
298
- margin: 10px;
289
+ margin-left: 10px;
290
+ margin-bottom: 10px;
299
291
  /* Allow line breaks in very long strings only when necessary */
300
292
  word-break: break-word;
301
293
  }
@@ -33,6 +33,7 @@ export function ConfigProvider({ config, children }) {
33
33
  * - showAppBar: boolean
34
34
  * - enableAssembler: boolean
35
35
  * - enablePlannotate: boolean
36
+ * - requiresBackendAuth: boolean
36
37
  * - noExternalRequests: boolean
37
38
  * - database: string | null
38
39
  *
package/src/version.js CHANGED
@@ -1,2 +1,2 @@
1
1
  // Version placeholder - replaced at publish time via prepack script
2
- export const version = "1.7.3";
2
+ export const version = "1.9.0";